C#调用科大讯飞离线语音合成TTS

来源:互联网 发布:调和的宝札淘宝 编辑:程序博客网 时间:2024/05/18 03:03

原作者勿怪,未经允许就转载了,感谢万分。

http://www.cnblogs.com/xuguanghui/p/4505555.html

----------------------------------------------------

c#调用科大讯飞的离线语音合成,需要在科大讯飞开放平台:http://www.xfyun.cn 注册、创建应用(获取APPID)、开通离线语音服务、下载SDK。

SDK中目录如下:

关于目录结构,讯飞平台的资料库中有介绍。

 

bin目录下有msc.dll动态库。c#调用科大讯飞的语音合成,需要引用该文件。该文件是C语言生成的dll,C#没办法直接引用。所有需要用C#重新封装一个TTS.dll,然后再在C#项目中引用封装的TTS.dll。

 

步骤:

1.在VS中新建一个类库项目(TTS),新建一个类文件(TTS.cs)

2.TTS.cs中的内容如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Runtime.InteropServices;namespace TTS{    public 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 */        /* 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 */    }    #region TTS枚举常量    /// <summary>    /// vol参数的枚举常量    /// </summary>    public enum enuVol    {        x_soft,        soft,        medium,        loud,        x_loud    }    /// <summary>    /// speed语速参数的枚举常量    /// </summary>    public enum enuSpeed    {        x_slow,        slow,        medium,        fast,        x_fast    }    /// <summary>    /// speeker朗读者枚举常量    /// </summary>    public enum enuSpeeker    {        小燕_青年女声_中英文_普通话 = 0,        小宇_青年男声_中英文_普通话,        凯瑟琳_青年女声_英语,        亨利_青年男声_英语,        玛丽_青年女声_英语,        小研_青年女声_中英文_普通话,        小琪_青年女声_中英文_普通话,        小峰_青年男声_中英文_普通话,        小梅_青年女声_中英文_粤语,        小莉_青年女声_中英文_台普,        小蓉_青年女声_汉语_四川话,        小芸_青年女声_汉语_东北话,        小坤_青年男声_汉语_河南话,        小强_青年男声_汉语_湖南话,        小莹_青年女声_汉语_陕西话,        小新_童年男声_汉语_普通话,        楠楠_童年女声_汉语_普通话,        老孙_老年男声_汉语_普通话    }      public enum SynthStatus    {        MSP_TTS_FLAG_STILL_HAVE_DATA = 1,        MSP_TTS_FLAG_DATA_END = 2,        MSP_TTS_FLAG_CMD_CANCELED = 0    }    #endregion    public class TTSDll    {        #region TTS dll import        [DllImport("msc.dll", CallingConvention = CallingConvention.Winapi)]        public static extern int MSPLogin(string user, string password, string configs);        [DllImport("msc.dll", CallingConvention = CallingConvention.Winapi)]        public static extern int MSPLogout();        [DllImport("msc.dll", CallingConvention = CallingConvention.Winapi)]        public static extern IntPtr QTTSSessionBegin(string _params, ref int errorCode);        [DllImport("msc.dll", CallingConvention = CallingConvention.Winapi)]        public static extern int QTTSTextPut(string sessionID, string textString, uint textLen, string _params);        [DllImport("msc.dll", CallingConvention = CallingConvention.Winapi)]        public static extern IntPtr QTTSAudioGet(string sessionID, ref uint audioLen, ref SynthStatus synthStatus, ref int errorCode);        [DllImport("msc.dll", CallingConvention = CallingConvention.Winapi)]        public static extern IntPtr QTTSAudioInfo(string sessionID);        [DllImport("msc.dll", CallingConvention = CallingConvention.Winapi)]        public static extern int QTTSSessionEnd(string sessionID, string hints);        #endregion    }}


3.把该类库生成一个TTS.dll

4.在C#项目中引用该类库TTS.dll

5.另外需要把下载的SDK中的msc.dll放到语音合成项目中的Debug目录下面(可以百度一下C#调用C/C++的DLL)

6.语音合成项目的代码如下:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using TTS;using System.Runtime.InteropServices;using System.IO;using System.Media;using System.Threading;namespace OfflineSpeech{    public partial class Form1 : Form    {        public Form1()        {            InitializeComponent();        }        int ret = 0;        IntPtr session_ID;        private void button1_Click(object sender, EventArgs e)        {            try            {                ///APPID请勿随意改动                string login_configs = "appid =***** ";//登录参数,自己注册后获取的appid                string text = richTextBox1.Text.Trim();//待合成的文本                if (string.IsNullOrEmpty(richTextBox1.Text.Trim()))                {                    text = "请输入合成语音的内容";                }                                string filename = "Call.wav"; //合成的语音文件                uint audio_len = 0;                SynthStatus synth_status = SynthStatus.MSP_TTS_FLAG_STILL_HAVE_DATA;                ret = TTSDll.MSPLogin(string.Empty, string.Empty, login_configs);//第一个参数为用户名,第二个参数为密码,第三个参数是登录参数,用户名和密码需要在http://open.voicecloud.cn                //MSPLogin方法返回失败                if (ret !=(int) ErrorCode.MSP_SUCCESS)                {                    return;                }                //string parameter = "engine_type = local, voice_name=xiaoyan, tts_res_path =fo|res\\tts\\xiaoyan.jet;fo|res\\tts\\common.jet, sample_rate = 16000";                string _params = "ssm=1,ent=sms16k,vcn=xiaoyan,spd=medium,aue=speex-wb;7,vol=x-loud,auf=audio/L16;rate=16000";                //string @params = "engine_type = local,voice_name=xiaoyan,speed=50,volume=50,pitch=50,rcn=1, text_encoding = UTF8, background_sound=1,sample_rate = 16000";                session_ID = TTSDll.QTTSSessionBegin(_params, ref ret);                //QTTSSessionBegin方法返回失败                if (ret != (int)ErrorCode.MSP_SUCCESS)                {                    return;                }                ret = TTSDll.QTTSTextPut(Ptr2Str(session_ID), text, (uint)Encoding.Default.GetByteCount(text), string.Empty);                //QTTSTextPut方法返回失败                if (ret != (int)ErrorCode.MSP_SUCCESS)                {                    return;                }                MemoryStream memoryStream = new MemoryStream();                memoryStream.Write(new byte[44], 0, 44);                while (true)                {                    IntPtr source = TTSDll.QTTSAudioGet(Ptr2Str(session_ID), ref audio_len, ref synth_status, ref ret);                    byte[] array = new byte[(int)audio_len];                    if (audio_len > 0)                    {                        Marshal.Copy(source, array, 0, (int)audio_len);                    }                    memoryStream.Write(array, 0, array.Length);                    Thread.Sleep(1000);                    if (synth_status == SynthStatus.MSP_TTS_FLAG_DATA_END || ret != 0)                        break;                }                WAVE_Header wave_Header = getWave_Header((int)memoryStream.Length - 44);                byte[] array2 = this.StructToBytes(wave_Header);                memoryStream.Position = 0L;                memoryStream.Write(array2, 0, array2.Length);                memoryStream.Position = 0L;                SoundPlayer soundPlayer = new SoundPlayer(memoryStream);                soundPlayer.Stop();                soundPlayer.Play();                if (filename != null)                {                    FileStream fileStream = new FileStream(filename, FileMode.Create,FileAccess.Write);                    memoryStream.WriteTo(fileStream);                    memoryStream.Close();                    fileStream.Close();                }                            }            catch (Exception)            {            }            finally            {                ret = TTSDll.QTTSSessionEnd(Ptr2Str(session_ID), "");                ret = TTSDll.MSPLogout();//退出登录            }        }        /// <summary>        /// 结构体转字符串        /// </summary>        /// <param name="structure"></param>        /// <returns></returns>        private byte[] StructToBytes(object structure)        {            int num = Marshal.SizeOf(structure);            IntPtr intPtr = Marshal.AllocHGlobal(num);            byte[] result;            try            {                Marshal.StructureToPtr(structure, intPtr, false);                byte[] array = new byte[num];                Marshal.Copy(intPtr, array, 0, num);                result = array;            }            finally            {                Marshal.FreeHGlobal(intPtr);            }            return result;        }        /// <summary>        /// 结构体初始化赋值        /// </summary>        /// <param name="data_len"></param>        /// <returns></returns>        private WAVE_Header getWave_Header(int data_len)        {            return new WAVE_Header            {                RIFF_ID = 1179011410,                File_Size = data_len + 36,                RIFF_Type = 1163280727,                FMT_ID = 544501094,                FMT_Size = 16,                FMT_Tag = 1,                FMT_Channel = 1,                FMT_SamplesPerSec = 16000,                AvgBytesPerSec = 32000,                BlockAlign = 2,                BitsPerSample = 16,                DATA_ID = 1635017060,                DATA_Size = data_len            };        }        /// <summary>        /// 语音音频头        /// </summary>        private struct WAVE_Header        {            public int RIFF_ID;            public int File_Size;            public int RIFF_Type;            public int FMT_ID;            public int FMT_Size;            public short FMT_Tag;            public ushort FMT_Channel;            public int FMT_SamplesPerSec;            public int AvgBytesPerSec;            public ushort BlockAlign;            public ushort BitsPerSample;            public int DATA_ID;            public int DATA_Size;        }        /// 指针转字符串        /// </summary>        /// <param name="p">指向非托管代码字符串的指针</param>        /// <returns>返回指针指向的字符串</returns>        public static string Ptr2Str(IntPtr p)        {            List<byte> lb = new List<byte>();            while (Marshal.ReadByte(p) != 0)            {                lb.Add(Marshal.ReadByte(p));                p = p + 1;            }            byte[] bs = lb.ToArray();            return Encoding.Default.GetString(lb.ToArray());        }    }}


7.语音合成项目界面如下:

 

推荐科大讯飞平台论坛帖子:

http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=3771

http://bbs.xfyun.cn/forum.php?mo ... &highlight=c%23

 

源码:

WindowsFormsApplication1.zip

appid  :要使用自己在科大讯飞官网创建应用后的appid

原创粉丝点击