简体   繁体   中英

Message "MM_WOM_DONE" is not called

I have a problem: i don't recieve "MM_WOM_DONE" once audio block finishes playing.

Code related to sound:

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;
    }
}

Console output:

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

The sine wave plays well and correct, but once it finishes playing, some short white noise starts playing for short amount of time (nearly 100-200 ms). Also "Sine wave stopped playing!" message never shows up in the console, which means WndProc function is never called with "MM_WOM_DONE" message. If i handle everything in "initSound" function, sine wave plays with no white noise in the end even when delay between writing and closing waveOut is much bigger (more than one second).

Credits for solving this problem to Remy Lebeau. The mistake i did is storing wave header and wave out header in stack rather than in heap. This resulted in noise appearence because data was overriden and sound card started reading invalid data. Wave out header was also probably lost or/and overwritten so i could not get proper call of MM_WOM_DONE message. All this was solved simply for declaring variables outside function. Just like this:

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

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

So in case if you have this problem, be sure your variables related to waveout live long enough.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM