首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 語音合成實戰(上):基於 SAPI 5.1 實現中英混合朗讀

     編輯:關於C語言

前言

.NET Framework 早期版本對中文語音合成(TTS)支援有限。透過安裝 Microsoft Speech SDK 5.1 (SAPI 5.1) 及對應語言包,可在 C# 中調用 COM 元件 SpeechLib 實現高品質中英混合朗讀。本文採用單例模式封裝核心類別,支援:語音切換(中/英)、音量/語速調節、異步播放、暫停/繼續/停止、中英混合文本智能分段朗讀。

環境準備

  1. 下載安裝:Speech SDK 5.1 + Speech SDK 5.1 Language Pack(勾選簡體中文、英文)
  2. 專案 → 加入參考 → COM → Microsoft Speech Object Library (生成 SpeechLib 互操作組件)
  3. using SpeechLib;

核心類別設計:SpeechSynthesizer


using System;
using SpeechLib;

public class SpeechSynthesizer
{
    private static SpeechSynthesizer _instance;
    private SpVoiceClass _voice;

    private SpeechSynthesizer() { BuildVoice(); }

    public static SpeechSynthesizer Instance {
        get {
            if (_instance == null) _instance = new SpeechSynthesizer();
            return _instance;
        }
    }

    private void BuildVoice() {
        if (_voice == null) _voice = new SpVoiceClass();
    }

    // 語音選擇:GetVoices() 返回 Token 列表,索引 0 通常為中文,1+ 為英文口音
    private void SetChineseVoice() {
        _voice.Voice = _voice.GetVoices("", "").Item(0);
    }

    private void SetEnglishVoice() {
        _voice.Voice = _voice.GetVoices("", "").Item(1);
    }

    // 核心發聲方法(異步)
    private void Speak(string text) {
        try {
            _voice.Speak(text, SpeechVoiceSpeakFlags.SVSFlagsAsync);
        }
        catch (Exception ex) {
            throw new Exception("語音播放失敗: " + ex.Message);
        }
    }

    // 中文朗讀
    public void SpeakChinese(string text) {
        SetChineseVoice();
        Speak(text);
    }

    // 英文朗讀
    public void SpeakEnglish(string text) {
        SetEnglishVoice();
        Speak(text);
    }

    // 智能分段:依字符 Unicode 範圍判斷中英,分段呼叫對應語音
    public void SpeakMixed(string text) {
        if (string.IsNullOrEmpty(text)) return;

        int chStart = 0, enStart = 0;
        bool inChinese = true;

        for (int i = 0; i < text.Length; i++) {
            char c = text[i];
            bool isAsciiLetter = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');

            if (inChinese) {
                if (isAsciiLetter) { // 切換到英文
                    SpeakChinese(text.Substring(chStart, i - chStart));
                    enStart = i;
                    inChinese = false;
                }
            } else { // 在英文段
                if (!isAsciiLetter) { // 切換回中文
                    SpeakEnglish(text.Substring(enStart, i - enStart));
                    chStart = i;
                    inChinese = true;
                }
            }
        }

        // 處理尾段
        if (inChinese)
            SpeakChinese(text.Substring(chStart));
        else
            SpeakEnglish(text.Substring(enStart));
    }

    // 音量 (0-100)
    public int Volume {
        get => _voice.Volume;
        set => _voice.Volume = (ushort)Math.Max(0, Math.Min(100, value));
    }

    // 語速 (-10 到 10)
    public int Rate {
        get => _voice.Rate;
        set => _voice.Rate = Math.Max(-10, Math.Min(10, value));
    }

    // 控制方法
    public void Stop() {
        _voice.Speak("", SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak);
    }

    public void Pause() => _voice.Pause();
    public void Resume() => _voice.Resume();
}

使用範例


class Program {
    static void Main() {
        var tts = SpeechSynthesizer.Instance;
        tts.Volume = 80;
        tts.Rate = 0;

        // 純中文
        tts.SpeakChinese("歡迎使用語音合成系統");

        // 純英文
        tts.SpeakEnglish("Welcome to the speech synthesis system");

        // 中英混合
        tts.SpeakMixed("你好 World,這是一個 Test 範例");

        Console.WriteLine("按任意鍵停止...");
        Console.ReadKey();
        tts.Stop();
    }
}

關鍵技術點解析

  1. 單例模式:SpVoiceClass 建立成本高、資源佔用大,全程複用單一實例
  2. 異步旗標 SVSFlagsAsync:Speak 立即返回,不阻塞呼叫執行緒(UI 應用關鍵)
  3. 語音 Token 選擇:GetVoices("", "") 返回所有已安裝語音 Token,Item(0) 通常為系統預設中文語音(如 Microsoft Simplified Chinese),Item(1...n) 為英文口音(Microsoft Sam, Mike, Mary 等)
  4. 中英分段演算法:簡易版依 ASCII 字母判斷;生產環境建議用 CharUnicodeInfo.GetUnicodeCategory 精確識別 CJK 統一表意文字
  5. 音量/語速屬性:直接映射到底層 COM 介面,範圍驗證防止無效值
  6. 停止機制:SVSFPurgeBeforeSpeak 清空隊列並立即停止

常見問題與解決

問題原因解決
無聲音/例外未安裝 SDK 或語言包重新安裝 Speech SDK 5.1 + Language Pack
中文唸成英文Voice Token 選錯列舉 GetVoices 列印 Description 確認索引
異步播放重疊連續呼叫 Speak 且未停止需求疊加用隊列管理,或呼叫 Stop 後再 Speak
64 位元專案編譯失敗SpeechLib 為 32 位元 COM專案屬性 → Build → 勾選 "Prefer 32-bit" 或目標平台 x86

擴展方向

  • SSML 支援:Speak 接受 SSML 標記,可控制停頓、音調、重音
  • 語音辨識 (SR):下篇將介紹 SpSharedRecoContext 實現中文語音輸入
  • .NET Core / 5+ 跨平台:SAPI 僅限 Windows;跨平台請用 System.Speech.Synthesis (Windows) 或第三方 Azure Cognitive Services Speech SDK、eSpeak-NG、Festival

總結

透過 SAPI 5.1 COM 互操作,C# 可輕鬆獲得企業級語音合成能力。單例封裝 + 異步播放 + 智能中英分段,構成實用 TTS 元件的核心。理解 COM 物件生命週期、執行緒模型、語音 Token 管理,是避坑關鍵。下篇將挑戰更複雜的中文語音辨識,敬請期待。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved