winows,播放 PCM音频, 双缓冲

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

你可能感兴趣的:(winows,播放 PCM音频, 双缓冲)