C# 利用TTS實現文本轉語音


TSS(Text To Speech),語音朗讀文本的技術,在Windows下台下,微軟給我們提供了一套API接口(Speech API)。金山詞霸的朗讀功能就是用的這個接口。

 

WindowsXP自帶的是Speech API 5.1版本,默認只支持英文,如果要支持中文需要安裝語音庫。

Speech API 5.1 官方下載地址

Speech API 5.1 中文語音庫官方下載地址

 

Vista版本開始,系統自帶的Speech API就換成了5.3版本,比較奇怪的是這個API並沒有做到向下兼容,5.3版本在Vista以下的版本是不可用的。

 

有一些非官方的Windows優化版本去掉了語音功能,需要對系統進行修復。
TTS修復工具及一些其他的語音庫下載
http://www.dacidian.net/tts/

 

下面我說一下如何實現,使用.NET 4.0新增的dynamic類型,可以很方便的使用COM類庫。

Type type = Type.GetTypeFromProgID("SAPI.SpVoice");
dynamic spVoice = Activator.CreateInstance(type); 
spVoice.Speak("Text To Speech 語音朗讀文本技術");

當然,直接使用dynamic還是很不方便的,可以對SAPI.SpVoice進行封裝

using System;  
using System.Collections.Generic;  
using System.Text;  
using System.Reflection;  
using System.Diagnostics;  
using System.Runtime.InteropServices;  
  
namespace COM  
{  
    [Guid("ED5DCE10-F40B-4655-9E7B-903779C77AF2")]  
    public partial class SpVoice : Object  
    {  
        public enum Flags  
        {  
            SVSFDefault = 0,  
            SVSFlagsAsync = 1,  
            SVSFPurgeBeforeSpeak = 2,   
            SVSFIsFilename = 4,   
            SVSFIsXML = 8,   
            SVSFIsNotXML = 16,  
            SVSFPersistXML = 32,  
            SVSFNLPSpeakPunc = 64,  
            SVSFParseSapi = 128,  
            SVSFParseSsml = 256,  
            SVSFParseAutodetect = 0,  
            SVSFNLPMask = 64,  
            SVSFParseMask = 384,  
            SVSFVoiceMask = 511,  
            SVSFUnusedFlags = -512  
        }  
  
        public enum Priority  
        {  
            SVPNormal = 0,   
            SVPAlert = 1,   
            SVPOver = 2  
        }  
    }  
    public partial class SpVoice : Object  
    {  
        private Type _ComType = null;  
        private object _ComObject = null;  
  
        public SpVoice()  
        {  
            this.Init();  
        }  
  
        public bool Init()  
        {  
            this._ComType = Type.GetTypeFromProgID("SAPI.SpVoice", true); // CLSID {269316D8-57BD-11D2-9EEE-00C04F797396}  
            if (this._ComType == null) {  
                throw new Exception("COM調用失敗");  
            }  
            this._ComObject = Activator.CreateInstance(this._ComType, true);  
            return this._ComObject != null;  
        }  
  
        public int Release()  
        {  
            return Marshal.ReleaseComObject(this._ComObject);  
        }  
  
        public int Rate  
        {  
            get {  
                return (int)this._ComType.InvokeMember("Rate", BindingFlags.GetProperty, null, this._ComObject, null);   
            }  
            set {  
                this._ComType.InvokeMember("Rate", BindingFlags.SetProperty, null, this._ComObject, new object[] { value });   
            }  
        }  
  
        public void Pause()  
        {  
            this._ComType.InvokeMember("Pause", BindingFlags.InvokeMethod, null, this._ComObject, null);  
        }  
  
        public void Resume()  
        {  
            this._ComType.InvokeMember("Resume", BindingFlags.InvokeMethod, null, this._ComObject, null);  
        }  
  
        public int Volume  
        {  
            get  
            {  
                return (int)this._ComType.InvokeMember("Volume", BindingFlags.GetProperty, null, this._ComObject, null);  
            }  
            set  
            {  
                this._ComType.InvokeMember("Volume", BindingFlags.SetProperty, null, this._ComObject, new object[] { value });  
            }  
        }  
  
        public int Skip(int Type, int NumItems)  
        {  
            return (int)this._ComType.InvokeMember("Skip", BindingFlags.InvokeMethod, null, this._ComObject, new object[] { Type, NumItems });   
        }  
  
        public bool IsUISupported(string TypeOfUI, object ExtraData)  
        {  
            return (bool)this._ComType.InvokeMember("IsUISupported", BindingFlags.InvokeMethod, null, this._ComObject, new object[] { TypeOfUI, ExtraData });  
        }  
  
        public bool WaitUntilDone(int msTimeout) {  
            return (bool)this._ComType.InvokeMember("WaitUntilDone", BindingFlags.InvokeMethod, null, this._ComObject, new object[] { msTimeout });  
        }  
  
        public void DisplayUI(int hWndParent, string Title, string TypeOfUI, object ExtraData)  
        {  
            this._ComType.InvokeMember("DisplayUI", BindingFlags.InvokeMethod, null, this._ComObject, new object[] { hWndParent, Title, TypeOfUI, ExtraData });  
        }  
  
        public void Speak(string Text, Flags Flags)  
        {  
            this._ComType.InvokeMember("Speak", BindingFlags.InvokeMethod, null, this._ComObject, new object[] { Text, Flags });  
        }  
  
        public Priority Property  
        {  
            get {  
                return (Priority)this._ComType.InvokeMember("Priority", BindingFlags.GetProperty, null, this._ComObject, null);   
            }  
            set {  
                this._ComType.InvokeMember("Priority", BindingFlags.SetProperty, null, this._ComType, new object[] { value });  
            }  
        }  
  
        public List<string> GetVoices()  
        {  
            List<string> _ret = null;  
            object Item = null, _Voices = this._ComType.InvokeMember("GetVoices", BindingFlags.InvokeMethod, null, this._ComObject, null);  
            int Count = (int)_Voices.GetType().InvokeMember("Count", BindingFlags.GetProperty, null, _Voices, null);  
            if (Count != 0) {  
                _ret = new List<string>();  
            }  
            for (int i = 0; i < Count; i++) {  
                Item = _Voices.GetType().InvokeMember("Item", BindingFlags.InvokeMethod, null, _Voices, new object[]{ i });  
                if (Item != null) {  
                    _ret.Add(Item.GetType().InvokeMember("GetDescription", BindingFlags.InvokeMethod, null, Item, null).ToString());  
                }  
            }  
            return _ret;  
        }  
  
        public bool SetVoices(string Name)  
        {  
            bool _ret = false;  
            object Item = null, _Voices = this._ComType.InvokeMember("GetVoices", BindingFlags.InvokeMethod, null, this._ComObject, null);  
            int Count = (int)_Voices.GetType().InvokeMember("Count", BindingFlags.GetProperty, null, _Voices, null);  
            for (int i = 0; i < Count; i++) {  
                Item = _Voices.GetType().InvokeMember("Item", BindingFlags.InvokeMethod, null, _Voices, new object[] { i });  
                if (Item != null) {  
                    var _str = Item.GetType().InvokeMember("GetDescription", BindingFlags.InvokeMethod, null, Item, null).ToString();  
                    if (_str == Name) {  
                        this._ComType.InvokeMember("Voice", BindingFlags.SetProperty, null, this._ComObject, new object[] { Item });  
                    }  
                }  
            }  
            return _ret;  
        }  
    }  
}
轉載於http://blog.csdn.net/windowsvipcuvs/article/details/30751707

這樣使用起來就比較方便

var spVoices = new SpVoice()
{
    Rate = -2,
    Volume = 100
};
spVoices.SetVoices(spVoices.GetVoices()[0]);
spVoices.Speak(speak, SpVoice.Flags.SVSFlagsAsync);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM