📄 cvoicechatdlg.cpp
字号:
return ;
}
if(m_clientstate==false)
{
PlaySound(NULL,NULL,NULL);//呼叫方在建立连接之前结束了呼叫
}
//关闭语音传输通道,关闭音频设备
}
void CCVoiceChatDlg::OnOK()
{
// TODO: Add extra validation here
Listensock.Close();
if( bwavedeviceInit==true){
for(int Exit=0;Exit<=1;Exit++)
{
delete pWaveHdrIn[Exit] ;
delete pWaveHdrOut[Exit] ;
free(pBufferIn[Exit]);
free(pBufferOut[Exit]) ;
waveInUnprepareHeader (hWaveIn, pWaveHdrIn[Exit], sizeof (WAVEHDR)) ;
waveOutUnprepareHeader (hWaveOut, pWaveHdrOut[Exit], sizeof (WAVEHDR)) ;
}
// 关闭音频设备
waveInClose (hWaveIn);
waveOutClose(hWaveOut);
}
//关闭线程
//清空队列
sendlist.deleteall();
recvlist.deleteall();
Sleep(10);
::TerminateThread(sendthread,0);
::TerminateThread(recvthread,0);
::WSACleanup();
CDialog::OnOK();
}
void CCVoiceChatDlg::OnCancel()
{
// TODO: Add extra cleanup here
CDialog::OnCancel();
}
void CCVoiceChatDlg::OnAccept()
{
m_link.EnableWindow(false);
m_agreen.EnableWindow(true);
m_abjust.EnableWindow(true);
UINT port=5050;
UpdateData(true);
//用于获得套接字连接的IP地址。
Contrlsock->GetPeerName(m_clientIP,port);
//int len=sizeof(client);
//Contrlsock->GetPeerName((sockaddr *)&client,&len);
m_info = m_clientIP;
m_info += "请求语音聊天.........\n";
UpdateData(false);
//播放提示语音
//PlaySound("../PhoneIn.wav",NULL,SND_SYNC|SND_LOOP| SND_ASYNC);
}
//接受客户端的控制信息,调整压缩比,提示对方的状态
void CCVoiceChatDlg::SerRecvCtrlnfo()
{
char buf[50];
Contrlsock->Receive(buf,50,0);
CString str;
str=buf;
if(str.Compare("对方终止了聊天..........")==0)
{
UpdateData(true);
m_info=str;
UpdateData(false);
sendlist.deleteall();
recvlist.deleteall();
Sleep(10);
::SuspendThread(sendthread);
::SuspendThread(recvthread);
m_serverstate=false;
bDisconnectState=true;
Contrlsock->Close();
Contrlsock=new CServerSock;
::closesocket(m_datasock);
return ;
}
}
//接受服务端的控制信息,调整压缩比,提示对方的状态
void CCVoiceChatDlg::ClientRecvCtrlnfo()
{
char buf[50];
Clientsock->Receive(buf,50,0);
CString str;
str=buf;
if(str.Compare("电话已接听!!")==0)
{
PlaySound(NULL,NULL,NULL);
m_clientstate=true;
bDisconnectState=false;
UpdateData(true);
m_info=str;
UpdateData(false);
//建立语音传输通道
if(SetDataSock())
{
return ;
}
//添加初始化音频函数
if( bwavedeviceInit==false)InitAudioDevice();
//开始录音
RecordBegin();
//启动发送与放音线程
::ResumeThread(sendthread);
::ResumeThread(recvthread);
}
if(str.Compare("对方拒绝了你的请求!!!")==0)
{
PlaySound(NULL,NULL,NULL);
m_link.EnableWindow(true);
m_end.EnableWindow(false);
UpdateData(true);
m_info=str;
UpdateData(false);
m_clientstate=false;
Clientsock->Close();//关闭套接字
Clientsock=new CClientSock;
}
if(str.Compare("对方终止了聊天..........")==0)
{
m_link.EnableWindow(true);
m_end.EnableWindow(false);
UpdateData(true);
m_info=str;
UpdateData(false);
m_clientstate=false;
Clientsock->Close();
Clientsock=new CClientSock;
::closesocket(m_datasock);
//清空发送与接受队列,睡眠5秒挂起线程
sendlist.deleteall();
recvlist.deleteall();
Sleep(10);
::SuspendThread(sendthread);
::SuspendThread(recvthread);
}
}
//设置语音传输通道
int CCVoiceChatDlg::SetDataSock()
{
m_datasock=socket(AF_INET,SOCK_DGRAM,0);
if(m_datasock<0)
{
AfxMessageBox("创建UDP的套接字失败");
}
server.sin_addr.S_un.S_addr=inet_addr(LocalIP);//转换点分格式IP为in_addr结构体
server.sin_family=AF_INET;
server.sin_port=htons(5050);
if(bind(m_datasock,(sockaddr *)&server,sizeof(server))!=0)
{
closesocket(m_datasock);
AfxMessageBox("绑定不成功,将退出!!");
return 0;
}
if(WSAAsyncSelect(m_datasock,this->m_hWnd,UM_SOCK,FD_READ|FD_WRITE|FD_CLOSE)==SOCKET_ERROR)
{
AfxMessageBox("函数WSAAsyncSelect()出错");
return 0;
}
if(m_clientstate==true)
{
server.sin_addr.S_un.S_addr=inet_addr(m_serverIP);
}
if(m_serverstate==true)
{
//server.sin_addr.S_un.S_addr=inet_addr(m_clientIP);
server.sin_addr.S_un.S_addr=inet_addr(m_clientIP);//("202.193.60.242");
}
return 1;
}
void CCVoiceChatDlg::ONDATASOCKETPRC(UINT wParam,LONG lParam)
{
switch(lParam)
{
case FD_READ:
{
//接受数据放入接受队列
char *buffer=new char[4096];
int len=sizeof(sockaddr);
::recvfrom(m_datasock,buffer,4096,0,(sockaddr *)&server,&len);
CQueueItem *item=new CQueueItem;
item->data=buffer;
//将数据放入接受队列
recvlist.InsertItem(item);
}
break;
case FD_WRITE:
break;
case FD_CLOSE:
{
}
break;
default:
break;
}
}
bool CCVoiceChatDlg::InitAudioDevice()
{
// 初始化waveform
waveform.wFormatTag = WAVE_FORMAT_PCM ; // 采样方式,PCM(脉冲编码调制)
waveform.nChannels = 2 ; // 双声道
waveform.nSamplesPerSec = 11025 ; // 采样率11.025KHz
waveform.nAvgBytesPerSec = 11025; // 数据率11.025KB/s
waveform.nBlockAlign = 2 ; // 最小块单元,wBitsPerSample×nChannels/8
waveform.wBitsPerSample = 8 ; // 样本大小为8bit
waveform.cbSize = 0 ; // 附加格式信息
// 准备pWaveHdrIn和pWaveHdrOut
for(int HdrNum=0;HdrNum<=1;HdrNum++)
{
// 为缓冲区分配内存
pBufferIn[HdrNum] = (PBYTE)malloc (INP_BUFFER_SIZE) ;
pBufferOut[HdrNum] = (PBYTE)malloc (INP_BUFFER_SIZE) ;
if (!pBufferIn[HdrNum] || !pBufferOut[HdrNum])
{
if (pBufferIn[HdrNum])
free (pBufferIn[HdrNum]) ;
if (pBufferOut[HdrNum])
free (pBufferIn[HdrNum]) ;
AfxMessageBox(_T("内存分配失败!"),MB_ICONINFORMATION|MB_OK,NULL);
}
pWaveHdrIn[HdrNum] =new WAVEHDR;
pWaveHdrOut[HdrNum]=new WAVEHDR;
pWaveHdrOut[HdrNum]->lpData = (char *)pBufferIn[HdrNum];
pWaveHdrOut[HdrNum]->dwBufferLength = INP_BUFFER_SIZE ;
pWaveHdrOut[HdrNum]->dwBytesRecorded = 0 ;
pWaveHdrOut[HdrNum]->dwUser = 0 ;
pWaveHdrOut[HdrNum]->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP ;
pWaveHdrOut[HdrNum]->dwLoops = 1;
pWaveHdrOut[HdrNum]->lpNext = NULL ;
pWaveHdrOut[HdrNum]->reserved = 0 ;
pWaveHdrIn[HdrNum]->lpData = (char *)pBufferOut[HdrNum] ;
pWaveHdrIn[HdrNum]->dwBufferLength = INP_BUFFER_SIZE ;
pWaveHdrIn[HdrNum]->dwBytesRecorded = 0 ;
pWaveHdrIn[HdrNum]->dwUser = 0 ;
pWaveHdrIn[HdrNum]->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP ;
pWaveHdrIn[HdrNum]->dwLoops = 1 ;
pWaveHdrIn[HdrNum]->lpNext = NULL ;
pWaveHdrIn[HdrNum]->reserved = 0 ;
}
// 打开播放波形音频设备
MMRESULT result;
result=waveOutOpen (&hWaveOut, WAVE_MAPPER, &waveform,
(DWORD) pDlg->m_hWnd, 0, CALLBACK_WINDOW);
// 打开录制波形音频设备
if(result==MMSYSERR_NOERROR)
result=waveInOpen (&hWaveIn, WAVE_MAPPER, &waveform,
(DWORD) pDlg->m_hWnd, 0, CALLBACK_WINDOW);
// 为播放和录音准备
for(int Prepare=0;Prepare<=1;Prepare++)
{
if(result==MMSYSERR_NOERROR)
result=waveOutPrepareHeader(hWaveOut, pWaveHdrOut[Prepare],
sizeof (WAVEHDR)) ;
if(result==MMSYSERR_NOERROR)
result=waveInPrepareHeader(hWaveIn, pWaveHdrIn[Prepare],
sizeof (WAVEHDR)) ;
}
// 设置音量为最大
//if(result==MMSYSERR_NOERROR)
// result=waveOutSetVolume(hWaveOut,65535);
// 成功返回TRUE
if(result==MMSYSERR_NOERROR)
{
bwavedeviceInit=true;
return TRUE;
}
else
{
AfxMessageBox(_T("打开波形音频设备时发生错误!"),MB_ICONINFORMATION | MB_OK,NULL);
return FALSE;
}
bwavedeviceInit=true;
return true;
}
void CCVoiceChatDlg::RecordBegin()
{
// 准备录音缓冲区
waveInAddBuffer (hWaveIn, pWaveHdrIn[nOut], sizeof (WAVEHDR)) ;
// 开始录音
waveInStart (hWaveIn) ;
}
void CCVoiceChatDlg::ON_MM_WIM_OPEN()
{
AfxMessageBox("打开录音设备成功!");
}
void CCVoiceChatDlg::ON_MM_WIM_DATA()//录音开始后,每当有采样数据填满数据块后
//设备驱动程序就会发消息MM_WIM_DATA给用户窗口
{
// 将音频数据放入队列
CQueueItem *item=new CQueueItem;
char *buffer=new char[4096];
memcpy(buffer,pBufferOut[nOut],4096);
item->data=buffer;
sendlist.InsertItem(item);
//memset(pBufferOut[nOut],0,4096);
// 缓冲区循环
nOut=1-nOut;
//if (bDisconnectState==TRUE)//判断连接是否已经断开
//{
// waveInClose(hWaveIn) ;
//}
//else
//{
// 开始下一轮录音
RecordBegin();
//}
}
void CCVoiceChatDlg::ON_MM_WIM_CLOSE()
{
waveInUnprepareHeader(hWaveIn, pWaveHdrIn[0], sizeof (WAVEHDR)) ;
waveInUnprepareHeader(hWaveIn, pWaveHdrIn[1], sizeof (WAVEHDR)) ;
waveInClose (hWaveIn);
hWaveIn=NULL; //clear it
}
void CCVoiceChatDlg::ON_MM_WOM_OPEN()
{
}
DWORD WINAPI ThreadSendPro(LPVOID lp)
{
while(1)
{
char *buffer;
while(1)
{
if(pDlg->sendlist.Itemnum()>0)break;
//::Sleep(1);
}
buffer=pDlg->sendlist.TakeOutItem();
//添加数据压缩代码
int ret=::sendto(pDlg->m_datasock,buffer,4096,0,(sockaddr *)&server,sizeof(sockaddr));
delete(buffer);
}
return 0;
}
DWORD WINAPI ThreadRecvPro(LPVOID lp)
{
while(1)
{
char *buffer;
while(1)
{
if(pDlg->recvlist.Itemnum()>0)break;
//::Sleep(1);
}
buffer=pDlg->recvlist.TakeOutItem();
//对数据进行解压缩还原
memcpy(pBufferIn[nIn],buffer,strlen(buffer));
//播放音频
waveOutWrite (hWaveOut, pWaveHdrOut[nIn], sizeof (WAVEHDR)) ;
//清空缓冲区
//memset(pBufferIn[nIn],0,4096);
nIn=1-nIn;
delete(buffer);
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -