消息 "MM_WOM_DONE" 未被调用
Message "MM_WOM_DONE" is not called
我有一个问题:音频块播放完毕后我没有收到 "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 毫秒)。 "Sine wave stopped playing!" 消息也永远不会出现在控制台中,这意味着 WndProc 函数永远不会用 "MM_WOM_DONE" 消息调用。如果我处理 "initSound" 函数中的所有内容,即使写入和关闭 waveOut 之间的延迟大得多(超过一秒),正弦波最终也不会播放白噪声。
Remy Lebeau 解决此问题的功劳。我犯的错误是将 wave header 和 wave out header 存储在堆栈而不是堆中。这导致出现噪音,因为数据被覆盖并且声卡开始读取无效数据。 Wave out header 也可能丢失 or/and 被覆盖,所以我无法正确调用 MM_WOM_DONE 消息。所有这一切都因为在函数外声明变量而简单地解决了。就像这样:
HWAVEOUT hWaveOut;
WAVEFORMATEX wfx;
DWORD size = 8192;
WAVEHDR header;
void initSound(HWND hwnd) {
/* Body of function */
}
因此,如果您遇到此问题,请确保与 waveout 相关的变量足够长。
我有一个问题:音频块播放完毕后我没有收到 "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 毫秒)。 "Sine wave stopped playing!" 消息也永远不会出现在控制台中,这意味着 WndProc 函数永远不会用 "MM_WOM_DONE" 消息调用。如果我处理 "initSound" 函数中的所有内容,即使写入和关闭 waveOut 之间的延迟大得多(超过一秒),正弦波最终也不会播放白噪声。
Remy Lebeau 解决此问题的功劳。我犯的错误是将 wave header 和 wave out header 存储在堆栈而不是堆中。这导致出现噪音,因为数据被覆盖并且声卡开始读取无效数据。 Wave out header 也可能丢失 or/and 被覆盖,所以我无法正确调用 MM_WOM_DONE 消息。所有这一切都因为在函数外声明变量而简单地解决了。就像这样:
HWAVEOUT hWaveOut;
WAVEFORMATEX wfx;
DWORD size = 8192;
WAVEHDR header;
void initSound(HWND hwnd) {
/* Body of function */
}
因此,如果您遇到此问题,请确保与 waveout 相关的变量足够长。