语音卡应用编程实例

通讯地址:辽河油田油建二公司人教科张辉 邮编:124012
电子邮件:zhanghui@lh.cnpc.com.cn

目前电话语音产品已在各方面得到广泛应用,常用的语音卡具有4线或8线通道,可以同时处理4线或8线电话的请求。以下介绍利用语音卡实现计算机自动应答的医疗及养老帐户金语音查询系统。
系统功能
当外线电话打入时,计算机自动检测到振铃信号,并开始播放提示音,同时开始接收用户的电话按键信息。用户通过电话按键选择查询类别、输入身份证号码、查询年度,计算机根据接收的信息从后台ORACLE数据库中取得查询结果数据,并将相应帐户金额数据进行语音合成,再通过语音卡的相应外线电话通道播放查询结果,例如:"姓名张三 年度1999您的医疗帐户金余额是一千二百三十四元五角六分 上年利息一百二十三元 统筹金划入二十三元四角 个人缴纳二十八元五角 帐户内报销八百零八元八角八分"。用户端电话接听所查帐户数据的语音信号。
编程思路
系统应划分为6个运行阶段:
1、 初始化语音卡、连接数据库,等待外线电话打入。检测到振铃后进入下一阶段。
2、 接收用户选择的查询类别。
播放提示音:"欢迎使用,查询医疗帐户请拨1,查询养老帐户请拨2,查询离退休金请拨3"。用户选择1-3后进入下一阶段。默认选择为1。
3、 接收用户输入的身份证号码。
播放提示音:"请您输入身份证号码"。用户输入后,系统判断数据库中是否存在此身份证号码,如果存在,则进入下一阶段。否则提示重新输入。
4、 接收用户输入查询年度。
播放提示音:"请您输入查询年度"。用户输入后,生成查询条件,取得查询数据。进入下一阶段。
5、 合成及播放姓名语音。
6、 帐户金数额语音合成及播放。
具体实现
由于电话语音卡的编程接口以windows动态链接库(TW8VID32.DLL)方式提供,可以使用目前常用的可视化开发工具,如:delphi ,vb, pb, visual c++等。下面以PB环境举例说明。
首先建立一个新的application ,一个新的窗口yyk,在application的open事件中,连接后台ORACLE数据库,并对语音卡进行初始化。设置窗口的定时器。也可以在窗口yyk中设置一些代表各个通道当前状态的提示文本,在系统响应用户按键时可以随时更新提示文本,以反映各通道的工作状态。

函数声明Global external functions ,以及常量定义
FUNCTION int TV_Installed() library "tw8vid32.dll"
SUBROUTINE TV_Initialize() library "tw8vid32.dll"
SUBROUTINE TV_Disable() library"tw8vid32.dll"
FUNCTION int TV_ChannelType(int chno) library"tw8vid32.dll"
FUNCTION int TV_OffHookDetect(int chno) library"tw8vid32.dll"
FUNCTION int TV_RingDetect(int chno) library"tw8vid32.dll"
......................略
详细的函数声明附录在最后。

定义结构ch_stru
{    string Fname //通道放音文件名
    int wstate //通道状态
    int jieduan //运行阶段
    int cx_select //查询类型
    string sfzhm //身份证号码
    string nd //查询年度
    string xingmin //姓名
    string sentence //通道放音字符 }

定义全局变量ch_stru channel[8]
            int chnum
定义application的open事件
integer i
string ls_startupfile
l_startupfile = "yyk.ini"
//设置数据库事务对象参数
sqlca.DBMS = ProfileString (l_startupfile, "database", "dbms", "")
sqlca.database = ProfileString (l_startupfile, "database", "database", "")
sqlca.userid = ProfileString (l_startupfile, "database", "userid", "")
sqlca.dbpass = ProfileString (l_startupfile, "database", "dbpass", "")
sqlca.logid = ProfileString (l_startupfile, "database", "logid", "")
sqlca.logpass = ProfileString (l_startupfile, "database", "LogPassWord", "")
sqlca.servername = ProfileString (l_startupfile, "database", "servername", "")
sqlca.dbparm = ProfileString (l_startupfile, "database", "dbparm", "")
connect; //连接数据库
if sqlca.sqlcode <> 0 then
MessageBox ("不能连通数据库", sqlca.sqlerrtext)
return
end if
open(yyk)
if timer(0.06,yyk)=-1 then
MessageBox ("错误提示","设置定时器失败, 程序不能执行!")
    return
end if
chnum=tv_installed()
if chnum<=0 then
MessageBox ("错误提示","未安装语音卡!")
else
    tv_initialize() //初始化语音卡
    if chnum>8 then
        chnum=8
    end if
    initchannel () //初始化各通道
end if
//application的open事件定义结束

定义函数initchannel (),初始化各通道结构channel[i]
for i=1 to 8
    channel[i].FName="welcome.tw"
    channel[i].wstate=WS_FREE
    channel[i].jieduan=1
    channel[i].cx_select=1
    channel[i].sfzhm=''
    channel[i].nd=''
    channel[i].xingmin=''
    channel[i].sentence=" "
    if i>chnum then
        channel[i].chtype = CT_EMPTY
    else
        channel[i].chtype=tv_channelType(i -1) //判断通道类型,外线或内线或空
    end if
next
//退出应用时,使语音卡无效。
if chnum>0 then
    tv_disable()
end if
disconnect using sqlca ; //取消连接数据库

//在窗口yyk的timer事件中处理各通道的请求
int i
for i=1 to chnum
            if channel[i].chtype=1 then
                //如果是外线通道,处理请求
                externalyyk (i) //自定义函数
            end if
next

自定义函数externalyyk (int chno)定义如下:
// 函数externalyyk ()开始
long retval
integer DtmfVal,temp
unsignedinteger sigtype
double num
string strRet, password,yyk_path,xm_temp
CHOOSE CASE channel[chno].jieduan
case 1 //选择查询类别
       
CHOOSE CASE channel[chno].wstate
    CASE WS_FREE
        if tv_ringdetect(chno -1) > 1 then //检测到振铃
            channel[chno].wstate=WS_STARTFILE
            tv_offhookctrl(chno -1) //控制摘机
            tv_flushdtmf(chno -1) //清空某通道的双音多频码(dtmf)
    end if
    case WS_STARTFILE
//开始播放提示音,"欢迎使用,查询医疗帐户请拨1,查询养老帐户......"            
            f_start_file(chno,WS_ONFILE)
//自定义函数f_start_file(int chno ,int next_state) 定义如下:
//        long retval
//启动某通道文件放音
//    retval=tv_startplayfile(ch_no -1,channel[ch_no].FName,0,300000)
//        if retval<=0 then
//            tv_hangupctrl(ch_no -1) //如果启动放音失败则挂断
//             channel[ch_no].wstate=WS_FREE
//             channel[ch_no].jieduan=1
//            设置提示音文件
//             channel[ch_no].FName="welcome.tw"
//        else
//             否则改变通道状态标志
//             channel[ch_no].wstate=next_state
//        end if
//       
//        return 1
case WS_ONFILE
        //如果检测到忙音,则停止放提示音,并控制挂断。
        if tv_monitorbusy(chno -1,SIG_BUSY1,5)<>0 or tv_monitorbusy(chno -1,SIG_BUSY2,5)<>0 then
            tv_stopplayfile(chno -1)
            channel[chno].wstate=WS_FREE
            tv_hangupctrl(chno -1)
            channel[chno].jieduan=1
        else
        //否则继续播放剩余提示音
            retval=tv_playfilerest(chno -1)
            if retval<=0 then //如果提示音播放完毕
                //设置等待接收双音多频码DTMF的时间为35秒
                tv_starttimer(chno -1,35)
                //准备转到接收双音多频码DTMF
                channel[chno].wstate=WS_WAITDTMF
            else
                DtmfVal=tv_getdtmfchar(chno -1) //检测用户按键信息
                if DtmfVal<>-1 then
                    tv_stopplayfile(chno -1) //检测到按键,停止播放提示音
                    channel[chno].wstate=WS_WAITDTMF
                    if char(DtmfVal)<>'*' and char(DtmfVal)<>'#' then
                        channel[chno].DtmfStr=""
                        channel[chno].DtmfStr=channel[chno].dtmfstr+char(dtmfval)
                        if len(channel[chno].dtmfstr)>=1 then
                            channel[chno].wstate=WS_STARTFILE
                            channel[chno].jieduan=2 //准备转到身份证输入部分
                            channel[chno].FName="srsfzhm.tw" //设置提示音文件,提示输入身份证
                            if integer(left(channel[chno].dtmfstr,1)) > 3 or integer(left(channel[chno].dtmfstr,1)) < 1 then
                                channel[chno].cx_select=1 //默认选择为1
                            else
                                channel[chno].cx_select=integer(left(channel[chno].dtmfstr,1))
                            end if
                        end if
                    end if
        end if
            end if
        end if
    case WS_WAITDTMF
        DtmfVal=tv_getdtmfchar(chno -1) //检测用户按键信息
        if DtmfVal<>-1 then //检测到按键
            channel[chno].wstate=WS_WAITDTMF
            if char(DtmfVal)<>'*' and char(DtmfVal)<>'#' then
                channel[chno].DtmfStr=""
                channel[chno].DtmfStr=channel[chno].dtmfstr+char(dtmfval)
                if len(channel[chno].dtmfstr)>=1 then
                    channel[chno].wstate=WS_STARTFILE
                    channel[chno].jieduan=2 //准备转到接收身份证号部分
                    channel[chno].FName="srsfzhm.tw" //设置放音文件名,提示输入身份证号码
                    if integer(left(channel[chno].dtmfstr,1)) > 3 or integer(left(channel[chno].dtmfstr,1)) < 1 then
                        channel[chno].cx_select=1 //默认选择为1(查询医疗帐户)
                    else
                        channel[chno].cx_select=integer(left(channel[chno].dtmfstr,1))
                    end if
                end if
            end if            
           
        else //未检测到用户按键信息
            if tv_monitorbusy(chno -1,SIG_BUSY1,5)<>0 or tv_monitorbusy(chno -1,SIG_BUSY2,5)<>0 then
                channel[chno].wstate=WS_FREE //检测到忙音,挂机,改变通道状态为空闲
                tv_hangupctrl(chno -1)
            else
                if tv_timerelapsed(chno -1)<0 then
                    channel[chno].wstate=WS_FREE //等待接收Dtmf数据码超时,挂机
                    tv_hangupctrl(chno -1)
                end if
            end if
        end if
    end choose
case 2 //获取身份证号部分
       
CHOOSE CASE channel[chno].wstate
    case WS_STARTFILE
        f_start_file(chno,WS_ONFILE)
case WS_ONFILE
//........省略,与前面类似
    case WS_WAITDTMF
//........省略,与前面类似
    case WS_GETDTMF
//..............省略
            if len(channel[chno].dtmfstr)=15 then
                channel[chno].sfzhm=channel[chno].dtmfstr //得到身份证号码(15位)
                //准备转到查询数据库中是否存在此身份证号部分
                channel[chno].wstate=WS_looksfzhmfromdb
            end if
    case WS_looksfzhmfromdb
        channel[chno].a1=0
        //判断数据库中是否存在所输的身份证号码
        choose case channel[chno].cx_select
            case 1 //从数据库中医疗帐户表中查找
                //a1>=1表示数据库中存在所输的身份证号码
                channel[chno].a1=f_count_yiliao(channel[chno].sfzhm)
            case 2 //从数据库中养老帐户表中查找
                channel[chno].a1=f_count_yanglao(channel[chno].sfzhm)
            case 3 //从数据库中离退休表中查找
                channel[chno].a1=f_count_lituixiu(channel[chno].sfzhm)
        end choose
        //如果数据库中存在所输的身份证号码
                if channel[chno].a1 >= 1 then
                    //从数据库中获取姓名
                    choose case channel[chno].cx_select
                        case 3
                            channel[chno].xingmin=f_getxingmin_lituixiu(chno)
                        case 2
                            channel[chno].xingmin=f_getxingmin_yanglao(chno)
                        case 1
                            channel[chno].xingmin=f_getxingmin_yiliao(chno)
                    end choose
                        channel[chno].wstate=WS_STARTFILE
                        channel[chno].jieduan=4 //准备转到接收查询年度部分
                        channel[chno].FName="srnd.tw" //设置放音文件名,提示输入查询年度
                else
                    //数据库中不存在所输的身份证号码
                        channel[chno].wstate=WS_STARTFILE
                        channel[chno].jieduan=2 //准备转到接收身份证号码部分
                        //设置放音文件名,身份证号码有误或为找到,请重输
                        channel[chno].FName="nosfzhm.tw"
                end if   
    end choose
case 4 //获取年度部分
CHOOSE CASE channel[chno].wstate       
    case WS_STARTFILE
        f_start_file(chno,WS_ONFILE)
case WS_ONFILE
        //........省略,与前面类似
    case WS_WAITDTMF
        //........省略,与前面类似
    case WS_GETDTMF
        //........省略,与前面类似
        channel[chno].dtmfstr=channel[chno].dtmfstr+char(DtmfVal)
        if len(channel[chno].dtmfstr)=4 then //如果接收到四位代表年度的按键
            channel[chno].wstate=WS_retrievedatafromdb //转到检索数据部分
        end if
    case WS_retrievedatafromdb
            channel[chno].nd=channel[chno].dtmfstr //赋值年度
            if channel[chno].cx_select=1 then //查询医疗帐户
                if integer(left(channel[chno].dtmfstr,4)) < 1996 then
                    channel[chno].dtmfstr='1996'
                    channel[chno].nd='1996'
                end if
                if integer(left(channel[chno].dtmfstr,4)) > year(today()) then
                    channel[chno].dtmfstr=string(today(),"yyyy")
                    channel[chno].nd=string(today(),"yyyy")
                end if                
                //检索帐户内数据,例如上年余额,利息,统筹金划入,个人交纳,帐户内报销等
                f_getdata_yiliao(chno)
//自定义函数f_getdata_yiliao(int i_chno)定义如下
//real aa1,aa2,aa3,aa4,aa5,aa6
//string sfz,s_nd
//sfz=channel[i_chno].sfzhm
//s_nd=channel[i_chno].nd
// SELECT "QA39"."SNYE",
// "QA39"."SNLX",
// "QA39"."DWHR",
// "QA39"."GRJN",
// "QA39"."ZHNBX"
// INTO :aa2,
// :aa3,
// :aa4,
// :aa5,
// :aa6
// FROM "QA39"
// WHERE ( "QA39"."SFZHM" = :sfz ) AND
// ( "QA39"."SJ" = :s_nd ) ;
//        aa1 = aa2 + aa3 + aa4 + aa5 - aa6
//channel[i_chno].a1=Round(aa1,2)
//channel[i_chno].a2=Round(aa2,2)
//channel[i_chno].a3=Round(aa3,2)
//channel[i_chno].a4=Round(aa4,2)
//channel[i_chno].a5=Round(aa5,2)
//channel[i_chno].a6=Round(aa6,2)
//return 1
                channel[chno].wstate=WS_STARTFILE
                channel[chno].jieduan=5 //准备转到播放姓名部分
                channel[chno].FName="ndxm.tw"     //提示音文件,提示音"您的姓名"
            end if
            //养老帐户机离退休金省略
            ....
END CHOOSE
case 5 //播放姓名语音
CHOOSE CASE channel[chno].wstate
    CASE WS_STARTFILE
        //播放姓名语音"您的姓名"
        f_start_file(chno,WS_ONFILE)
case WS_ONFILE
        f_on_file(chno,WS_startoutputxingmin)
//自定义函数f_on_file(int ch_no,int next_state)定义如下:
//long retval
//    if tv_monitorbusy(ch_no -1,SIG_BUSY1,5)<>0 or tv_monitorbusy(ch_no -1,SIG_BUSY2,5)<>0 then
//            tv_stopplayfile(ch_no -1)
//             channel[ch_no].wstate=WS_FREE
//            tv_hangupctrl(ch_no -1)
//             channel[ch_no].jieduan=1
//             channel[ch_no].FName="welcome.tw"
//        else
//             retval=tv_playfilerest(ch_no -1) //继续播放剩余提示音
//            if retval<=0 then
//                 channel[ch_no].wstate=next_state
//            end if
//        end if
//        return 1
    CASE WS_startoutputxingmin
        password="12345678" //语音合成库口令
        yyk_path="" //语音合成库路径,当前路径
        temp=PasswordDetect(password,yyk_path)
        if temp < 0 then //如果语音合成库出错,则挂机
            tv_hangupctrl(chno -1)
            channel[chno].wstate=WS_FREE
            channel[chno].jieduan=1
            channel[chno].FName="welcome.tw"
        else
            xm_temp=trim(channel[chno].xingmin)
            retval=TV_StartPlayCh(chno -1,xm_temp) //播放姓名语音
            if retval < 0 then //如果播放姓名语音出错,挂机
                tv_hangupctrl(chno -1)
                channel[chno].wstate=WS_FREE
                channel[chno].jieduan=1
                channel[chno].FName="welcome.tw"
            else
                channel[chno].wstate=WS_onoutputxingmin
            end if
        end if
    case WS_onoutputxingmin
        if tv_monitorbusy(chno -1,SIG_BUSY1,5)<>0 or tv_monitorbusy(chno -1,SIG_BUSY2,5)<>0 then
            tv_stopplaych(chno -1)
            channel[chno].wstate=WS_FREE
            tv_hangupctrl(chno -1)
            channel[chno].jieduan=1
            channel[chno].FName="welcome.tw"
        else
            retval=tv_playchrest(chno -1) //继续播放姓名语音剩余部分
            if retval<=0 then //播放姓名语音完毕
                choose case channel[chno].cx_select
                    case 1 //yiliao
                        channel[chno].wstate=WS_yiliao_nd
                        channel[chno].jieduan=7 //准备转到播放医疗帐户数据部分
                        channel[chno].FName="nd.tw" //设置放音文件名,提示所查年度
                    case 2
                        .....
                    case 3
                        .....
                end choose
            end if
        end if        
end choose
case 6 //播放离退休金数据略

case 7 //播放医疗帐户数据
CHOOSE CASE channel[chno].wstate
    case WS_yiliao_nd
        f_start_file(chno,WS_yiliao_on_nd) //播放年度提示语音
    case WS_yiliao_on_nd       
        f_on_file(chno,WS_yiliao_nd_data)
    case WS_yiliao_nd_data
        f_start_year(chno,channel[chno].nd,WS_yiliao_on_nd_data) //播放年度数据语音
    case WS_yiliao_on_nd_data       
        f_onmoney(chno,WS_yiliao_a1,"ye.tw")        
//自定以函数f_onmoney(int ch_no,int next_state,string fname)如下:        
//long     retval
//        if tv_monitorbusy(ch_no -1,SIG_BUSY1,5)<>0 or tv_monitorbusy(ch_no -1, SIG_BUSY2,5)<>0 then
//             channel[ch_no].wstate=WS_FREE
//            tv_stopplayfile(ch_no -1)
//            tv_hangupctrl(ch_no -1)
//             channel[ch_no].jieduan=1
//             channel[ch_no].FName="welcome.tw"
//        else
//             retval=tv_playsentencerest(ch_no -1) //继续播放剩余的放音字符
//            if retval<=0 then
//                 channel[ch_no].wstate=next_state
//                 channel[ch_no].FName=fname
//            end if
//        end if
//        return 1        
    case WS_yiliao_a1
        f_start_file(chno,WS_on_yiliao_a1)
case WS_on_yiliao_a1
        f_on_file(chno,WS_yiliao_a1_data)
    case WS_yiliao_a1_data
        f_startmoney(chno,channel[chno].a1,WS_on_yiliao_a1_data)
//自定以函数f_startmoney(int ch_no,real data_a,int next_state)如下:
//long retval
//double num
//        num=double(data_a)/1.0
// 赋值生成的放音字符串,makemoney(num)对给定的数生成xx千x百X十X元X角X分放音字符
//        channel[ch_no].sentence=makemoney(num)
//        播放帐户金额语音
//        retval=tv_playsentence(ch_no -1,channel[ch_no].sentence)
//        if retval<=0 then //         播放帐户金额语音失败
//             channel[ch_no].wstate=WS_FREE
//            tv_hangupctrl(ch_no -1)
//             channel[ch_no].jieduan=1
//             channel[ch_no].FName="welcome.tw"
//        else
//             channel[ch_no].wstate=next_state
//        end if
//        return 1
//自定以函数makemoney(real num)
//string strTmp
//string strRet
//double yuan, jiao, fen
//if money=0 then
//    strRet=char(2)
//    strRet=strRet+char(19)
//    return strRet
//end if
//strRet=""
//strTmp=space(60)
//if money<0 then
//    strRet=strRet+char(18)
// money=abs(money)
//end if
//yuan=truncate(money,0)
//money=(money - yuan)*10.0
//jiao=truncate(money,0)
//money=(money - jiao)*10.0
//fen = truncate(money,0)
//if (yuan>0) then
//    tv_MakeSentence(yuan,strTmp) //生成多文件放音字符串
//    strRet=strRet + strTmp
////    strRet=strRet + strTmp + char(19) //元
//end if
//if jiao=0 then
//    if fen>0 then
//        strRet=strRet+char(2)+char(fen+2)+char(21)
// end if
//else
//    strRet=strRet+char(jiao+2)+char(20) // 角
//    if fen>0 then
//        strRet=strRet+char(fen+2)+char(21) // 分
//    end if
//end if
//return strRet       
    case WS_on_yiliao_a1_data
        f_onmoney(chno,WS_yiliao_a2,"snye.tw")
//播放"上年余额"数据语音
    case WS_yiliao_a2
        f_start_file(chno,WS_on_yiliao_a2)
case WS_on_yiliao_a2
        f_on_file(chno,WS_yiliao_a2_data)
    case WS_yiliao_a2_data
        f_startmoney(chno,channel[chno].a2,WS_on_yiliao_a2_data)
    case WS_on_yiliao_a2_data
        f_onmoney(chno,WS_yiliao_a3,"snlx.tw")
//播放"上年利息"数据语音等
    case WS_yiliao_a3
....
    case WS_on_yiliao_a3_data
            retval=tv_playsentencerest(chno -1)
            if retval<=0 then
                channel[chno].wstate=WS_STARTFILE
                channel[chno].jieduan=1
                channel[chno].FName="welcome.tw"
            end if
END CHOOSE
case 8 //播放养老帐户数据略
END CHOOSE
// 函数externalyyk ()结束
应用效果
本系统已经应用于油田采油厂,方便了人们对帐户金的查询。无论距离多远,仅需使用电话就可以得到所需信息,全天24小时随时提供查询服务。达到了系统设计要求,具有准确性、易于操作的特点。

附录
//设置函数声明,设置系统常量
FUNCTION int TV_Installed() library "tw8vid32.dll"
SUBROUTINE TV_Initialize() library "tw8vid32.dll"
SUBROUTINE TV_Disable() library"tw8vid32.dll"
FUNCTION int TV_ChannelType(int chno) library"tw8vid32.dll"
FUNCTION int TV_OffHookDetect(int chno) library"tw8vid32.dll"
FUNCTION int TV_RingDetect(int chno) library"tw8vid32.dll"
FUNCTION unsignedint TV_StartPlay(int chno,string sp,unsignedint play) library"tw8vid32.dll"
FUNCTION unsignedint TV_StopPlay(int chno) library"tw8vid32.dll"
FUNCTION unsignedint TV_PlayRest(int chno) library"tw8vid32.dll"
FUNCTION long TV_StartPlayFile(int chno,string sp,long long_min,long long_max) library"tw8vid32.dll"
FUNCTION long TV_PlayFileRest(int chno) library"tw8vid32.dll"
FUNCTION long TV_StopPlayFile(int chno) library"tw8vid32.dll"
SUBROUTINE TV_MakeSentence(double double_test, REF string sp) library"tw8vid32.dll"
FUNCTION long TV_PlaySentence(int chno,string sp) library"tw8vid32.dll"
FUNCTION long TV_PlaySentenceRest(int chno) library"tw8vid32.dll"
SUBROUTINE TV_FlushDTMF(int chno) library"tw8vid32.dll"
FUNCTION int TV_GetDTMFChar(int chno) library"tw8vid32.dll"
FUNCTiON string TV_GetDTMFStr(int chno) library"tw8vid32.dll"
FUNCTION int TV_CheckSignal(int chno,int int1,int int2) library"tw8vid32.dll"
FUNCTION int TV_ListenerOffHook(int chno) library"tw8vid32.dll"
SUBROUTINE TV_StartMonitor(int chno) library"tw8vid32.dll"
FUNCTION int TV_MonitorOffHook(int chno,int tirme) library"tw8vid32.dll"
FUNCTION int TV_MonitorBusy(int chno,int int1,int int2) library"tw8vid32.dll"
SUBROUTINE TV_StartTimer(int chno,long timer) library"tw8vid32.dll"
FUNCTION long TV_TimerElapsed(int chno) library"tw8vid32.dll"
SUBROUTINE TV_SetVoicei(int num,string fn) library"tw8vid32.dll"
FUNCTION int PasswordDetect(string password,string path) library"Playch32.dll"
FUNCTION int TV_StartPlayCh(int chn,string sentence) library"Playch32.dll"
FUNCTION int TV_PlayChRest(int chn) library"Playch32.dll"
FUNCTION int TV_StopPlayCh(int chn) library"Playch32.dll"
CONSTANT Integer WS_NULL=0
CONSTANT Integer WS_FREE=1
CONSTANT Integer WS_STARTFILE=2
CONSTANT Integer WS_ONFILE=3
CONSTANT Integer WS_WAITDTMF=4
CONSTANT Integer WS_GETDTMF=5
CONSTANT Integer WS_STARTSENTENCE=6
CONSTANT Integer WS_ONSENTENCE=7
CONSTANT Integer WS_STARTMONEY=8
CONSTANT Integer WS_ONMONEY=9
CONSTANT Integer WS_WAITEND=10
CONSTANT Integer WS_looksfzhmfromdb=11
CONSTANT Integer WS_retrievedatafromdb=12
CONSTANT Integer WS_startoutputxingmin=13
CONSTANT Integer WS_onoutputxingmin=14
CONSTANT Integer WS_yiliao_nd=16
CONSTANT Integer WS_yiliao_on_nd=18
CONSTANT Integer WS_yiliao_nd_data =100
CONSTANT Integer WS_yiliao_on_nd_data =101
CONSTANT Integer WS_yiliao_a1 =40
CONSTANT Integer WS_on_yiliao_a1 =41
CONSTANT Integer WS_yiliao_a1_data =42
CONSTANT Integer WS_on_yiliao_a1_data =43
CONSTANT Integer WS_yiliao_a2 =44
CONSTANT Integer WS_on_yiliao_a2 =45
CONSTANT Integer WS_yiliao_a2_data =46
CONSTANT Integer WS_on_yiliao_a2_data =47
CONSTANT Integer WS_yiliao_a3 =48
CONSTANT Integer WS_on_yiliao_a3 =49
CONSTANT Integer WS_yiliao_a3_data =50
CONSTANT Integer WS_on_yiliao_a3_data =51