分类: C/C++
2008-03-11 17:54:48
例子程序运行画面:
下面且看我细细道来:
(一)首先定义了一个声音数据“块”
struct CAudioData
{
PBYTE lpdata; //指向语音数据,注意这里内存区域是动态申请释放的
DWORD dwLength;//语音数据长度
}
接下来申明两个循环队列和相关指针。//InBlocks,OutBlocks非别为两个常数
CAudioData m_AudioDataIn[InBlocks],m_AudioDataOut[OutBlocks];
int nAudioIn, nSend, //录入、发送指针
nAudioOut, nReceive;//接收、播放指针
// 对于录音和放音都存在和网络的同步问题,主要靠这些指针进行协调|
|
|
综合以上情况,相关实现如下:
(二)声音的录制与播放
(1)录音处理
void CRecTestDlg::OnMM_WIM_DATA(UINT wParam,LONG lParam)
{
int nextBlock = (nAudioIn+1)% InBlocks;
if(m_AudioDataIn[nextBlock].dwLength!=0)//下一“块”没发走
{ //把PWAVEHDR(即pBUfferi)里的数据接到当前“块”的末尾
m_AudioDataIn[nAudioIn].lpdata
= (PBYTE)realloc (m_AudioDataIn[nAudioIn].lpdata ,
(((PWAVEHDR) lParam)->dwBytesRecorded+m_AudioDataIn[nAudioIn].dwLength)) ;
if (m_AudioDataIn[nAudioIn].lpdata == NULL)
{//...出错处理
return ;
}
CopyMemory ((m_AudioDataIn[nAudioIn].lpdata+m_AudioDataIn[nAudioIn].dwLength),
((PWAVEHDR) lParam)->lpData,
((PWAVEHDR) lParam)->dwBytesRecorded) ;//(*destination,*resource,nLen);
m_AudioDataIn[nAudioIn].dwLength +=((PWAVEHDR) lParam)->dwBytesRecorded;
}
else //把PWAVEHDR(即pBUfferi)里的数据拷贝到下一“块”中
{
nAudioIn = (nAudioIn+1)% InBlocks;
m_AudioDataIn[nAudioIn].lpdata = (PBYTE)realloc
(0,((PWAVEHDR) lParam)->dwBytesRecorded);
CopyMemory(m_AudioDataIn[nAudioIn].lpdata,
((PWAVEHDR) lParam)->lpData,
((PWAVEHDR) lParam)->dwBytesRecorded) ;
m_AudioDataIn[nAudioIn].dwLength =((PWAVEHDR) lParam)->dwBytesRecorded;
}
// Send out a new buffer
waveInAddBuffer (hWaveIn, (PWAVEHDR) lParam, sizeof (WAVEHDR)) ;
return ;
}
(2)放音处理void CRecTestDlg::OnMM_WOM_DONE(UINT wParam,LONG lParam)
{ //释放播放完的缓冲区,并准备新的数据
free(m_AudioDataOut[nAudioOut].lpdata);
m_AudioDataOut[nAudioOut].lpdata = reinterpret_cast(malloc(1));
m_AudioDataOut[nAudioOut].dwLength = 0;
nAudioOut= (nAudioOut+1)%OutBlocks;
((PWAVEHDR)lParam)->lpData = (LPTSTR)m_AudioDataOut[nAudioOut].lpdata ;
((PWAVEHDR)lParam)->dwBufferLength = m_AudioDataOut[nAudioOut].dwLength ;
waveOutPrepareHeader (hWaveOut,(PWAVEHDR)lParam,sizeof(WAVEHDR));
waveOutWrite(hWaveOut,(PWAVEHDR)lParam,sizeof(WAVEHDR));
return;
}
(三)套接字发送、接收线程UINT Audio_Listen_Thread(LPVOID lParam)
{
CRecTestDlg *pdlg = (CRecTestDlg*)lParam;
CSocket m_Server;
DWORD length;
if(!m_Server.Create(4002))
AfxMessageBox("Listen Socket create error"+pdlg->GetError(GetLastError()));
if(!m_Server.Listen())
AfxMessageBox("m_server.Listen ERROR"+pdlg->GetError(GetLastError()));
CSocket recSo;
if(! m_Server.Accept(recSo))
AfxMessageBox("m_server.Accept() error"+pdlg->GetError(GetLastError()));
m_Server.Close();
int ret ;
while(1)
{ //开始循环接收声音文件,首先接收文件长度
ret = recSo.Receive(&length,sizeof(DWORD));
if(ret== SOCKET_ERROR )
AfxMessageBox("服务器端接收声音文件长度出错,原因: "+pdlg->GetError(GetLastError()));
if(ret!=sizeof(DWORD))
{
AfxMessageBox("接收文件头错误,将关闭该线程");
recSo.Close();
return -1;
}//接下来开辟length长的内存空间
pdlg->m_AudioDataOut[pdlg->nReceive].lpdata =(PBYTE)realloc (0,length);
if (pdlg->m_AudioDataOut[pdlg->nReceive].lpdata == NULL)
{
AfxMessageBox("erro memory_ReceiveAudio");
recSo.Close();
return -1;
}
else//内存申请成功,可以进行循环检测接受
{
DWORD dwReceived = 0,dwret;
while(length>dwReceived)
{
dwret = recSo.Receive((pdlg->m_AudioDataOut[pdlg->nReceive].lpdata+dwReceived),
(length-dwReceived));
dwReceived +=dwret;
if(dwReceived ==length)
{
pdlg->m_AudioDataOut[pdlg->nReceive].dwLength = length;
break;
}
}
}//本轮声音文件接收完毕
pdlg->nReceive=(pdlg->nReceive+1)%OutBlocks;
}
recSo.Close();
return 0;
}
UINT Audio_Send_Thread(LPVOID lParam)
{
CRecTestDlg *pdlg = (CRecTestDlg*)lParam;
CSocket m_Client;
m_Client.Create();
if( m_Client.Connect("127.0.0.1",4002))
{
DWORD ret, length;
int count=0;
while(1)//循环使用指针nSend
{
length =pdlg->m_AudioDataIn[pdlg->nSend].dwLength;
if(length !=0)
{ //首先发送块的长度
if(((ret = m_Client.Send(&length,sizeof(DWORD)))
!= sizeof(DWORD))||(ret==SOCKET_ERROR))
{
AfxMessageBox("声音文件头传输错误!"+pdlg->GetError(GetLastError()));
pdlg->OnOK();
break;
}//其次发送块的内容,循环检测是否发送完毕
DWORD dwSent = 0;//已经发送掉的字节数
while(1)//==============================发送声音数据开始
{
ret = m_Client.Send((pdlg->m_AudioDataIn[pdlg->nSend].lpdata+dwSent),
(length-dwSent));
if(ret==SOCKET_ERROR)//检错
{
AfxMessageBox("声音文件传输错误!"+pdlg->GetError(GetLastError()));
break;
}
else //发送未发送完的
{
dwSent += ret;
if(dwSent ==length)//发送完毕,则释放当前“块”
{
free(pdlg->m_AudioDataIn[pdlg->nSend].lpdata);
pdlg->m_AudioDataIn[pdlg->nSend].dwLength = 0;
break;
}
}
} //======================================发送声音数据结束
}
pdlg->nSend = (pdlg->nSend +1)% InBlocks;
}
}
else
AfxMessageBox("Socket连接失败"+pdlg->GetError(GetLastError()));
m_Client.Close();
return 0;
}
存在的问题
Finally,Thank Candy Lee(my special friend) for her help.