尝试使用waveOutWrite()实现流畅的音频播放时遇到问题。我的数据包括许多从相机获取的adpcmdata块,在解码每个adpcm块后我使用waveOutWrite()播放它。第一个块是成功播放的(至少我能听到)但是当我为下一个块播放这些块之间存在间隙时我有问题。我试着在使用waveOutWrite()之后调用sleep(),但它不行。在这种情况下,有人能告诉我如何顺利吗?我播放音频的方式有什么问题吗?
for (i = 0, i < MaxBlockData, i++)
BYTE * pcmBuff = new BYTE[length*8];
memset(pcmBuff, 0, length*8);
G726 g726;
int pcmDataSize = 0;
g726.SetRate(g726.Rate32kBits);
g726.SetLaw(g726.PCM16);
pcmDataSize = g726.Decode(pcmBuff, adpcmData[i], 0, length*8); /decode adcmData PCM 16
if(pcmDataSize > 0)
{
int sampleRate = 8000;
CHAR* waveIn = new CHAR[pcmDataSize];
HWAVEIN hWaveIn;
WAVEHDR WaveInHdr;
MMRESULT result;
HWAVEOUT hWaveOut;
WAVEFORMATEX pFormat;
pFormat.wFormatTag = WAVE_FORMAT_PCM;
pFormat.nChannels = 1;
pFormat.nSamplesPerSec = sampleRate;
pFormat.nAvgBytesPerSec = 2 * sampleRate;
pFormat.nBlockAlign = 2;
pFormat.wBitsPerSample = 16;
pFormat.cbSize = 0;
result = waveInOpen(&hWaveIn, WAVE_MAPPER, &pFormat, 0, 0, WAVE_FORMAT_DIRECT);
if(result != MMSYSERR_NOERROR)
{
char fault[256];
waveInGetErrorTextA(result, fault, 256);
MessageBoxA(NULL, fault, "Failed to open waveform input device.", MB_OK | MB_ICONEXCLAMATION);
return;
}
WaveInHdr.lpData = (LPSTR)waveIn;
WaveInHdr.dwBufferLength = pcmDataSize;
WaveInHdr.dwBytesRecorded = 0;
WaveInHdr.dwUser = 0;
WaveInHdr.dwFlags = 0;
WaveInHdr.dwLoops = 0;
waveInPrepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));
memcpy(WaveInHdr.lpData, pcmBuff, pcmDataSize);
if(waveOutOpen(&hWaveOut, WAVE_MAPPER, &pFormat, 0, 0, WAVE_FORMAT_DIRECT))
{
MessageBoxA(NULL, "Failed to replay", NULL, MB_OK | MB_ICONEXCLAMATION );
}
waveOutWrite(hWaveOut, &WaveInHdr, sizeof(WaveInHdr));
Sleep((pcmDataSize/sampleRate ) * 1000); //Sleep for as long as there was recorded
waveOutUnprepareHeader(hWaveOut, &WaveInHdr, sizeof(WAVEHDR));
waveInUnprepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));
waveInClose(hWaveIn);
waveOutClose(hWaveOut);
WaveInHdr.lpData = NULL;
delete []waveIn;
}
}
感谢您阅读我的问题。
答案 0 :(得分:1)
我不会这样工作。
当您播放第一个样本时,您无法在下一个样本时睡觉,而应使用双重或多重缓冲以及回调机制。
整体协议如下:
1)从相机或其他任何东西获得第一块
2)从相机或其他任何东西获得第二块
3)在没有任何等待的情况下写入第一个块然后第二个块
然后创建一个循环,等待来自回调的信号,并在接收信号时写入下一个捕获的块。
答案 1 :(得分:0)
要使用waveOut *系列顺利播放音频,请打开设备,分配缓冲区并继续向设备发送缓冲区,以保持积压的数据。在代码中Sleep
,您应该准备并向设备写入新数据,同时检查播放的缓冲区(WHDR_DONE
标志设置为表示驱动程序不再存在使用缓冲区,应用程序收到它。)