语音卡

13.5  语音卡控制

随着语音技术的不断发展,语音卡在通信行业应用非常广泛。本节通过几个典型实例介绍语音卡程序的开发。

实例428 语音卡电话呼叫系统

实例说明

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

文本框:
图13.12  语音卡电话呼叫系统
技术要点

本例采用东进公司开发的8路模拟语音卡,该卡采用灵活的模式化设计,可按需配置外线、内线两种模块。该语音卡可实现坐席、会议、FSK数据收发、语音合成等多种功能,并提供SDK开发工具包。

在安装完驱动程序后,相应的动态链接库(NewSig.dll和Tc08a32.dll文件)会复制到Windows的系统目录下。在语音卡的开发过程中,主要通过调用NewSig.dll和Tc08a32.dll来实现相应的功能。下面介绍这两个动态库中的主要使用函数。

(1)LoadDRV函数

该函数用于加载动态链接库。语法如下:

        [DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]

        public static extern long LoadDRV();

返回值:返回值为0表示成功;−1表示打开设备驱动程序错误。−2表示在读取TC08A-V.INI文件时发生错误;−3表示INI文件的设置与实际的硬件不一致时发生错误。

(2)FreeDRV函数

该函数用于关闭驱动程序。语法如下:

        [DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]

        public static extern long EnableCard(short wusedCh, short wFileBufLen);

(3)EnableCard函数

该函数用于初始化语音卡硬件,并为每个通道分配语音缓冲区。语法如下:

        [DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]

        public static extern long EnableCard(short wusedCh, short wFileBufLen);

参数说明如下。

l     wUsedCh:标识通道数量。

l     WFileBufLen:标识分配的缓冲区大小。

(4)CheckValidCh函数

该函数检测在当前机器内可用的通道总数。语法如下:

        [DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]

        public static extern short CheckValidCh();

l     返回值:通道总数量。

(5)CheckChType函数

该函数用于测试某个通道的类型。语法如下:

        [DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]

        public static extern short CheckChType(short wChnlNo);

参数说明如下。

l     wChnlNo:标识通道号。

l     返回值:为0表示内线;为1表示外线;为2表示悬空。

(6)PUSH_PLAY函数

该函数用于维持文件录放音的持续进行,需在处理函数的大循环中调用。语法如下:

        [DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]

        public static extern void PUSH_PLAY();

(7)SetBusyPara函数

该函数用于设置要检测的挂机忙音的参数。语法如下:

        [DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]

        public static extern void SetBusyPara(short BusyLen);

参数说明:

l     BusyLen:标识忙音的时间长度,单位为毫秒。

(8)RingDetect函数

该函数用于测试外线是否振铃或内线是否提机。语法如下:

       [DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]

        public static extern bool RingDetect(short wChnlNo);

参数说明如下。

l     wChnlNo:标识通道号。

返回值:如果为1,对于外线表示有振铃信息;对于内线,表示提机。如果为0,对于外线,表示无振铃信息;对于内线,表示挂机。

(9)OffHook函数

该函数用于外线提机。对于内线,不起作用。语法如下:

        [DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]

        public static extern void OffHook(short wChnlNo);

参数说明如下。

l     wChnlNo:标识外线通道。

(10)HangUp函数

该函数用于外线挂机。对于内线,不起作用。语法如下:

        [DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]

        public static extern void HangUp(short wChnlNo);

参数说明如下。

l     wChnlNo:标识外线通道。

(11)Sig_Init函数

该函数用于完成信号音检测的初始化工作。语法如下:

        [DllImport("NewSig.dll", CharSet = CharSet.Auto)]

        public static extern void Sig_Init(int Times);

参数说明如下。

l     wPara:缺省值为0,不起作用。

(12)Sig_CheckBusy函数

清空忙音检测的缓冲区以及内部计数。当检测对方挂机的忙音后,必须调用本函数。语法如下:

        [DllImport("NewSig.DLL", CharSet = CharSet.Auto)]

        public static extern void Sig_ResetCheck(short wChlNo);

参数说明如下。

l     wChNo:标识通道号。

l     返回值:为1表示检测到忙音;为0,表示没有检测到忙音。

(13)Sig_ResetCheck函数

该函数用于清空忙音检测的缓冲区以及内部计数。当检测对方挂机的忙音后,必须调用本函数。语法如下:

        [DllImport("NewSig.DLL", CharSet = CharSet.Auto)]

        public static extern void Sig_ResetCheck(short wChlNo);

参数说明如下。

l     wChNo:标识通道号。

(14)Sig_StartDial函数

该函数用于拨打电话号码。开始某通道的呼出过程。该函数只是设置通道的呼出缓冲区,真正的呼出过程需要循环调用Sig_CheckDial函数来逐步完成。语法如下:

        [DllImport("NewSig.dll", CharSet = CharSet.Auto)]

        public static extern int Sig_StartDial(short wChNo, [MarshalAs(UnmanagedType.LPArray)] byte[] DialNum, [MarshalAs(UnmanagedType.LPArray)] byte[] PreDialNum, short wMode);

参数说明如下。

l     wChNo:标识通道号。

l     DialNum:标识呼出号码。

l     PreDialNum:标识前导号码。

l     wMode:呼出检测的模式。

(15)Sig_CheckDial函数

该函数用于检测呼出结果。

在调用函数Sig_StartDial启动拨号过程后,就可以循环调用Sig_CheckDial函数维持拨号过程,并检测呼出的结果,直至得到结果为止。

拨号的一般过程如下。

1.如果参数PreDialNum不为空,则延迟1秒后拨出PreDialNum,如果参数PreDialNum为空,则直接进入步骤3。

2.检测PreDialNum是否已发完。如已发完转至步骤3。

3.检测是否有拨号音,如拨号音长度达到配置项DialToneAfterOffHook的数值,则发送DialNum码串,并转至步骤4。如在此步骤已等待配置项NoDialToneAfterOffHook定义的时间长度仍未检测到拨号音,则返回0x10。

4.检测DialNum码串是否发完,如已发完则延迟StartDelay配置项的时间长度后进入步骤5。

5.如果从进入此步骤起已经过配置项RingLen定义的时间长度,拨号音仍未停止则返回0x10;如果在此步骤已等待配置项NoRingLen定义的时间长度仍未检测到回铃音则返回0x10;如果检测到占线忙音数达到配置项BusySigCount定义的数字,则返回0x21;如果检测到对方摘机,则返回0x14;如果进入此步骤已经过配置项Ringback_NoAnswerTime定义的时间长度,并且已检测到回铃音,则返回0x13;其他情况返回0x10。

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

语法如下:

        [DllImport("NewSig.dll", CharSet = CharSet.Auto)]

        public static extern int Sig_CheckDial(short wChNo);

参数说明如下。

l     wChNo:标识通道号。

l     返回值包括以下几种情况。

l     16(0x10):尚未得出结果。

l     15(0x0F):没有拨号音。

l     33(0x21):检测到对方占线的忙音。

l     20(0x14):对方摘机,可以进行通话。

l     19(0x13):振铃若干次,无人接听电话。

l     21(0x15):没有信号音。

 注意:关于语音卡其他函数语法请参见光盘中的本实例文件D161A.CS,该文件给出大部分语音卡的函数语法。

实现过程

(1)新建一个项目,命名为Ex13_11,默认窗体为Form1。

(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;

        }

举一反三

根据本实例,读者可以开发以下程序。

*  实现电话自助服务系统。

*  实现电话自动报警系统。

实例429 客户来电查询系统

实例说明

随着市场竞争的加剧,企业越来越重视客户服务和市场反馈。本例实现了电话来电的显示支持功能。当有客户打入电话时,会读取客户的电话号码,根据电话号码可以提取客户的相关信息,方便客服人员有针对性地进行服务。实例运行结果如图13.13所示。

图13.13  客户来电查询

技术要点

其他相关函数介绍请参见实例“语音卡电话呼叫系统”,本实例主要介绍GetCallerIDStr函数,该函数用于获取主叫号码。语法如下:

        [DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]

        public static extern short GetCallerIDStr(short wChnlNo, byte[] IDStr);

参数说明如下。

l     wChnlNo:标识通道号。

l     IDStr:用于接收读取的号码。

l     返回值:为0,表示未收到任何信息;为1,表示正在接收头信息;为2表示正在接收ID号码;为3表示接收完毕,校验正确;为4表示接收完毕,校验错误。

在调用GetCallerIDStr函数时,只有返回值为3或4才表示已经正确接收了主机号码。

实现过程

(1)新建一个项目,命名为Ex13_12,默认窗体为Form1。

(2)在Form1窗体中,主要添加一个DataGridView控件,显示语音卡各通道和通道状态,并在来电时显示来电号码;添加一个Timer控件用于时刻检测来电信息;添加其他控件及用途如图13.13所示。

(3)主要程序代码。

private void timer1_Tick(object sender, EventArgs e)

        {

            byte[] ss = new byte[100];

                for (short i = 0; i < 8; i++)

                {

                    DJ160API.StartSigCheck(i);

                    if(open_close==false)

                        DJ160API.ResetCallerIDBuffer(i);

                    if (DJ160API.RingDetect(i))

                    {

                        open_close = true;

                        //获取来电号码

                        result = DJ160API.GetCallerIDStr(i, ss);

                        if (result == 3 || result == 4)

                        {

                            string str = Encoding.UTF8.GetString(ss);

                            txtTel.Text = str;

                            txtTel.Text = txtTel.Text.Substring(txtTel.Text.Length - 8, 8);

                            dataGridView1[2, i].Value = txtTel.Text;

                            //查询客户资料

                            this.getMessage(txtTel.Text);

                        }

                    }

                }

        }

        private void getMessage(string str)

        {

            OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + "db_csell.mdb" + ";Persist Security Info=False");

            OleDbDataAdapter dap = new OleDbDataAdapter("SELECT * FROM 个人名录表 WHERE 电话='" + str + "'", con);

            DataSet ds = new DataSet();

            dap.Fill(ds);

            if (ds.Tables[0].Rows.Count > 0)

            {

                txtName.Text = ds.Tables[0].Rows[0]["姓名"].ToString();

                txtDuty.Text = ds.Tables[0].Rows[0]["职务"].ToString();

                txtAddress.Text = ds.Tables[0].Rows[0]["地址"].ToString();

                txtMobile.Text = ds.Tables[0].Rows[0]["手机"].ToString();

                txtCompany.Text = ds.Tables[0].Rows[0]["公司名称"].ToString();

                txtPostId.Text = ds.Tables[0].Rows[0]["邮编"].ToString();

            }

            else

            {

                labStatus.Text = "非本单位会员客户。。。。";

            }

        }

举一反三

根据本实例,读者可以开发以下程序。

*  用语音卡实现客户某项费用的查询。

*  用语音卡实现客户在某个时间的留言信息。

*  用语音卡实现客户购买物品的查询。

*  实现客户反馈电话录音系统。

实例430 语音卡实现电话录音

实例说明

文本框:
图13.14  利用语音卡实现电话录音
如今的许多电话都具有电话录音的功能。本例实现了该功能,当有电话打入时,即刻将双方的对话信息进行录音。实例运行结果如图13.14所示。

技术要点

其他相关函数介绍请参见实例“语音卡电话呼叫系统”,本实例主要介绍StartRecordFile函数和StopRecordFile函数。

(1)StartRecordFile函数用于开始文件录音。停止该方式的录音一定要用StopRecordFile函数。检查录音是否结束,用CheckRecordEnd函数。StartRecordFile函数语法如下:

        [DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]

        public static extern bool StartRecordFile(short wChnlNo, byte[] FileName, long dwRecordLen);

参数说明如下。

l     wChnINo:标识录音的通道号。

l     FileName:标识录音的文件名。

l     dwRecordLen:标识文件大小。

(2)StopRecordFile函数用于停止录音。该函数语法如下:

        [DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]

        public static extern void StopRecordFile(short wChnlNo);

参数说明如下。

l     wChnINo:标识要停止的录音通道。

(3)CheckRecordEnd函数检查指定通道录音是否结束(缓冲区已满)。

        [DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]

        public static extern int CheckRecordEnd(int ChannelNo);

参数说明如下。

l     wChnINo:标识录音的通道号。

l     返回值:0表示未结束;1代表结束。

实现过程

(1)新建一个项目,命名为Ex13_13,默认窗体为Form1。

(2)在Form1窗体中,主要添加一个DataGridView控件,显示语音卡各通道和通道状态,并在来电时显示来电号码;添加一个Timer控件用于实时检测来电信息,如果来电,程序将自动摘机并且实现录音;添加其他控件及用途如图13.14所示。

(3)主要程序代码。

        private void timer1_Tick(object sender, EventArgs e)

        {

            //维持文件录音持续执行

            DJ160API.PUSH_PLAY();

            for (short i = 0; i < 8; i++)

            {

                DJ160API.StartSigCheck(i);

                if (open_close == false)

                    DJ160API.ResetCallerIDBuffer(i);

                if (DJ160API.RingDetect(i))

                {

                    open_close = true;

                    //摘机

                    DJ160API.OffHook(i);

                    DJ160API.StartSigCheck(i);

                    //是否挂机

                    if (DJ160API.ReadCheckResult(i, 2) != 33)

                    {

                        bool bl = DJ160API.StartRecordFile(i, Encoding.UTF8.GetBytes(@"D:/ly.001"), 600 * 1024);

                        dataGridView1[2, i].Value = "已接来电,开始录音";

                    }

                    else

                    {

                        DJ160API.StopRecordFile(i);

                        open_close = false;

                        DJ160API.Sig_ResetCheck(i);

                        dataGridView1[2, i].Value = "";

                    }

                    if (DJ160API.CheckRecordEnd(i)==1)

                    {

                        DJ160API.StopRecordFile(i);

                        open_close = false;

                        dataGridView1[2, i].Value = "";

                    }

                }

            }

        }

举一反三

根据本实例,读者可以实现以下功能。

*  用语音卡实现电话点播歌曲,通过按键的选择点播自己喜爱的歌曲。

*  用语音卡实现产品报价,通过按键实现某些产品的报价。

*  利用语音卡实现产品报价。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值