|
|
发表于 2007-4-23 11:25:36
|
显示全部楼层
头文件
// VocPlay.h: interface for the CVocPlay class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_VOCPLAY_H__2B681B64_C240_4632_A7DA_16D0E56E89A5__INCLUDED_)
#define AFX_VOCPLAY_H__2B681B64_C240_4632_A7DA_16D0E56E89A5__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#pragma comment( lib, "Winmm.lib" )
#include <mmsystem.h>
#include <mmreg.h>
#include <msacm.h>
//#define PCM_SAMPLERTE 8000
#define VOC_NET_FORMAT_MP3 1001
class CVocPlay : public CObject
{////多路语音叠加播放
public:
CVocPlay(int iID);
virtual ~CVocPlay();
public:
BOOL Start();
BOOL End();
BOOL PutNetVoc( WAVEHDR * pWave, int iID );////save to ptrlist, play voc
protected:
int m_iSenderID; ////区分不同节点的数据
BYTE * m_pMp3WaveBuff;
CPtrList m_listRecvVoc;
WAVEFORMATEX m_wfx;
CCriticalSection m_csRecvVocList; ////语音列表的多线程控制
BOOL m_bPlayVoc;////将收到的语音数据是否送放音设备。每一路单独控制。
BOOL m_bHaveVoc;////1 语音数据放完,回调函数中不能自动播放语音。需要外部送语音
BOOL PlayDeviceOpen();
void PlayDeviceClose();
static int m_iClassRef;
static HWAVEOUT m_hWavePlay; //放音设备句柄,一直是打开的。
static void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);
BOOL GetNetVoc( WAVEHDR * &pWave );////取网络收到的数据
BOOL WriteBuff2Device(WAVEHDR *pWave);
void CleanVocBuff();////when stop play, call this to clean voc buffer
};
#endif // !defined(AFX_VOCPLAY_H__2B681B64_C240_4632_A7DA_16D0E56E89A5__INCLUDED_)
源文件
// VocPlay.cpp: implementation of the CVocPlay class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "voip.h"
#include "VocPlay.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
HWAVEOUT CVocPlay::m_hWavePlay = NULL;
int CVocPlay::m_iClassRef = 0;
CVocPlay::CVocPlay(int iID)
{
m_iSenderID = iID;
m_wfx.wFormatTag = WAVE_FORMAT_PCM; // simple, uncompressed format
m_wfx.nChannels = 1; // 1 = mono, 2 = stereo
m_wfx.nSamplesPerSec = PCM_SAMPLERTE;
m_wfx.nAvgBytesPerSec = PCM_SAMPLERTE * 2; // = nSamplesPerSec * n.Channels * wBitsPerSample/8
m_wfx.nBlockAlign = 1; // = n.Channels * wBitsPerSample/8
m_wfx.wBitsPerSample = 16; // 16 for high quality, 8 for telephone-grade
m_wfx.cbSize = 0;
m_bHaveVoc = FALSE;
m_pMp3WaveBuff = new BYTE[PCM_SAMPLERTE * 4];
PlayDeviceOpen();
}
CVocPlay::~CVocPlay()
{
delete [] m_pMp3WaveBuff;
PlayDeviceClose();
}
BOOL CVocPlay::Start()
{
m_bPlayVoc = TRUE;
return TRUE;
}
BOOL CVocPlay::End()
{
m_bPlayVoc = FALSE;
PlayDeviceClose();
return TRUE;
}
////save to ptrlist, play voc
BOOL CVocPlay:: PutNetVoc( WAVEHDR * pWave, int iID )
{
WAVEHDR * pWavePlay;
if( iID != m_iSenderID ) return FALSE;
CSingleLock sl(&m_csRecvVocList);
sl.Lock();
m_listRecvVoc.AddTail( pWave );
sl.Unlock();
if( !m_bHaveVoc )
{
if( GetNetVoc( pWavePlay ) )
{
WriteBuff2Device( pWavePlay );
}
}
return TRUE;
}
BOOL CVocPlay:: PlayDeviceOpen()
{
BOOL bRtn;
char szMsg[256];
MMRESULT mmrRtn;
m_iClassRef++;
if( m_hWavePlay != NULL )
{
TRACE( "Client %d Play Wave device already open !\n", m_iSenderID );
return TRUE;
}
mmrRtn = waveOutOpen( &m_hWavePlay, WAVE_MAPPER, &m_wfx, (DWORD)(waveOutProc), (DWORD)this, CALLBACK_FUNCTION);
bRtn = (mmrRtn == MMSYSERR_NOERROR);
if( bRtn )
{
TRACE( "Client %d Play Record Wave device suceess !\n", m_iSenderID );
}
else
{
waveOutGetErrorText( mmrRtn, szMsg, 256);
TRACE( szMsg );
TRACE( " Client %d Play Record Wave device failed !\n", m_iSenderID );
}
return ( bRtn );
}
void CVocPlay:: PlayDeviceClose()
{
m_bPlayVoc = FALSE;
while( m_bHaveVoc )
{
Sleep( 100 );
}
m_iClassRef--;
if( m_iClassRef <= 0 )
{
if( m_hWavePlay != NULL )
{
Sleep( 100 );
waveOutReset(m_hWavePlay);
waveOutClose(m_hWavePlay);
}
m_hWavePlay = NULL;
}
}
BOOL CVocPlay::WriteBuff2Device(WAVEHDR *pWave)
{
char szMsg[256];
MMRESULT mmrRtn = waveOutPrepareHeader( m_hWavePlay, pWave, sizeof(WAVEHDR));
if( mmrRtn != MMSYSERR_NOERROR)
{
waveOutGetErrorText( mmrRtn, szMsg, 256);
TRACE( szMsg );
delete [] pWave;
return FALSE;
}
mmrRtn = waveOutWrite( m_hWavePlay, pWave, sizeof (WAVEHDR)); //填入新的缓冲
if( mmrRtn != MMSYSERR_NOERROR)
{
waveOutGetErrorText( mmrRtn, szMsg, 256);
TRACE( szMsg );
delete [] pWave;
return FALSE;
}
m_bHaveVoc = TRUE;
return TRUE;
}
void CALLBACK CVocPlay::waveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) //放音
{
WAVEHDR * pWave;
CVocPlay * pAudio;
if( uMsg == WOM_DONE )
{
pWave = (WAVEHDR *)dwParam1;
pAudio = (CVocPlay *)pWave->dwUser;
waveOutUnprepareHeader( hwo, (WAVEHDR *)dwParam1, sizeof(WAVEHDR));
delete [] (BYTE *)dwParam1;
if( pAudio->m_bPlayVoc )
{
if( pAudio->GetNetVoc( pWave ) )
{
pAudio->WriteBuff2Device( pWave );
}
else
{
pAudio->m_bHaveVoc = FALSE;
}
}
else
{
pAudio->CleanVocBuff();
pAudio->m_bHaveVoc = FALSE;
}
}
}
BOOL CVocPlay::GetNetVoc( WAVEHDR * &pWave )////取网络收到的数据
{
int iRtn;
BOOL bRtn;
WAVEHDR * pMp3Wave;
bRtn = FALSE;
pWave = NULL;
CSingleLock sl(&m_csRecvVocList);
sl.Lock();
if( m_listRecvVoc.GetCount() > 0 )
{
pMp3Wave = (WAVEHDR *)m_listRecvVoc.RemoveHead();
if( pMp3Wave->dwUser == VOC_NET_FORMAT_MP3 )
{
bRtn = TRUE;
iRtn = lame_decode( (UCHAR *)pMp3Wave->lpData, pMp3Wave->dwBufferLength,
(SHORT *)m_pMp3WaveBuff, (SHORT *)m_pMp3WaveBuff );
if( iRtn > 0 )
{
pWave = (WAVEHDR *) new BYTE[iRtn +sizeof(WAVEHDR)];
pWave->dwFlags = WHDR_DONE;
pWave->dwBufferLength = iRtn;
pWave->dwUser = (DWORD)this;
pWave->lpData = (char *)((BYTE *)pWave + sizeof(WAVEHDR));
CopyMemory( pWave->lpData, m_pMp3WaveBuff, iRtn );
}
}
else
{
TRACE("Recv Unknow net voc format %d \n", pWave->dwUser);
delete [] pMp3Wave;
pWave = NULL;
}
}
sl.Unlock();
return bRtn;
}
void CVocPlay::CleanVocBuff()
{
void * p;
CSingleLock sl(&m_csRecvVocList);
sl.Lock();
for( ; m_listRecvVoc.GetCount() > 0 ; )
{
p = m_listRecvVoc.RemoveHead();
delete [] p;
}
sl.Unlock();
}
[ 本帖最后由 ganjike 于 2007-4-23 11:27 编辑 ] |
|