VOIP Research——东进D161A语音处理卡应用

什么是VOIP   

      VoIP是Voice over Internet Protocol的缩写,指的是将模拟的声音讯号经过压缩与封包之后,以数据封包的形式在IP 网络的环境进行语音讯号的传输,通俗来说也就是互联网电话、网络电话或者简称IP电话的意思。VoIP技术是目前互联网应用领域的一个热门话题,成为全球互联网与电子商务十大趋势之一(eMarketer)。

VOIP的原理

      VoIP的基本原理是:通过语音的压缩算法对语音数据编码进行压缩处理,然后把这些语音数据按 TCP/IP 标准进行打包,经过 IP 网络把数据包送至接收地,再把这些语音数据包串起来,经过解压处理后,恢复成原来的语音信号,从而达到由互联网传送语音的目的。 IP 电话的核心与关键设备是 IP 网关,它把各地区电话区号映射为相应的地区网关 IP 地址。这些信息存放在一个数据库中,数据接续处理软件将完成呼叫处理、数字语音打包、路由管理等功能。

如何实现长途电话

  在用户拨打长途电话时,网关根据电话区号数据库资料,确定相应网关的 IP 地址,并将此 IP 地址加入 IP 数据包中,同时选择最佳路由,以减少传输时延, IP 数据包经 Internet 到达目的地的网关。在一些 Internet 尚未延伸到或暂时未设立网关的地区,可设置路由,由最近的网关通过长途电话网转接,实现通信业务。

VOIP的优点

      VoIP网络电话会成为将来的主流,技术的可控性、灵活性和经济性优势使网络电话可应用于许多场所。

实例说明

      随着科学技术的不断发展,语音卡被广泛地应用于商业软件中。本例实现了利用语音卡实现电话呼叫的功能。实例运行结果如图13.12所示。

image
图13.12 语音卡电话呼叫系统

技术要点

      本例采用东进公司开发的8路模拟语音卡,该卡采用灵活的模式化设计,可按需配置外线、内线两种模块。该语音卡可实现坐席、会议、FSK数据收发、语音合成等多种功能,并提供SDK开发工具包。
在安装完驱动程序后,相应的动态链接库(NewSig.dllTc08a32.dll文件)会复制到Windows的系统目录下。在语音卡的开发过程中,主要通过调用NewSig.dll和Tc08a32.dll来实现相应的功能。下面介绍这两个动态库中主要使用的函数
(1)LoadDRV函数
该函数用于加载动态链接库。
(2)FreeDRV函数
该函数用于关闭驱动程序。
(3)EnableCard函数
该函数用于初始化语音卡硬件,并为每个通道分配语音缓冲区。
(4)CheckValidCh函数
该函数检测在当前机器内可用的通道总数。
(5)CheckChType函数
该函数用于测试某个通道的类型。
(6)PUSH_PLAY函数
该函数用于维持文件录放音的持续进行,需在处理函数的大循环中调用。
(7)SetBusyPara函数
该函数用于设置要检测的挂机忙音的参数。
(8)RingDetect函数
该函数用于测试外线是否振铃或内线是否提机。
(9)OffHook函数
该函数用于外线提机。
(10)HangUp函数
该函数用于外线挂机。
(11)Sig_Init函数
该函数用于完成信号音检测的初始化工作。
(12)Sig_CheckBusy函数
清空忙音检测的缓冲区以及内部计数。
(13)Sig_ResetCheck函数
该函数用于清空忙音检测的缓冲区以及内部计数。
(14)Sig_StartDial函数
该函数用于拨打电话号码。开始某通道的呼出过程。该函数只是设置通道的呼出缓冲区,真正的呼出过程需要循环调用Sig_CheckDial函数来逐步完成。
(15)Sig_CheckDial函数
该函数用于检测呼出结果。

注意:在进行呼出结果检测之前必须调用函数StartSigCheck启动信号音采集过程,并且在进行呼出结果检测时,要循环调用FeedSigFunc函数维持信号音采集过程。

实现过程
(1)新建一个项目。
(2)在Form1窗体中,主要添加两个Button控件,用于执行电话拨号和电话挂机,添加一个DataGridView控件,显示语音卡各通道及通道状态,添加Timer组件实现电话的呼出过程,添加一个TextBox控件,用于输入呼出电话号码
(3)主要程序代码
      在窗体装载事件中,主要进行初始化语音卡驱动程序,并且检测通道总数及状态,为每一条通道分配语音缓冲区。代码如下:
        private void Form1_Load(object sender, EventArgs e)
        {
            //初始化驱动程序
            long load = DJ160API.LoadDRV();
            //检测通道总数,并为每个通道分配语音缓冲区
            short wuseCh = DJ160API.CheckValidCh();
            short wFileBufLen = 16 * 1024;
            long card = DJ160API.EnableCard(wuseCh, wFileBufLen);
            //设置表格通道的行数
            dataGridView1.RowCount = wuseCh;
            //检测每个通道类型
            short chanelTpye = 0; //定义通道类型变量
            string strType = "";
            for (short i = 0; i < wuseCh; i++)
            {
                chanelTpye = DJ160API.CheckChType(i);
                dataGridView1[0, i].Value = i;
                switch (chanelTpye)
                {
                    case 0:
                        strType = "内线";
                        break;
                    case 1:
                        strType = "外线";
                        break;
                    case 2:
                        strType = "悬空";
                        break;
                }
                dataGridView1[1, i].Value = strType;
                dataGridView1[2, i].Value = "空闲";
            }
        }
      在DataGridView控件中选择一个外线空闲通道,单击【拨号】按钮,进行电话拨号,并且将拨号过程中的状态显示在相应的DataGirdView表格中。代码如下:
        private void button1_Click(object sender, EventArgs e)
        {
            short wuseCh = DJ160API.CheckValidCh();
            short wFileBufLen = 16 * 1024;
            long card = DJ160API.EnableCard(wuseCh, wFileBufLen);
            DJ160API.Sig_Init(chanel);
            //检查(外线)是否有振铃信号或(内线)是否有提机
            bool ring = DJ160API.RingDetect(chanel);
            //外线提机
            DJ160API.OffHook(chanel);
            byte[] ss =new byte[textBox1.Text.Length];
            byte[] s ={ 0 };
            for (int i = 0; i < textBox1.Text.Length; i++)
            {
                ss[i] = Convert.ToByte(textBox1.Text.Substring(i, 1));
            }
            DJ160API.Sig_StartDial(chanel, ss, s, 0);
            timer1.Enabled = true;
            dataGridView1[2, chanel].Value = "拨号中…";
            dataGridView1[3, chanel].Value = textBox1.Text;
        }
      单击【挂机】按钮,实现电话挂机功能。代码如下:
        private void button2_Click(object sender, EventArgs e)
        {
            DJ160API.HangUp(chanel);
            DJ160API.Sig_ResetCheck(chanel);
            DJ160API.StartSigCheck(chanel);
            timer1.Enabled = false;
            dataGridView1[2, chanel].Value = "空闲";
            dataGridView1[3, chanel].Value = "";
        }
      Sig_StartDial函数用于拨打电话号码。开始某通道的呼出过程。该函数只是设置通道的呼出缓冲区,真正的呼出过程需循环调用Sig_CheckDial函数来逐步完成。代码如下:
        private void timer1_Tick(object sender, EventArgs e)
        {
            DJ160API.Sig_CheckDial(chanel);
        }
      单击DataGridView控件的相应行记录相应的通道号,代码如下:
   private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            chanel = (short)e.RowIndex;
        }

参考资料:

http://blog.csdn.net/long102/archive/2007/10/31/1859287.aspx

完整的东进D161A板卡API函数类:

http://www.dj.com.cn/donjinbbs/ShowPost.asp?action=Previous&id=2789

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s