Сообщение "MM_WOM_DONE" не вызывается - PullRequest
0 голосов
/ 08 января 2020

У меня проблема: я не получаю «MM_WOM_DONE» после завершения воспроизведения аудиоблока.

Код, относящийся к звуку:

void initSound(HWND hwnd) {
    HWAVEOUT hWaveOut;
    WAVEFORMATEX wfx;

    wfx.nSamplesPerSec = 44100; /* sample rate */
    wfx.wBitsPerSample = 8; /* sample size */
    wfx.nChannels = 1; /* channels*/

    wfx.cbSize = 0;
    wfx.wFormatTag = WAVE_FORMAT_PCM;
    wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
    wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;

    if(waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfx, (DWORD)hwnd, 0, CALLBACK_WINDOW) != MMSYSERR_NOERROR) {
        printf("Wave out can't be opened!\n");
        ExitProcess(1);
    } else {
        printf("Wave out is now open!\n");
    }

    /* Building a block */
    DWORD size = 8192;
    int frequency = 523; // C note
    int volume = 20;
    float sinMul = 3.1415 * frequency / (wfx.nSamplesPerSec);
    unsigned char blockArray[size];
    for (int i = 0; i < size; i++) {
        blockArray[i] = 128 + (signed char)(sin(i * sinMul) * volume);
    }

    WAVEHDR header;
    ZeroMemory(&header, sizeof(WAVEHDR));
    header.dwBufferLength = size;
    header.lpData = (LPSTR)&blockArray;
    printf("Block was created!\n");

    /* Prepearing header */
    printf("Prepearing header for wave out...\n");
    waveOutPrepareHeader(hWaveOut, &header, sizeof(WAVEHDR));

    /* Playing a block */
    printf("Writing sound to wave out...\n");
    waveOutWrite(hWaveOut, &header, sizeof(WAVEHDR));
    printf("Waiting sound for finishing playing...\n");
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch(msg) {
        case WM_CREATE:
            initSound(hwnd);
        break;
        case MM_WOM_DONE:
            printf("Sine wave stopped playing!");
            waveOutUnprepareHeader((HWAVEOUT)wParam, (LPWAVEHDR)lParam, sizeof(WAVEHDR));
            waveOutClose((HWAVEOUT)wParam);
        break;
    }
}

Вывод на консоль:

Wave out is now open!
Block was created!
Prepearing header for wave out...
Writing sound to wave out...
Waiting sound for finishing playing...

Синусоида играет хорошо и правильно, но как только она заканчивает играть, короткий короткий белый шум начинает воспроизводиться в течение короткого промежутка времени (почти 100-200 мс). Также "Синусоида перестала играть!" сообщение никогда не отображается в консоли, что означает, что функция WndPro c никогда не вызывается с сообщением "MM_WOM_DONE". Если я обрабатываю все в функции «initSound», синусоида воспроизводится без белого шума в конце, даже когда задержка между записью и закрытием waveOut намного больше (более одной секунды).

1 Ответ

1 голос
/ 10 января 2020

Кредиты для решения этой проблемы Реми Лебо. Ошибка, которую я сделал, заключается в сохранении заголовка волны и заголовка волны в стеке, а не в куче. Это привело к появлению шума, поскольку данные были переопределены, и звуковая карта начала считывать недействительные данные. Вероятно, заголовок Wave Out также был потерян или перезаписан, поэтому я не смог правильно вызвать сообщение MM_WOM_DONE. Все это было решено просто для объявления переменных вне функции. Точно так же:

HWAVEOUT hWaveOut;
WAVEFORMATEX wfx;
DWORD size = 8192;
WAVEHDR header;

void initSound(HWND hwnd) {
    /* Body of function */
}

Так что в случае, если у вас возникла эта проблема, убедитесь, что ваши переменные, связанные с волнами, живут достаточно долго.

...