摘要:提出了一种集成式IP电话网关的实现方法,分析了语音信号在该网关中的处理过程,详细介绍了语音采样、播放、压缩与解压缩、RTP包的封装与解包以及IP包的接受和发送的实现方法。 关键词:IP电话网关 语音压缩 RTP协议
随着IP电话技术的飞速发展,IP电话的实现方式正在由PC To PC过渡到Phone to Phone,在Phone to Phone的实现方式中,需要所谓的IP电话网关来连接PSTN和因特网。因此IP电话网关成为目前计算机和通信领域研究的热点之一。虽然国内外许多厂商都在以不同的方式开发IP电话网关,但他们有一个共同的特点,即:几乎所有IP电话网关都采用了自己的专用硬件设备。本文提出了一种采用市场上通用的板卡来构造一种硬件集成式的IP电话网关的方法,并研究了语音数据在该网关的处理过程和实现方法。集成式IP电话网关的硬件构成如图1所示,它是在Pentium Ⅱ PC机基础上,插入Dialogic公司的D/41E型语音卡、LSI公司的C6200资源卡和D_Link网卡所组成。其中D/41E语音卡用来完成语音的采样和播放。C6200资源卡有一块TI公司的TMS320C6201DSP芯片,用来完成语音的压缩和解压缩以及回声抵消。Pentium Ⅱ PC用来实现H.323协议栈的主要功能,网卡用来发送和接受IP包。下面具体分析语音数据在IP电话网关的处理过程和实现方法。 1 语音采样和播放
在该IP电话网关中,语音的采样和播放是由Dialogic公司的D/41E型语音卡来完成,其中,语音采样是利用语音卡所提供的录音函数来完成的。在实时语音通信时,语音数据存入语音采样缓冲区中,等待语音压缩线程取出并处理。录音函数形式如下:
dx_reciottdata (activeChdev,&chinfo [activeChdev].iott,&tptrec[0],&xpbVox,mode);
该函数的输入参数的含义如下:
int chdev 语音通道的设备句柄
DX_IOTT *iott 指向语音数据目的地的指针
DV_TPT *tptp 指向终止参数块的指针
DX_XPB *xpbp 指向I/O传输块的指针
unsigned short mode 录音所采取的方式
iott是一种DX_IOTT类型的数据结构,该数据结构中的io_type可取值IO_DEV和IO_MEM,分别用于指定语音数据存入文件还是存入缓冲区中。Io_type的另一类取值可为IO_CONT,IO_LINK或DX_IOTT,用于指定语音数据目的地的结构。如果io_type取值IO_DEV,则io_fhandle的值应为一个文件的句柄;如果io_type取值IO_MEM,则io_fhandle的值应为0,此时,io_bufp指向存放语音数据的缓冲区的起始地址。io_offset为地址偏移量。io_length用于指定文件或缓冲区的大小。如果io_type取值IO_LINK,则io_nextp指向下一个存放语音数据的DX_IOTT数据结构,而io_pre vp指向上一个存放语音数据的DX_IOTT数据结构。DX_IOTT的数据结构定义如下:
typedef struct dx_iott {
unsigned short io_type; /*Transfer type*/
unsigned short rfu; /*Reserved*/
int io_fhandle; /*File descriptor*/
char* io_bufp; /*Pointer to base memory*/
unsigned long io_offset; /*File/Buffer offset*/
long int io_length; /*Length of data*/
DX_IOTT io_nextp; /*Ptr to next DX_IOTT if IO_LINK set*/
DX_IOTT io_prevp; /*(Optional) Ptr to previous DX_IOTT*/
}DX_IOTT;
DV_TPT数据结构用于指定终止某语音通道上函数的条件。具体如下:
typedef struct DV_TPT {
unsigned short tp_type; /*Flags describing this structure*/
unsigned short tp_termno; /*Termination parameter number */
unsigned short tp_length; /*Length of terminator*/
unsigned short tp_flags; /*Term.parameter attributes flag*/
unsigned short tp_data; /*Optional additional data*/
unsigned short rfu; /*Reserved for future use*/
struct DV_TPT tp_nextp; /Pointer to next term.parameter if*/
/*IO_LINK is set*/
} DV_TPT;
DX_XPB数据结构用于指定用何种算法进行录音等。WfileFormat可取值FILE_FORMAT_VOX和FILE_FORMAT_WAVE,分别代表用VOX文件格式和WAV文件格式存放语音数据。WDataFormat可取值DATA_FORMAT_DIALOGIC_ADPCM、DATA_FORMAT_MULAW、DATA_FORMAT_ALAW、DATA_FORMAT_PCM,分别代表用ADPCM、μ率、A率或线性PCM的算法对声音进行采样。NsamplesPerSec可取值DRT_6kHz、DRT_8kHz、DRT_11kHz,用于指定采样频率分别为6kHz、8kHz或11kHz。NBitsPerSample可取值4和8,为每个样本点的位数。如果wDataFormat采用ADPCM算法,则nBitsPerSample只能取4。DX_XPB的数据结构定义如下:
Typedef struct {
USHORT wFileFormat; //file format
USHORT wDataFormat; //audio data format
ULONG nSamplesPerSec; //sampling rate
ULONG nBitsPerSample; //bits per sample
} DX_XPB;
mode用于指定录音的方式,可取值PM_TONE、EV_SYNCH或EV_ASYNCH。取值PM_TONE代表在录制前先播放一个200ms的提示音。取值为EV_SYNCH时,代表用同步的方式执行语音采样,在同一线程中的其它功能将被暂挂起,直到该同步函数执行完后才被释放。取值为EV_ASYNCH代表是用异步的方式执行语音采样,在同一线程中的其它功能仍可照常进行。
语音播放是利用语音卡播放函数来完成的。该函数所用的参数与录音函数的参数类似。播放函数的形式如下:
dx_playiottdata (activeChdev,&chinfo [activeChdev]iott,&tptplay[0],&xpbVox,mode) 2 电话状况侦测
电话状总值侦测功能主要是判断电话线状况,如判断现在电话机话筒是拿起或放下,有没有拨号音,是否电话正忙或没有人接电话。在异步方式下,采用语音卡的ATDX_CPTERM()来检测某语音通道上电话呼叫的返回值。在同步方式下无需该步骤。当返回值为CR_CEPT时,表示特殊通知音,即拨了无效的电话号码或遇到了其它特殊问题。当返回值为CR_NORB时,表示无回铃音,即检测不到可识别的信号模式。当返回值为CR_NOANS时,表示无应答,即线已拨通,但无应答。当返回值为CR_NOANS时,表示忙音。当返回值为CR_CNCT时,还可利用ATDX_CONNTYPE(chdev)函数检测连接音的类型。返回值可能是CON_CAD,CON_LPC,CON_PVD或CON_PAMD,分别代表韵律连接音,循环流连接音,阳机音连接或阳极应答机连接音。
进行呼叫时,先用ATDX_HOOKST(activeChdev)函数获取电话机的状态。如果是挂机状态,则用dx_sethook(activeChdev,DX_OFFHOOK,EV_SYNC)将电话机置为摘机状态。然后给呼叫函数传递所需的参数。参数是通过DX_CAP这个数据结构来传递的,其定义为:
typedef struct DX_CAP {
unsigned short ca_nbrdna; //# of rings before no answer.
unsigned short ca_stdely; //Delay after dial before analysis
unsigned short ca_cnosig; //Duration if no signal time out delay
unsigned short ca_lcdly; //Delay after dial before lc drop connect
unsigned short ca_lcdly 1; //Delay after lc drop con. Before msg.
unsigned short ca_hEdge; //Edge of answer to send connect message
unsigned short ca_cnosil; //Initial continuous noise timeout delay
unsigned short ca_loltola; //% acceptable pos.dev of short low sig.
unsigned short ca_lo l tolb; //% acceptable neg.dev of short low sig.
unsigned short ca_lo2tola; //% acceptable pos.dev of long low sig.
unsigned short ca_lo2tolb; //% acceptable neg.dev of long low sig.
unsigned short ca_hiltola; //% acceptable pos.dev of high signal.
unsigned short ca_hiltolb; //% acceptable neg.dev of high signal
unsigned short ca_lo 1 bmax; //Maximum interval for shrt low for busy.
unsigned short ca_lo 2 bmax; //Maximum interval for long low for busy.
unsigned short ca_hi 1 bmax; //Maximum interval for lst high for busy
unsigned short ca_nsbusy; //Num.of highs after nbrdna busy check.
unsigned short ca_logltch; //Silence deglitch duration.
unsigned short ca_higltch; //Non-shlence deglitch duration.
unsigned short ca_lo 1 rmax; //Max.short low dur.of double ring
} DX_CAP;
该数据结构中有大量的参数项,一般使用缺省值即可。需要修改时,可通过程序提供的呼叫对话框来修改。呼叫的电话号码也在该对话框中指定。