[转载]关于讯飞语音SDK开发学习 - 或、许 - 博客园

[转载]关于讯飞语音SDK开发学习 – 或、许 – 博客园.

前奏,浑浑噩噩已经工作一年多,这一年多收获还是挺多的。逛园子应该有两年多了,工作后基本上是天天都会来园子逛逛,园子 里还是有很多牛人写了一些不错的博客,帮我解决很多问题。但是一直没写过博客,归根到底一个字“懒”,还有就是不知道该写 些什么…

今 天把我最近研究讯飞语音东东,分享一下,不过有些还是前辈们提供的。之前公司让我做一个小的语音识别功能,一开始我就建议使用讯飞语音,个人觉得讯飞识别 正确率还是可观的。可是老总说不能考 虑联网,还有就是钱的问题。想到微软自带语音识别引擎(基于win7)。第一次接触到语音识别,没什么头绪,只有收集相关资料 。最后成品出来了,但是识别效果不是那么满意,老总说那就将就用吧,我想他都那样说了,我也没多大意见…开年后老总老总 买了个iphone5玩了siri后,觉得我们现在那个语音太丑陋了,让换一个解决方案,识别率要达到90%。国内有好几家公司做语音识 别的比如科大讯飞、云知声、捷通华声以及紫冬锐意语音都做了一定开放。市面上我知道语音助手有百度语音助手、虫洞语音助手 、360语音助手以及科大讯飞语点;前两个我不知道采用那家公司的还是自己研发的不过都没开开放,360语音助手采用讯飞的。然 后我就继续提议使用讯飞语音SDK,于是乎同事们都下载讯飞语点来玩玩,老总说那就试试讯飞语音SDK。

先 做一个简单demo,看看识别效果,感觉识别率上能够满足要求。一般要的结果不光只是要把所说的话翻译成文字,而是需要的是 语义的理解:例如我要去北京,直接返回北京这个关键。目前讯飞还没把这个接口开放出来,公司负责人说今年会把这个开放出来 。那现在只能使用关键词识别语法,一种是直接是文本词库;另一种是ABNF语法。ABNF写法有点烦杂(语法文件里使用到的词句都是指定的,对于无法枚举 的词句暂时没有很好的解决办法。),就直接采用文本词库(因为关键词有点多)。讯飞还有专门人负责关于讯飞语音问题解答(QQ群:153789256)。

讯飞提供msc.dll这个DLL,调用DLL的封装:

/// <summary>
        /// MSCDLL入口封装
        /// </summary>
        private class MscDll
        {
            #region MscDLL
           
            /// <summary>
            /// 初始化MSC的ISR部分
            /// </summary>
            /// <param name="configs">初始化时传入的字符串,以指定合成用到的一些配置参数,各个参数以“参数名=参数值”的形式出现,大小写不敏感,不同的参数之间以“,”或“\n”隔开,不设置任何值时可以传入NULL或空串:</param>
            /// <returns>如果函数调用成功返回MSP_SUCCESS,否则返回错误代码,错误代码参见msp_errors</returns>
            [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
            public static extern int QISRInit(string configs);
           
            /// <summary>
            /// 开始一个ISR会话
            /// </summary>
            /// <param name="grammarList">uri-list格式的语法,可以是一个语法文件的URL或者一个引擎内置语法列表。可以同时指定多个语法,不同的语法之间以“,”
            /// 隔开。进行语音听写时不需要语法,此参数设定为NULL或空串即可;进行语音识别时则需要语法,语法可以在此参数中指定,也可以随后调用QISRGrammarActivate指定识别所用的语法。</param>
            /// <param name="_params">本路ISR会话使用的参数,可设置的参数及其取值范围请参考《可设置参数列表_MSP20.xls》,各个参数以“参数名=参数值” 的形式出现,不同的参数之间以“,”或者“\n”隔开。</param>
            /// <param name="errorCode">如果函数调用成功则其值为MSP_SUCCESS,否则返回错误代码,错误代码参见msp_errors。几个主要的返回值: MSP_ERROR_NOT_INIT 未初始化 MSP_ERROR_INVALID_PARA 无效的参数; MSP_ERROR_NO_LICENSE 开始一路会话失败</param>
            /// <returns>MSC为本路会话建立的ID,用来唯一的标识本路会话,供以后调用其他函数时使用。函数调用失败则会返回NULL。</returns>
            [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr QISRSessionBegin(string grammarList, string _params, ref int errorCode);
           
            /// <summary>
            /// 传入语法
            /// </summary>
            /// <param name="sessionID">由QISRSessionBegin返回过来的会话ID</param>
            /// <param name="grammar">语法字符串</param>
            /// <param name="type">语法类型,可以是uri-list、abnf、xml等</param>
            /// <param name="weight">本次传入语法的权重,本参数在MSP 2.0中会被忽略。</param>
            /// <returns>如果函数调用成功返回MSP_SUCCESS,否则返回错误代码,错误代码参见msp_errors</returns>
            [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
            public static extern int QISRGrammarActivate(string sessionID, string grammar, string type, int weight);

            /// <summary>
            /// 写入用来识别的语音
            /// </summary>
            /// <param name="sessionID">由QISRSessionBegin返回过来的会话ID</param>
            /// <param name="waveData">音频数据缓冲区起始地址</param>
            /// <param name="waveLen">音频数据长度,其大小不能超过设定的max_audio_size</param>
            /// <param name="audioStatus">用来指明用户本次识别的音频是否发送完毕,可能值如下:
            /// MSP_AUDIO_SAMPLE_FIRST = 1 第一块音频
            /// MSP_AUDIO_SAMPLE_CONTINUE = 2 还有后继音频
            /// MSP_AUDIO_SAMPLE_LAST = 4 最后一块音频</param>           
            /// <param name="epStatus">端点检测(End-point detected)器所处的状态,可能的值如下:
            /// MSP _EP_LOOKING_FOR_SPEECH = 0 还没有检测到音频的前端点。
            /// MSP _EP_IN_SPEECH = 1 已经检测到了音频前端点,正在进行正常的音频处理。
            /// MSP _EP_AFTER_SPEECH = 3 检测到音频的后端点,后继的音频会被MSC忽略。
            /// MSP _EP_TIMEOUT = 4 超时。
            /// MSP _EP_ERROR= 5 出现错误。
            /// MSP _EP_MAX_SPEECH = 6 音频过大。</param>
            /// <param name="recogStatus">识别器所处的状态</param>
            /// <returns></returns>
            [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
            public static extern int QISRAudioWrite(string sessionID, byte[] waveData, uint waveLen, AudioStatus audioStatus, ref  EpStatus epStatus, ref RecogStatus recogStatus);

            /// <summary>
            /// 获取识别结果
            /// </summary>
            /// <param name="sessionID">由QISRSessionBegin返回过来的会话ID</param>
            /// <param name="rsltStatus">识别结果的状态,其取值范围和含义请参考QISRAudioWrite的参数recogStatus</param>
            /// <param name="waitTime">与服务器交互的间隔时间,可以控制和服务器的交互频度。单位为ms,建议取值为5000</param>
            /// <param name="errorCode">如果函数调用成功返回MSP_SUCCESS,否则返回错误代码,错误代码参见msp_errors</param>
            /// <returns>函数执行成功并且获取到识别结果时返回识别结果,函数执行成功没有获取到识别结果时返回NULL</returns>
            [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr QISRGetResult(string sessionID, ref RecogStatus rsltStatus, int waitTime, ref int errorCode);

            /// <summary>
            /// 结束一路会话
            /// </summary>
            /// <param name="sessionID">由QISRSessionBegin返回过来的会话ID</param>
            /// <param name="hints">结束本次会话的原因描述,用于记录日志,便于用户查阅或者跟踪某些问题</param>
            /// <returns></returns>
            [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
            public static extern int QISRSessionEnd(string sessionID, string hints);

            /// <summary>
            /// 获取与识别交互相关的参数
            /// </summary>
            /// <param name="sessionID">由QISRSessionBegin返回过来的会话ID</param>
            /// <param name="paramName">要获取的参数名称;支持同时查询多个参数,查询多个参数时,参数名称按“,” 或“\n”分隔开来</param>
            /// <param name="paramValue">获取的参数值,以字符串形式返回;查询多个参数时,参数值之间以“;”分开,不支持的参数将返回空的值</param>
            /// <param name="valueLen">参数值的长度</param>
            /// <returns></returns>
            [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
            public static extern int QISRGetParam(string sessionID, string paramName, string paramValue, ref uint valueLen);

            /// <summary>
            /// 逆初始化MSC的ISR部分
            /// </summary>
            /// <returns></returns>
            [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
            public static extern int QISRFini();

            /// <summary>
            /// 上传用户自定义词库
            /// </summary>
            /// <param name="sessionID">由QISRSessionBegin返回过来的会话ID</param>
            /// <param name="dataName">词库名称</param>
            /// <param name="userData">词库数据采用是utf8格式</param>
            /// <param name="lenght">词库大小</param>
            /// <param name="paramValue">参数值</param>
            /// <param name="errorCode">如果函数调用成功返回MSP_SUCCESS,否则返回错误代码,错误代码参见msp_errors</param>
            /// <returns>函数执行成功并且返回exID(词库编号)</returns>
            [DllImport("msc.dll", CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr QISRUploadData(string sessionID, string dataName, byte[] userData, uint lenght, string paramValue, ref int errorCode);

            #endregion
        }

说明一下:“QISRUploadData”(上传词库)这个函数在开发文档里面没的,讯飞遗漏了。

具体实现(关键词识别,文本词库):

类:MscNet

#region 定义字段

        //返回错误代号
        private int ret = 0;
        private RecoErrors Re = null;
        /// <summary>
        /// 会话ID
        /// </summary>
        private string sess_id = null;
        /// <summary>
        /// 参数
        /// </summary>
        private string param = null;
        /// <summary>
        /// 语法
        /// </summary>
        private string grammar = null;
        //错误消息通知托管
        public delegate void delegdateOnerror(string Msg);
        private string path = null;
        /// <summary>
        /// 识别数据返回的事件
        /// </summary>
        public event EventHandler<DataArrivedEventArgs> DataArrived;
        /// <summary>
        /// 识别过程结束的事件
        /// </summary>
        public event EventHandler ISREnd;
        /// <summary>
        /// 正在识别
        /// </summary>
        public event EventHandler Spoting;

        #endregion

        #region 构造函数

        /// <summary>
        /// 构造函数,初始化引擎
        /// </summary>
        /// <param name="appid">appid</param>
        /// <param name="param">参数</param>      
        /// <param name="grammar">语法ID</param>
        /// <param name="path">路径</param>
        public MscNet(string appid, string param, string path, string grammar)
        {
            this.path = path;
            this.param = param;
            this.grammar = grammar;
            Re = new RecoErrors();
            //引擎初始化,只需初始化一次
            ret = MscDll.QISRInit("appid=" + appid);
            try
            {
                Re.GetError(ret);
            }
            catch (MscException ex)
            {
                RaiseError(ex.Message.ToString());
            }
        }
        #endregion

        #region 公共方法

        /// <summary>
        /// 开始识别语音
        /// </summary>
        /// <param name="buffer">音频数据</param>
        public void InterpretVoice(byte[] buffer)
        {
            //用来指明用户本次识别的音频是否发送完毕
            AudioStatus audioStatus = AudioStatus.ISR_AUDIO_SAMPLE_LAST;
            //端点检测(End-point detected)器所处的状态
            EpStatus ep_status = EpStatus.ISR_EP_NULL;
            //识别器所处的状态
            RecogStatus rec_status = RecogStatus.ISR_REC_NULL;
            //识别结果的状态
            RecogStatus rslt_status = RecogStatus.ISR_REC_NULL;
            Loadgrammar();
            int ret = MscDll.QISRAudioWrite(sess_id, buffer, (uint)buffer.Length, audioStatus, ref ep_status, ref rec_status);
            try
            {
                Re.GetError(ret);
                do
                {
                    if (rslt_status == RecogStatus.ISR_REC_STATUS_INCOMPLETE)
                    {
                        Spoting(this, new EventArgs());//通知正在识别
                    }
                    IntPtr p = MscDll.QISRGetResult(sess_id, ref rslt_status, 0, ref ret);
                    Re.GetError(ret);
                    if (p != IntPtr.Zero)
                    {
                        string tmp = PtrToStr(p);
                        DataArrived(this, new DataArrivedEventArgs(tmp));//激发识别数据到达事件                    
                    }
                    System.Threading.Thread.Sleep(500);
                } while (rslt_status != RecogStatus.ISR_REC_STATUS_SPEECH_COMPLETE);
            }
            catch (MscException ex)
            {
                RaiseError(ex.Message);
            }
            finally
            {
                try
                {
                    ret = MscDll.QISRSessionEnd(sess_id, string.Empty);
                    Re.GetError(ret);
                    ISREnd(this, new EventArgs());//通知识别结束 
                }
                catch (MscException ex)
                {
                    RaiseError(ex.Message);
                }
            }
        }

        /// <summary>
        /// 上传词库词库采用是utf8格式
        /// </summary>
        /// <param name="txtFile">词库名称</param>
        /// <param name="path">词库路径</param>
        /// <param name="param">参数</param>
        /// <returns>返回词库编号</returns>
        public string GetExID(string txtFile, string path, string param)
        {
            string filePath = Path.Combine(path, txtFile);
            string tmp = string.Empty;
            if (!string.IsNullOrEmpty(filePath))
            {
                try
                {
                    sess_id = PtrToStr(MscDll.QISRSessionBegin(null, param, ref ret));
                    Re.GetError(ret);
                    try
                    {
                        using (FileStream fs = File.Open(filePath, FileMode.Open))
                        {
                            long len = fs.Length;
                            byte[] buffer = new byte[len];
                            fs.Read(buffer, 0, (int)len);
                            IntPtr p = MscDll.QISRUploadData(sess_id, "sces", buffer, (uint)fs.Length, "dtt=keylist", ref ret);
                            Re.GetError(ret);
                            if (p != IntPtr.Zero)
                            {
                                tmp = PtrToStr(p);
                            }
                        }
                    }
                    catch (FileNotFoundException ex)
                    {
                        RaiseError(ex.Message);
                    }

                }
                catch (MscException ex)
                {
                    RaiseError(ex.Message);
                }
                finally
                {
                    try
                    {
                        ret = MscDll.QISRSessionEnd(sess_id, null);
                        Re.GetError(ret);
                    }
                    catch (MscException ex)
                    {
                        RaiseError(ex.Message.ToString());
                    }
                }
            }
            else
            {
                RaiseError("路径不正确!");
            }
            return tmp;
        }

        /// <summary>
        /// 对MSC的ISR部分进行逆初始化。
        /// </summary>
        public void QISRFini()
        {
            try
            {
                ret = MscDll.QISRFini();
                Re.GetError(ret);
            }
            catch (MscException ex)
            {
                RaiseError(ex.Message.ToString());
            }
        }

        #endregion

        #region 受保护方法
        /// <summary>
        /// 加载语法 
        /// </summary>
        private void Loadgrammar()
        {
            try
            {
                sess_id = PtrToStr(MscDll.QISRSessionBegin(grammar, param, ref ret));
                Re.GetError(ret);
            }
            catch (MscException ex)
            {
                RaiseError(ex.Message);
            }
        }

        /// <summary>
        /// 指针转字符串
        /// </summary>
        /// <param name="p">指向非托管代码字符串的指针</param>
        /// <returns>返回指针指向的字符串</returns>
        private string PtrToStr(IntPtr p)
        {
            List<byte> lb = new List<byte>();
            try
            {
                while (Marshal.ReadByte(p) != 0)
                {
                    lb.Add(Marshal.ReadByte(p));
                    p = p + 1;
                }
            }
            catch (AccessViolationException ex)
            {
                RaiseError(ex.Message);
            }
            return Encoding.Default.GetString(lb.ToArray());
        }       
        #endregion

        #region 事件
        /// <summary>
        /// 错误通知事件
        /// </summary>
        public event delegdateOnerror OnError;
        private void RaiseError(string Msg)
        {
            if (OnError != null)
            {
                OnError(Msg);
            }
        }
        /// <summary>
        /// 有识别数据返回的事件参数,包含了识别的文本结果
        /// </summary>
        public class DataArrivedEventArgs : EventArgs
        {
            public string result;
            public DataArrivedEventArgs(string rs)
            {
                result = rs;
            }
        }
        #endregion

如果采用ABNF语法,只是与文本词库加载语法方式有点不一样:

/// <summary>
        /// 加载语法 
        /// </summary>
        private void Loadgrammar()
        {
            try
            {
               
               //sess_id = PtrToStr(MscDll.QISRSessionBegin(grammar, param, ref ret));              
                /*ABNF语法*/
                sess_id = PtrToStr(MscDll.QISRSessionBegin(null, "rst=plain,sub=asr,ssm=1,aue=speex,auf=audio/L16;rate=16000,cfd=350", ref ret));
                em.GetError(ret);
                string grammar1 = "#ABNF 1.0 GB2312;\n mode voice;\n language zh-cn;\n\n\n root $main;\n public $main = 我[想要]看$place1;\n $place1=足球;\n";
                ret = MscDll.QISRGrammarActivate(sess_id, grammar1, "abnf", 0);//将语法ID传入QISRSessionBegin
                /*end */
                em.GetError(ret);             
            }
            catch (MscException ex)
            {
                RaiseError(ex.Message.ToString());
            }
        }

常量的枚举:

#region 错误代号
    enum ErrorCode
    {
        MSP_SUCCESS= 0,
        MSP_ERROR_FAIL = -1,
        MSP_ERROR_EXCEPTION = -2,

        /* General errors 10100(0x2774) */
        MSP_ERROR_GENERAL = 10100,     /* 0x2774 */
        MSP_ERROR_OUT_OF_MEMORY = 10101,     /* 0x2775 */
        MSP_ERROR_FILE_NOT_FOUND = 10102,     /* 0x2776 */
        MSP_ERROR_NOT_SUPPORT = 10103,     /* 0x2777 */
        MSP_ERROR_NOT_IMPLEMENT = 10104,     /* 0x2778 */
        MSP_ERROR_ACCESS = 10105,     /* 0x2779 */
        MSP_ERROR_INVALID_PARA = 10106,     /* 0x277A */
        MSP_ERROR_INVALID_PARA_VALUE = 10107,     /* 0x277B */
        MSP_ERROR_INVALID_HANDLE = 10108,     /* 0x277C */
        MSP_ERROR_INVALID_DATA = 10109,     /* 0x277D */
        MSP_ERROR_NO_LICENSE = 10110,     /* 0x277E */
        MSP_ERROR_NOT_INIT = 10111,     /* 0x277F */
        MSP_ERROR_NULL_HANDLE = 10112,     /* 0x2780 */
        MSP_ERROR_OVERFLOW = 10113,     /* 0x2781 */
        MSP_ERROR_TIME_OUT = 10114,     /* 0x2782 */
        MSP_ERROR_OPEN_FILE = 10115,     /* 0x2783 */
        MSP_ERROR_NOT_FOUND = 10116,     /* 0x2784 */
        MSP_ERROR_NO_ENOUGH_BUFFER = 10117,     /* 0x2785 */
        MSP_ERROR_NO_DATA = 10118,     /* 0x2786 */
        MSP_ERROR_NO_MORE_DATA = 10119,     /* 0x2787 */
        MSP_ERROR_SKIPPED = 10120,     /* 0x2788 */
        MSP_ERROR_ALREADY_EXIST = 10121,     /* 0x2789 */
        MSP_ERROR_LOAD_MODULE = 10122,     /* 0x278A */
        MSP_ERROR_BUSY = 10123,     /* 0x278B */
        MSP_ERROR_INVALID_CONFIG = 10124,     /* 0x278C */
        MSP_ERROR_VERSION_CHECK = 10125,     /* 0x278D */
        MSP_ERROR_CANCELED = 10126,     /* 0x278E */
        MSP_ERROR_INVALID_MEDIA_TYPE = 10127,     /* 0x278F */
        MSP_ERROR_CONFIG_INITIALIZE = 10128,     /* 0x2790 */
        MSP_ERROR_CREATE_HANDLE = 10129,     /* 0x2791 */
        MSP_ERROR_CODING_LIB_NOT_LOAD = 10130,     /* 0x2792 */

        /* Error codes of network 10200(0x27D8)*/
        MSP_ERROR_NET_GENERAL = 10200,     /* 0x27D8 */
        MSP_ERROR_NET_OPENSOCK = 10201,     /* 0x27D9 */   /* Open socket */
        MSP_ERROR_NET_CONNECTSOCK = 10202,     /* 0x27DA */   /* Connect socket */
        MSP_ERROR_NET_ACCEPTSOCK = 10203,     /* 0x27DB */   /* Accept socket */
        MSP_ERROR_NET_SENDSOCK = 10204,     /* 0x27DC */   /* Send socket data */
        MSP_ERROR_NET_RECVSOCK = 10205,     /* 0x27DD */   /* Recv socket data */
        MSP_ERROR_NET_INVALIDSOCK = 10206,     /* 0x27DE */   /* Invalid socket handle */
        MSP_ERROR_NET_BADADDRESS = 10207,     /* 0x27EF */   /* Bad network address */
        MSP_ERROR_NET_BINDSEQUENCE = 10208,     /* 0x27E0 */   /* Bind after listen/connect */
        MSP_ERROR_NET_NOTOPENSOCK = 10209,     /* 0x27E1 */   /* Socket is not opened */
        MSP_ERROR_NET_NOTBIND = 10210,     /* 0x27E2 */   /* Socket is not bind to an address */
        MSP_ERROR_NET_NOTLISTEN = 10211,     /* 0x27E3 */   /* Socket is not listenning */
        MSP_ERROR_NET_CONNECTCLOSE = 10212,     /* 0x27E4 */   /* The other side of connection is closed */
        MSP_ERROR_NET_NOTDGRAMSOCK = 10213,     /* 0x27E5 */   /* The socket is not datagram type */
        MSP_ERROR_NET_DNS=10214,
        /* Error codes of mssp message 10300(0x283C) */
        MSP_ERROR_MSG_GENERAL = 10300,     /* 0x283C */
        MSP_ERROR_MSG_PARSE_ERROR = 10301,     /* 0x283D */
        MSP_ERROR_MSG_BUILD_ERROR = 10302,     /* 0x283E */
        MSP_ERROR_MSG_PARAM_ERROR = 10303,     /* 0x283F */
        MSP_ERROR_MSG_CONTENT_EMPTY = 10304,     /* 0x2840 */
        MSP_ERROR_MSG_INVALID_CONTENT_TYPE = 10305,     /* 0x2841 */
        MSP_ERROR_MSG_INVALID_CONTENT_LENGTH = 10306,     /* 0x2842 */
        MSP_ERROR_MSG_INVALID_CONTENT_ENCODE = 10307,     /* 0x2843 */
        MSP_ERROR_MSG_INVALID_KEY = 10308,     /* 0x2844 */
        MSP_ERROR_MSG_KEY_EMPTY = 10309,     /* 0x2845 */
        MSP_ERROR_MSG_SESSION_ID_EMPTY = 10310,     /* 0x2846 */
        MSP_ERROR_MSG_LOGIN_ID_EMPTY = 10311,     /* 0x2847 */
        MSP_ERROR_MSG_SYNC_ID_EMPTY = 10312,     /* 0x2848 */
        MSP_ERROR_MSG_APP_ID_EMPTY = 10313,     /* 0x2849 */
        MSP_ERROR_MSG_EXTERN_ID_EMPTY = 10314,     /* 0x284A */
        MSP_ERROR_MSG_INVALID_CMD = 10315,     /* 0x284B */
        MSP_ERROR_MSG_INVALID_SUBJECT = 10316,     /* 0x284C */
        MSP_ERROR_MSG_INVALID_VERSION = 10317,     /* 0x284D */
        MSP_ERROR_MSG_NO_CMD = 10318,     /* 0x284E */
        MSP_ERROR_MSG_NO_SUBJECT = 10319,     /* 0x284F */
        MSP_ERROR_MSG_NO_VERSION = 10320,     /* 0x2850 */
        MSP_ERROR_MSG_MSSP_EMPTY = 10321,     /* 0x2851 */
        MSP_ERROR_MSG_NEW_RESPONSE = 10322,     /* 0x2852 */
        MSP_ERROR_MSG_NEW_CONTENT = 10323,     /* 0x2853 */
        MSP_ERROR_MSG_INVALID_SESSION_ID = 10324,     /* 0x2854 */

        /* Error codes of DataBase 10400(0x28A0)*/
        MSP_ERROR_DB_GENERAL = 10400,     /* 0x28A0 */
        MSP_ERROR_DB_EXCEPTION = 10401,     /* 0x28A1 */
        MSP_ERROR_DB_NO_RESULT = 10402,     /* 0x28A2 */
        MSP_ERROR_DB_INVALID_USER = 10403,     /* 0x28A3 */
        MSP_ERROR_DB_INVALID_PWD = 10404,     /* 0x28A4 */
        MSP_ERROR_DB_CONNECT = 10405,     /* 0x28A5 */
        MSP_ERROR_DB_INVALID_SQL = 10406,     /* 0x28A6 */
        MSP_ERROR_DB_INVALID_APPID = 10407,    /* 0x28A7 */

        /* Error codes of Resource 10500(0x2904)*/
        MSP_ERROR_RES_GENERAL = 10500,     /* 0x2904 */
        MSP_ERROR_RES_LOAD = 10501,     /* 0x2905 */   /* Load resource */
        MSP_ERROR_RES_FREE = 10502,     /* 0x2906 */   /* Free resource */
        MSP_ERROR_RES_MISSING = 10503,     /* 0x2907 */   /* Resource File Missing */
        MSP_ERROR_RES_INVALID_NAME = 10504,     /* 0x2908 */   /* Invalid resource file name */
        MSP_ERROR_RES_INVALID_ID = 10505,     /* 0x2909 */   /* Invalid resource ID */
        MSP_ERROR_RES_INVALID_IMG = 10506,     /* 0x290A */   /* Invalid resource image pointer */
        MSP_ERROR_RES_WRITE = 10507,     /* 0x290B */   /* Write read-only resource */
        MSP_ERROR_RES_LEAK = 10508,     /* 0x290C */   /* Resource leak out */
        MSP_ERROR_RES_HEAD = 10509,     /* 0x290D */   /* Resource head currupt */
        MSP_ERROR_RES_DATA = 10510,     /* 0x290E */   /* Resource data currupt */
        MSP_ERROR_RES_SKIP = 10511,     /* 0x290F */   /* Resource file skipped */

        /* Error codes of TTS 10600(0x2968)*/
        MSP_ERROR_TTS_GENERAL = 10600,     /* 0x2968 */
        MSP_ERROR_TTS_TEXTEND = 10601,     /* 0x2969 */  /* Meet text end */
        MSP_ERROR_TTS_TEXT_EMPTY = 10602,     /* 0x296A */  /* no synth text */

        /* Error codes of Recognizer 10700(0x29CC) */
        MSP_ERROR_REC_GENERAL = 10700,     /* 0x29CC */
        MSP_ERROR_REC_INACTIVE = 10701,     /* 0x29CD */
        MSP_ERROR_REC_GRAMMAR_ERROR = 10702,     /* 0x29CE */
        MSP_ERROR_REC_NO_ACTIVE_GRAMMARS = 10703,     /* 0x29CF */
        MSP_ERROR_REC_DUPLICATE_GRAMMAR = 10704,     /* 0x29D0 */
        MSP_ERROR_REC_INVALID_MEDIA_TYPE = 10705,     /* 0x29D1 */
        MSP_ERROR_REC_INVALID_LANGUAGE = 10706,     /* 0x29D2 */
        MSP_ERROR_REC_URI_NOT_FOUND = 10707,     /* 0x29D3 */
        MSP_ERROR_REC_URI_TIMEOUT = 10708,     /* 0x29D4 */
        MSP_ERROR_REC_URI_FETCH_ERROR = 10709,     /* 0x29D5 */

        /* Error codes of Speech Detector 10800(0x2A30) */
        MSP_ERROR_EP_GENERAL = 10800,     /* 0x2A30 */
        MSP_ERROR_EP_NO_SESSION_NAME = 10801,     /* 0x2A31 */
        MSP_ERROR_EP_INACTIVE = 10802,     /* 0x2A32 */
        MSP_ERROR_EP_INITIALIZED = 10803,     /* 0x2A33 */

        /* Error codes of TUV */
        MSP_ERROR_TUV_GENERAL = 10900,     /* 0x2A94 */
        MSP_ERROR_TUV_GETHIDPARAM = 10901,     /* 0x2A95 */   /* Get Busin Param huanid*/
        MSP_ERROR_TUV_TOKEN = 10902,     /* 0x2A96 */   /* Get Token */
        MSP_ERROR_TUV_CFGFILE = 10903,     /* 0x2A97 */   /* Open cfg file */
        MSP_ERROR_TUV_RECV_CONTENT = 10904,     /* 0x2A98 */   /* received content is error */
        MSP_ERROR_TUV_VERFAIL = 10905,     /* 0x2A99 */   /* Verify failure */

        /* Error codes of IMTV */
        MSP_ERROR_IMTV_SUCCESS = 11000,     /* 0x2AF8 */   /* 成功 */
        MSP_ERROR_IMTV_NO_LICENSE = 11001,     /* 0x2AF9 */   /* 试用次数结束,用户需要付费 */
        MSP_ERROR_IMTV_SESSIONID_INVALID = 11002,     /* 0x2AFA */   /* SessionId失效,需要重新登录通行证 */
        MSP_ERROR_IMTV_SESSIONID_ERROR = 11003,     /* 0x2AFB */   /* SessionId为空,或者非法 */
        MSP_ERROR_IMTV_UNLOGIN = 11004,     /* 0x2AFC */   /* 未登录通行证 */
        MSP_ERROR_IMTV_SYSTEM_ERROR = 11005,     /* 0x2AFD */   /* 系统错误 */

        /* Error codes of HCR */
        MSP_ERROR_HCR_GENERAL = 11100,
        MSP_ERROR_HCR_RESOURCE_NOT_EXIST = 11101,

        /* Error codes of http 12000(0x2EE0) */
        MSP_ERROR_HTTP_BASE = 12000,    /* 0x2EE0 */

        /*Error codes of ISV */
        MSP_ERROR_ISV_NO_USER = 13000,    /* 32C8 */    /* the user doesn't exist */
    }
    #endregion

    #region ISR枚举常量
    public enum AudioStatus
    {
        ISR_AUDIO_SAMPLE_INIT = 0x00,
        ISR_AUDIO_SAMPLE_FIRST = 0x01,
        ISR_AUDIO_SAMPLE_CONTINUE = 0x02,
        ISR_AUDIO_SAMPLE_LAST = 0x04,
        ISR_AUDIO_SAMPLE_SUPPRESSED = 0x08,
        ISR_AUDIO_SAMPLE_LOST = 0x10,
        ISR_AUDIO_SAMPLE_NEW_CHUNK = 0x20,
        ISR_AUDIO_SAMPLE_END_CHUNK = 0x40,

        ISR_AUDIO_SAMPLE_VALIDBITS = 0x7f /* to validate the value of sample->status */
    }

    public enum EpStatus
    {
        ISR_EP_NULL = -1,
        ISR_EP_LOOKING_FOR_SPEECH = 0,          ///还没有检测到音频的前端点
        ISR_EP_IN_SPEECH = 1,                   ///已经检测到了音频前端点,正在进行正常的音频处理。
        ISR_EP_AFTER_SPEECH = 3,                ///检测到音频的后端点,后继的音频会被MSC忽略。
        ISR_EP_TIMEOUT = 4,                     ///超时
        ISR_EP_ERROR = 5,                       ///出现错误
        ISR_EP_MAX_SPEECH = 6                   ///音频过大
    }

    public enum RecogStatus
    {
        ISR_REC_NULL = -1,
        ISR_REC_STATUS_SUCCESS = 0,             ///识别成功,此时用户可以调用QISRGetResult来获取(部分)结果。
        ISR_REC_STATUS_NO_MATCH = 1,            ///识别结束,没有识别结果
        ISR_REC_STATUS_INCOMPLETE = 2,          ///正在识别中
        ISR_REC_STATUS_NON_SPEECH_DETECTED = 3, ///保留
        ISR_REC_STATUS_SPEECH_DETECTED = 4,     ///发现有效音频
        ISR_REC_STATUS_SPEECH_COMPLETE = 5,     ///识别结束
        ISR_REC_STATUS_MAX_CPU_TIME = 6,        ///保留
        ISR_REC_STATUS_MAX_SPEECH = 7,          ///保留
        ISR_REC_STATUS_STOPPED = 8,             ///保留
        ISR_REC_STATUS_REJECTED = 9,            ///保留
        ISR_REC_STATUS_NO_SPEECH_FOUND = 10     ///没有发现音频
    }
    #endregion
}

自定义异常:

[Serializable] //声明为可序列化的 因为要写入文件中  
    public class MscException : ApplicationException//由用户程序引发,用于派生自定义的异常类型  
    {
        /// <summary>  
        /// 默认构造函数  
        /// </summary>  
        public MscException() { }
        public MscException(string message)
            : base(message) { }
        public MscException(string message, Exception inner)
            : base(message, inner) { }
    } 
    /// <summary>
    /// 是否出错
    /// </summary>
    internal class RecoErrors
    {
        public RecoErrors() { }
        /// <summary>  
        /// 是否发生错误.  
        /// </summary>  
        /// <param name="id">错误ID</param>  
        public virtual void GetError(int id)
        {
            if (id != 0)
            {               
                var ex = new MscException(((ErrorCode)id).ToString("G"));
               // var ex = new MscException(Enum.GetName(typeof(ErrorCode),id));
                throw ex;
            }
        }
    }

讯飞语音支持边录边上传,不过我这里采用是一次性上传。起初我采用的是边录边上传,不过感觉有数字混合后识别正常率不好(还没跟讯飞那边沟通。),最后才使用一次性上传,毕竟语音文件也不是大就200KB一下。讯飞语音识别不支持多线程识别。

我做的这个语音识别产品,做成服务端与客户端。服务端:放在一个能连接外网机子上提供语音识别(做了一个简单队列),客户端:将音频数据采集后发送到局域网内的语音识别服务端进行识别。

以上有些代码是借助别人的,第一次写大家尽量不要吐槽,不过可以给点意见。大家相互学习…

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏