📄 wavecn_com 世纪音频 - 音频应用 - 基于wavex低级音频函数的实时语音通信.htm
字号:
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>↓</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
WM_WOM_DONE</SPAN></P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>│<SPAN>
</SPAN>↘</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>│ <SPAN> </SPAN>缓冲播放完或停止输出消息</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>↓</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
WM_WOM_CLOSE</SPAN></P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>│<SPAN> </SPAN>↘ </P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>↓<SPAN> </SPAN>音频输出
设备关闭消息</P></DIV>
<P style="TEXT-ALIGN: center" align=center><SPAN>6.2
</SPAN>播放过程消息</P>
<P> 在打开音频输入或输出设备消息处理中,可对一些变量进行初始化;在<SPAN>WM_WIM_CLOSE</SPAN>消息的处理中主要是调用<SPAN>WaveInUnprepareHeader</SPAN>释放输入设备对应的缓存和其他资源;在<SPAN>WOM_CLOSE</SPAN>消息的处理中主要是调用<SPAN>WaveOutUnprepareHeader</SPAN>释放输出设备对应的缓存和其他资源;在<SPAN>WM_WIM_DATA</SPAN>消息处理中,处理完录入的数据后需要重新为输入设备添加缓冲;在<SPAN>WM_WIM_DATA</SPAN>消息处理中,首先清空已经播放的数据,调整循环队列中接收音频指针和播放音频指针,然后从该队列中拷贝数据到输出缓存中。</P>
<H1><A id=_Toc162973511 name=_Toc162973511><SPAN>7 </SPAN>程序结构</A></H1>
<P> 系统的功能是实现在局域网内的点对点实时音频通信。音频的网络传输采用<SPAN>UDP</SPAN>方式。</P>
<P> 程序中为输入设备准备了两块缓冲,输出设备的缓冲块数可以通过修改宏进行调整,但至少是两块。程序使用多线程技术实现声音的采集发送和接收播放。总体结构如下所示:</P>
<DIV
style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 4pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 1pt; BORDER-LEFT: windowtext 1pt solid; PADDING-TOP: 1pt; BORDER-BOTTOM: windowtext 1pt solid">
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>程序启动</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>↓</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>设置音频属性</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>│</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>↙<SPAN> </SPAN>↘</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>启动录音 <SPAN> </SPAN>启动音频包接收</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>↓<SPAN>
</SPAN>↓</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>发送音频包
<SPAN> </SPAN>启动播放</P></DIV>
<P style="TEXT-ALIGN: center" align=center><SPAN>7.1
</SPAN>总体结构图</P>
<P> 程序总体结构很简单,大体可以分为两部分:一是录音和发送,二是接收和播放。</P>
<P>(一) 录音发送部分的流程如下:</P>
<DIV
style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 4pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 1pt; BORDER-LEFT: windowtext 1pt solid; PADDING-TOP: 1pt; BORDER-BOTTOM: windowtext 1pt solid">
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>打开音频输入设备(录音)</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>↓</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>为输入设备准备两块缓存</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>↓</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>启动录音</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>│</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>┌─────────────→│</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>│<SPAN>
</SPAN>↙ ↘</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>│<SPAN>
</SPAN>捕捉到消息:<SPAN>WM_WIM_DATA</SPAN><SPAN>
</SPAN>捕捉到消息:<SPAN>WM_WIM_CLOSE</SPAN></P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>│<SPAN>
</SPAN>↓<SPAN>
</SPAN>↓</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>│<SPAN>
</SPAN>对已录数据进行<SPAN>G721</SPAN>编码<SPAN>
</SPAN>释放输入设备所有缓存</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>│<SPAN>
</SPAN>↓<SPAN>
</SPAN>↓</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>│<SPAN>
</SPAN>发送编码后数据<SPAN>
</SPAN>关闭音频输入设备,结束</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>│<SPAN>
</SPAN>↓</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>│ <SPAN> </SPAN>为输入设备重新指定缓存</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>│<SPAN>
</SPAN>│</P>
<P class=TextGraph
style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; BACKGROUND: #ccffcc; PADDING-BOTTOM: 0pt; BORDER-TOP-STYLE: none; PADDING-TOP: 0pt; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"><SPAN>
</SPAN>└───────┘</P></DIV>
<P style="TEXT-ALIGN: center" align=center><SPAN>7.2
</SPAN>录音及发送流程图</P>
<P> 部分源码:</P>
<P><SPAN>1</SPAN>)打开音频输入设备源码为:</P>
<DIV
style="BORDER-RIGHT: navy 1pt solid; PADDING-RIGHT: 4pt; BORDER-TOP: navy 1pt solid; PADDING-LEFT: 4pt; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 1pt; BORDER-LEFT: navy 1pt solid; PADDING-TOP: 1pt; BORDER-BOTTOM: navy 1pt solid">
<P class=SourceCode><SPAN>waveInOpen(&hWaveIn,</SPAN></P>
<P class=SourceCode><SPAN> WAVE_MAPPER,</SPAN></P>
<P
class=SourceCode><SPAN> &m_waveformin,</SPAN></P>
<P
class=SourceCode><SPAN> (DWORD)waveInProc,</SPAN></P>
<P class=SourceCode><SPAN> NULL,</SPAN></P>
<P
class=SourceCode><SPAN> CALLBACK_FUNCTION);</SPAN></P></DIV>
<P> 其中,<SPAN>hWaveIn</SPAN>为音频输入句柄,<SPAN>WAVE_MAPPER</SPAN>表示让系统选择录音的声卡,<SPAN>m_waveformin</SPAN>是音频格式,<SPAN>waveInProc</SPAN>是消息处理函数名,<SPAN>CALLBACK_FUNCTION</SPAN>表示以函数调用的方式处理响应录音过程中的消息。</P>
<P><SPAN>2</SPAN>)为输入设备添加缓冲的源码为:</P>
<DIV
style="BORDER-RIGHT: navy 1pt solid; PADDING-RIGHT: 4pt; BORDER-TOP: navy 1pt solid; PADDING-LEFT: 4pt; BACKGROUND: #f3f3f3; PADDING-BOTTOM: 1pt; BORDER-LEFT: navy 1pt solid; PADDING-TOP: 1pt; BORDER-BOTTOM: navy 1pt solid">
<P class=SourceCode><SPAN>//
</SPAN>为音频输入准备两个缓存<SPAN>:pBuffer1,pBuffer2</SPAN>,大小为<SPAN>BUFFER_SIZE</SPAN>。</P>
<P class=SourceCode><SPAN>// hWaveIn</SPAN>为音频输入句柄</P>
<P
class=SourceCode><SPAN>pWaveHdr1->lpData &
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -