两个缓冲切换时会出现咔咔的声音,网上的解决办法都很含糊,以下是我研究出的正确的方法...播放一个WAV文件.可以帮助正在做网络语音存在困惑的人... 网络语音最好用两个线程一个放音一个接收数据,接收的数据放进一个队列中.

#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>

#include "mmsystem.h"
#pragma comment(lib,"winmm.lib")
#define Buf_Size 44100*30

HWAVEOUT m_hWaveOut;
WAVEFORMATEX m_waveformat; //音频格式
WAVEHDR m_header[3];
char m_Buf[Buf_Size*3]; //缓冲区
int m_CurBufIdx;
FILE *fp;

void CALLBACK waveOutProc( HWAVEOUT hwo,
UINT uMsg,
DWORD_PTR dwInstance,
DWORD_PTR dwParam1,
DWORD_PTR dwParam2 );

void InitFile()
{
fp = fopen("C:\\Users\\Administrator\\Desktop\\99.wav","rb");
}
void Play()
{
m_waveformat.wFormatTag = WAVE_FORMAT_PCM;
m_waveformat.nChannels = 2; //声道数
m_waveformat.nSamplesPerSec = 44100; //If wFormatTag = WAVE_FORMAT_PCM, then common values for nSamplesPerSec are 8.0 kHz, 11.025 kHz, 22.05 kHz, and 44.1 kHz.
m_waveformat.nAvgBytesPerSec = 44100*16*2/8; //
m_waveformat.nBlockAlign = 4; //对齐If wFormatTag = WAVE_FORMAT_PCM, set nBlockAlign to (nChannels*wBitsPerSample)/8
m_waveformat.wBitsPerSample = 16; //采样位数
m_waveformat.cbSize = 0;

if( ::waveOutGetNumDevs() <= 0 )
{
::MessageBox( NULL, _T("没有可用的音频设备!"), _T("错误"), MB_OK | MB_ICONERROR );
return;
}
if( MMSYSERR_NOERROR != ::waveOutOpen( &m_hWaveOut, WAVE_MAPPER, &m_waveformat, (DWORD_PTR)waveOutProc, 0L, CALLBACK_FUNCTION ) )
{
::MessageBox( NULL, _T("不能打开音频设备!"), _T("错误"), MB_OK | MB_ICONERROR );
return;
}
//::waveOutSetVolume( m_hWaveOut, 0xFFFFFFFF ); //最大化音量


::memset(&m_header, 0 , sizeof(WAVEHDR));
//char tmp_Buf[8000/5] = {0};


//*
for(int i=0;i<3;i++)
{
::memset(&m_header[i], 0, sizeof(WAVEHDR) );
m_header[i].lpData = &m_Buf[Buf_Size*i]; //设置缓冲区
m_header[i].dwBufferLength = fread( &m_Buf[Buf_Size*i], sizeof(char), Buf_Size, fp ); //设置播放字节长度
::waveOutPrepareHeader( m_hWaveOut, &m_header[i], sizeof(WAVEHDR) ); //准备3个缓冲区
::waveOutWrite( m_hWaveOut, &m_header[i], sizeof(WAVEHDR) ); //写入3个缓冲区
}
m_CurBufIdx=0; //当前缓冲区索引


}

int _tmain(int argc, _TCHAR* argv[])
{
InitFile();
Play();

system("pause");
return 0;
}

// 放音回调函数
void CALLBACK waveOutProc( HWAVEOUT hwo,
UINT uMsg,
DWORD_PTR dwInstance,
DWORD_PTR dwParam1,
DWORD_PTR dwParam2 )
{
//WAVEHDR* pHdr = (PWAVEHDR)dwParam1; // 该参数由系统自动返回
LPWAVEHDR lpHdr = (LPWAVEHDR)dwParam1;
if( lpHdr == NULL ) return ;

if (WOM_DONE == uMsg)
{
::waveOutUnprepareHeader(m_hWaveOut, lpHdr, sizeof(WAVEHDR));
::memset(&m_header[m_CurBufIdx], 0 , sizeof(WAVEHDR));

//fseek(fp,10000L,SEEK_SET);
m_header[m_CurBufIdx].lpData = &m_Buf[Buf_Size*m_CurBufIdx];
m_header[m_CurBufIdx].dwBufferLength = fread( &m_Buf[Buf_Size*m_CurBufIdx], sizeof(char), Buf_Size, fp);

//char *p=&m_Buf[Buf_Size*m_CurBufIdx];
//for(int i=0;i<Buf_Size;i++)
//p[i] = rand()*255;


if( m_header[m_CurBufIdx].dwBufferLength <= 0 )
{
::waveOutReset( m_hWaveOut );
::waveOutClose( m_hWaveOut );
//fseek( fp, 0, SEEK_SET );
}
// ::Sleep(200);
::waveOutPrepareHeader( m_hWaveOut, &m_header[m_CurBufIdx], sizeof(WAVEHDR) );
::waveOutWrite( m_hWaveOut, &m_header[m_CurBufIdx], sizeof(WAVEHDR) );
//*/

m_CurBufIdx++;
if( m_CurBufIdx == 3 ) m_CurBufIdx = 0;

}
}

posted on 2011-09-18 23:40  aricgreen  阅读(1490)  评论(2)    收藏  举报