分类: 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.