From d29dabff75255d578994fab774b4ec3a9415dfe3 Mon Sep 17 00:00:00 2001 From: shimitei Date: Tue, 29 Jun 2021 19:30:00 +0900 Subject: [PATCH] =?utf8?q?[Fix]=20Windows=E7=89=88=E3=81=AE=E5=8A=B9?= =?utf8?q?=E6=9E=9C=E9=9F=B3=E5=86=8D=E7=94=9F=E3=81=AE=E3=82=A8=E3=83=A9?= =?utf8?q?=E3=83=BC=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit waveOutPrepareHeader、waveOutWriteがエラーの場合、再生完了することがないためキューにデータが無限に溜まってしまう。 これらのAPIの戻り値をチェックするようにした。 また、キューに上限を設けてデータが溜まり続けることがないようにした。 --- src/main-win/main-win-sound.cpp | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/main-win/main-win-sound.cpp b/src/main-win/main-win-sound.cpp index af158f8fb..7934aed52 100644 --- a/src/main-win/main-win-sound.cpp +++ b/src/main-win/main-win-sound.cpp @@ -47,6 +47,16 @@ struct sound_res { std::unique_ptr buf; WAVEHDR wh = { 0 }; + /*! + * 再生完了判定 + * @retval true 完了 + * @retval false 再生中 + */ + bool isDone() + { + return (this->hwo == NULL || (this->wh.dwFlags & WHDR_DONE)); + } + void dispose() { if (hwo != NULL) { @@ -67,16 +77,17 @@ std::queue sound_queue; * 効果音の再生と管理キューへの追加. * * @param wf WAVEFORMATEXへのポインタ - * @param buf PCMデータバッファ + * @param buf PCMデータバッファ。使用後にdelete[]すること。 * @param bufsize バッファサイズ * @retval true 正常に処理された * @retval false 処理エラー */ static bool add_sound_queue(const WAVEFORMATEX *wf, BYTE *buf, DWORD bufsize) { + // 再生完了データをキューから削除する while (!sound_queue.empty()) { auto res = sound_queue.front(); - if (res->hwo == NULL || (res->wh.dwFlags & WHDR_DONE)) { + if (res->isDone()) { delete res; sound_queue.pop(); continue; @@ -97,8 +108,23 @@ static bool add_sound_queue(const WAVEFORMATEX *wf, BYTE *buf, DWORD bufsize) wh->dwBufferLength = bufsize; wh->dwFlags = 0; - ::waveOutPrepareHeader(res->hwo, wh, sizeof(WAVEHDR)); - ::waveOutWrite(res->hwo, wh, sizeof(WAVEHDR)); + mr = ::waveOutPrepareHeader(res->hwo, wh, sizeof(WAVEHDR)); + if (mr != MMSYSERR_NOERROR) { + res->dispose(); + return false; + } + + mr = ::waveOutWrite(res->hwo, wh, sizeof(WAVEHDR)); + if (mr != MMSYSERR_NOERROR) { + res->dispose(); + return false; + } + + while (sound_queue.size() >= 16) { + auto res = sound_queue.front(); + delete res; + sound_queue.pop(); + } return true; } -- 2.11.0