C#控制语音卡实现呼叫、录音以及来电弹屏
最近,正在忙基于三汇语音卡的呼叫中心的项目,真的好迷糊啊!公司在呼叫中心这方面的研发是空白,所有的资料都得从零开始收集,分析,上网查找一些前辈们的技术资料,在这里备个份,好好学习一下!
---------------------------------------------------------------------------------------------------------------------
随着语音技术的不断发展,语音卡在通信行业应用非常广泛。本节通过几个典型实例介绍语音卡程序的开发。
实例428 语音卡电话呼叫系统
实例说明
随着科学技术的不断发展,语音卡被广泛地应用于商业软件中。本例实现了利用语音卡实现电话呼叫的功能。实例运行结果如图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所示。
技术要点
其他相关函数介绍请参见实例“语音卡电话呼叫系统”,本实例主要介绍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 = "";
}
}
}
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/long102/archive/2007/10/31/1859287.aspx
C#控制语音卡实现呼叫、录音以及来电弹屏相关推荐
- 硬件接口开发之USB电话录音盒来电显示
除了上篇<硬件接口开发之Modem来电显>介绍的Modem来电显示,还可以采用USB电话录音盒来进行来电显示和电话录音功能,本文介绍如何在C#中实现该功能.首先我们看看我是如何在我的软件中 ...
- 企业级:基于语音卡呼叫中心系统 CTI语音服务器,电话排队系统,电话转接系统,电话录音系统
<CTI通讯接口软件D081A>用 户 手 册 语音服务器软件源代码+用户手册+数据结构+开发文档 有需要的给我留言! 我的QQ 7732 4199 本系统基本上可以适用于 有语 ...
- 分享一个C#使用AT指令控制语音猫的例子
阅读全文:http://www.cckan.net/forum.php?mod=viewthread&tid=61 先来说说 最近公司让开发一个语音猫充值的软件,就是拨打10086(虚拟)进行 ...
- 谈谈市场上常用语音芯片方案选型,录音芯片方案选型
[系列专栏]:博主结合工作实践输出的,解决实际问题的专栏,朋友们看过来! <QT开发实战> <嵌入式通用开发实战> <嵌入式Linux开发实战> 转自:http:/ ...
- Java字节流读取shp_SHN系列语音卡调试文档.doc
三汇系列语音卡 杭 州 三 汇 信 息 工 程 有 限 公 司修订记录 时间修订内容修订人版本批准人20-11-22创建郑王峰V0.102012-06-08完善DTMF收发方式部分以及STUN与NAT ...
- C#实现IVR(基于东进的语音卡)-3
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Runtim ...
- Delphi之东进模拟语音卡(D160A)可复用源码
Delphi之东进模拟语音卡(D160A)可复用源码 作者:成晓旭 Blog:http://blog.csdn.net/cxxsoft (声明:欢迎转载,请保证文章的完整性) 设计简介: 1. 将 ...
- 东进语音卡 java_东进语音卡的声音文件格式
转自东进论坛 语音卡只支持8K8bit a-law 单声道的 PCM.wave.mp3,您的立体声的mp3需要转换成单声道,8k 8bit的才能播放 问:怎么样把wav格式的文件转换成东进卡能播放的格 ...
- Delphi之东进模拟语音卡(D160A)可复用源码(转)
计 简介: 1. 将卡.通道分别单独进行设计与封装. 2. 所有的外部操作接口都封装在卡类这一类. 3. 在我的项目中,在卡类这一级还增加了适配器或者代理,分别实现了Adapter或Pro ...
- 怎么控制物联网卡的流量使用?
随着时代的发展,物联网卡俨然成为了一种新的发展趋势,他也在被越来越多的人所熟知认识.不过,虽然物联网卡的发展十分迅速,但是相信还是有相当大的一部分人对于物联网卡是不是很熟悉吧,那接下来我就来简单的介绍 ...
最新文章
- 【Leetcode】刷题之路3(python版)
- rsync安装与配置使用 数据同步方案(centos6.5)
- 【福利】计算机公开课合集(视频教程)
- MySQL之TCL(事务控制)语句
- SQL Server 建立索引视图并查看性能状况
- JDBC案例-用java操作数据库增删改查
- 【T3】运行时错误3709
- mysql数据库连接池锁_数据库连接池deadlock
- 微信公众号文章如何设置关键词自动回复链接
- 小程序or网页前端CSS选择器
- 迎合老板还是员工 结果导向CRM更受欢迎
- 普通路由器改4g路由器_4G工业路由器物联卡批发价格是多少?良心厂家推荐
- CrateDB三机三节点部署(Docker Overlay网络)
- i710750h和r74800h玩游戏哪个好 r7 4800h和i7 10750h哪个性能好
- anaconda3配置python2.7环境_Anaconda3+python3环境下如何创建python2环境(win+Linux下适用,同一个anaconda下py2/3共存)...
- 大O表示法(复杂度分析)
- 我是如何诱骗你的-高级钓鱼技术
- 微信聊天中上怎么用计算机,电脑可以上微信吗,教您电脑怎么用微信
- 2021福建往届高考成绩查询,2021福建省地区高考成绩排名查询,福建省高考各高中成绩喜报榜单...
- 零基础请进,影视解说必备的5个工具|不可错过的免费配音软件
热门文章
- swift调用api接口_如何在Swift中进行API调用
- 按键精灵post请求_[教程] 以本论坛为例,手把手教你使用按键精灵POST登陆网页...
- 线性回归中的交互效应(interaction)
- 超越阿里云,华为云服务器究竟有多厉害!
- 线性代数学习笔记——第六讲——矩阵的转置
- 计算机论文英文摘要范文,毕业论文英文摘要范文三篇
- html自动排版 vs,Visual Stidio Code (vscode)自定义HTML页面自动生成格式
- 成功三步曲:有勇、有谋、有德
- Android 传感器概述
- Ubuntu查看有线网卡eth0和eth1分别对应网卡型号