1. 首先用 waveOutOpen 获得 Windows 混音器的句柄。
2. 再初始化一个 Wave Header, 并用 waveOutPrepareHeader
3. 接着用 waveOutWrite 输出这个 Wave Header。
4. 等待播放完成后用 waveOutUnprepareHeader 。
5. 最后调用 waveOutClose 来关闭最开始获得的句柄。
waveOutPrepareHeader 和 waveOutUnprepareHeader 的意思有点像“锁定”。就是只要 Prepare 了, 你就不能改动了, 特别地, 你不能释放已锁定 Wave Header 的内存, 否则会引起程序崩溃。内存指 Wave Header 的 lpData 指向的一块内存区域, 这块内存区域在播放完成之前不能释放。我们在这个程序里简单地通过 waveOutUnprepareHeader 的返回值来判断是否播放完成。在较为复杂的程序中, 我们可以通过回调函数来判断何时播放完毕。回调函数可以在 waveOutOpen 的 dwCallback 参数中设置
#define BUFF_LEN 4096
void PlayPCM()
{
WAVEFORMATEX sFormat;
WAVEFORMATEX *lpFormat;
char* *lpData1, *lpData2;
sFormat.wFormatTag = 1;
sFormat.nChannels = 1;
sFormat.nSamplesPerSec = 8000;
sFormat.wBitsPerSample = 16;
sFormat.nAvgBytesPerSec = 8000*2;
sFormat.nBlockAlign = 2;
sFormat.cbSize = sizeof(WAVEFORMATEX); //
lpFormat = &sFormat;
DWORD dwDataSize1, dwDataSize2;
lpData1 = new char[BUFF_LEN];
lpData2 = new char[BUFF_LEN];
int reads, sum;
//此处填充两个缓冲, 本例是从网络收数据
if (-1 == SockInit())
{
AfxMessageBox("sock init error!");
return;
}
int len = sizeof(cliaddr);
clifd = accept(m_socket,(struct sockaddr*)&cliaddr,&len);
if (clifd < 0)
{
return;
}
sum = 0;
while(sum < BUFF_LEN - 320)
{
reads = recv(clifd, lpData1+sum, 320, 0);
sum += reads;
}
dwDataSize1 = sum;
sum = 0;
while(sum < BUFF_LEN - 320)
{
reads = recv(clifd, lpData2+sum, 320, 0);
sum += reads;
}
dwDataSize2 = sum;
//test net work
WAVEOUTCAPS pwoc;
if(waveOutGetDevCaps(WAVE_MAPPER, &pwoc, sizeof(WAVEOUTCAPS))!=0)
{
return ;
}
HWAVEOUT hWaveOut;
if(waveOutOpen(&hWaveOut, WAVE_MAPPER, lpFormat, (DWORD)waveOutProc, NULL, CALLBACK_FUNCTION)!=0)
{
return ;
}
LPWAVEHDR lpWaveHdr1, lpWaveHdr2;
lpWaveHdr1 = new WAVEHDR;
lpWaveHdr2 = new WAVEHDR;
lpWaveHdr1->lpData = lpData1;
lpWaveHdr1->dwBufferLength = dwDataSize1;
lpWaveHdr1->dwFlags = 0L;
lpWaveHdr1->dwLoops = 0L;
lpWaveHdr2->lpData = lpData2;
lpWaveHdr2->dwBufferLength = dwDataSize2;
lpWaveHdr2->dwFlags = 0L;
lpWaveHdr2->dwLoops = 0L;
waveOutPrepareHeader(hWaveOut, lpWaveHdr1, sizeof(WAVEHDR));
waveOutPrepareHeader(hWaveOut, lpWaveHdr2, sizeof(WAVEHDR));
waveOutWrite(hWaveOut, lpWaveHdr1, sizeof(WAVEHDR));
waveOutWrite(hWaveOut, lpWaveHdr2, sizeof(WAVEHDR));
}
void CALLBACK waveOutProc( HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 )
{
if(uMsg == WOM_DONE)
{
LPWAVEHDR pWaveHeader = (LPWAVEHDR)dwParam1;
waveOutUnprepareHeader( hwo, pWaveHeader, sizeof(WAVEHDR));
//从网络上取数据
int count = 0, reads = 0;
while(count < BUFF_LEN - 320)
{
reads = recv(clifd, pWaveHeader->lpData+count, 320, 0);
count += reads;
}
pWaveHeader->dwBufferLength = count;
waveOutPrepareHeader( hwo, pWaveHeader, sizeof(WAVEHDR));
waveOutWrite( hwo, pWaveHeader, sizeof(WAVEHDR) );
}
return ;
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jifengszf/archive/2009/07/08/4330402.aspx