簡體   English   中英

無法在C#中使用MS-SAPI 5.1創建MULTIPLE“wav”文件

[英]Unable to create MULTIPLE TTS “wav” files using MS-SAPI 5.1 in C#

問候人們!

我正在開發一個項目,我將不得不使用TTS創建名稱的WAV文件。

我在Windows Server 2003上安裝了MS-SAPI 5.1 SDK,並使用C#編寫TTS程序。 除了默認的Microsoft Sam語音外,我還在服務器上安裝了NeoSpeech TTS的聲音。

我遇到的問題是, 該程序不會產生超過1個工作WAV文件

更具體地說,如果我向程序發送4個名稱,程序將創建4個WAV文件。 但是只能正確轉換名字。 文件大小大於1 kb,並且該文件還在媒體播放器中播放。

其他3個文件已創建,但大小為1 kb,不適用於任何媒體播放器。

我是C#和MS-SAPI的新手,但我相信我在創建代碼方面做得不錯。 我花了幾天時間試圖解決這個問題,但現在我精力充沛。

非常感謝您對此問題的見解。 謝謝你的時間。

這是我的代碼:

using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using SpeechLib;
using System.Threading;

namespace TTS_Text_To_Wav
{
    class Gender
    {
        public static String MALE = "Male";
        public static String FEMALE = "Female";
    }

    class Languages
    {
        public static String ENGLISH = "409;9";
        public static String SPANISH = "40a";
    }

    class Vendor
    {
        public static String VOICEWARE = "Voiceware";
        public static String MICROSOFT = "Microsoft";
    }

    class SampleTTS
    {
        static void Main(string[] args)
        {
            SampleTTS processor = null;

            try
            {
                processor = new SampleTTS();

                // get unprocessed items
                ArrayList unProcessedItems = new ArrayList();
                unProcessedItems.Add("Kate");
                unProcessedItems.Add("Sam");
                unProcessedItems.Add("Paul");
                unProcessedItems.Add("Violeta");

                if (unProcessedItems != null)
                {
                    foreach (string record in unProcessedItems)
                    {
                        // convert text to wav
                        processor.ConvertStringToSpeechWav(record, "c:/temp/" + record + ".wav", Vendor.VOICEWARE, Gender.MALE, Languages.ENGLISH);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        void ConvertStringToSpeechWav(String textToConvert, String pathToCreateWavFile, String vendor, String gender, String language)
        {
            SpVoice voice = null;
            SpFileStream spFileStream = null;

            try
            {
                spFileStream = new SpFileStream();
                voice = new SpVoice();

                spFileStream.Format.Type = SpeechAudioFormatType.SAFT8kHz16BitMono;
                spFileStream.Open(pathToCreateWavFile, SpeechStreamFileMode.SSFMCreateForWrite, false);

                voice.Voice = voice.GetVoices("Vendor=" + vendor + ";Gender=" + gender, "Language=" + language).Item(0);
                voice.AudioOutputStream = spFileStream;
                voice.Speak(textToConvert, SpeechVoiceSpeakFlags.SVSFlagsAsync | SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak);
                voice.WaitUntilDone(Timeout.Infinite);
            }
            catch (Exception e)
            {
                throw new Exception("Error occured in ConvertStringToSpeechWav()\n" + e.Message);
            }
            finally
            {
                if (spFileStream != null)
                {
                    spFileStream.Close();
                }
            }
        }
    }
}

編輯:

我似乎注意到了一些新行為。 該代碼對於系統上的Microsoft語音正常運行。 只有NeoSpeech的聲音,我似乎才有這個問題。

這是否意味着我的代碼正確,聲音有問題? 首先,我得到了客戶的聲音,所以我無能為力。 其次,這些是生產就緒的聲音。 我很確定它們經過了很好的測試,或者我們會聽到很多關於它的信息。

我仍然傾向於相信我編寫的代碼有問題。

還有其他建議嗎? 我在這里是一個真正的解決辦法,任何幫助將不勝感激。

雖然我看不到任何引起TTS問題的明顯信息,但是您可以使用一些最佳實踐和簡化的代碼。

首先,包含Main(),SampleTTS的類不需要實例化以調用ConvertStringToSpeechWav():

class SampleTTS
{
    static void Main(string[] args)
    {
        SampleTTS processor = null;

        try
        {
            processor = new SampleTTS();

可以將TTS示例類重寫如下:

class SampleTTS
{
    static void Main(string[] args)
    {
        try
        {
            // get unprocessed items
            List<String> unProcessedItems = new List<String>();
            unProcessedItems.Add("Kate");
            unProcessedItems.Add("Sam");
            unProcessedItems.Add("Paul");
            unProcessedItems.Add("Violeta");

            foreach (string record in unProcessedItems)
            {
                // convert text to wav
                ConvertStringToSpeechWav(record, "c:/temp/" + record + ".wav", Vendor.VOICEWARE, Gender.MALE, Languages.ENGLISH);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

注意我還將列表從ArrayList -> List<String>更改為最佳實踐,因為List(T)的性能優於ArrayList且類型安全。 我還刪除了if (unProcessedItems != null check)因為你已經在實例化上面的列表,所以它將為非null或拋出異常。

最后,每次調用ConvertStringToSpeechWav()時,您都會創建一個新的語音對象:

voice = new SpVoice();

並讓GC清理它。 您是否嘗試過像上面提到的PauloPinto一樣調用GC.Collect(),看它是否有效? 您不必為了使某些工作正常而遵循嚴格的編碼原則。 目標應始終是干凈利落地編寫原則,但更重要的是讓代碼處於工作狀態,然后根據需要進行重構。

我希望其中一些有所幫助。

干杯。

我做TTS已經有一段時間了,但是我記得Speak方法是異步的,所以后續的調用可能會在第一次調用時被阻塞。

看起來您正在使用“SpeechVoiceSpeakFlags.SVSFlagsAsync”標志明確地執行此操作,因此請先嘗試更改它。

我遇到了類似的問題,除了我使用來自不同供應商(不是NeoSpeech)的聲音,並且問題只出現在大約300個左右成功的wav文件生成之后。

但症狀是一樣的:所有不起作用的wav文件大小都不到1K。

我注意到將失敗的行移動到列表的頂部仍然產生了類似的結果:最初的300行左右成功(即使其中一些行在上一次運行中失敗)。 所以問題不在於線本身,而在於處理多少問題。

我找不到任何“重置”語音系統的方法,所以我嘗試每100行調用一次垃圾收集器。 有效!

所以我建議你試試:

GC.Collect();

在ConvertStringToSpeechWav函數的末尾。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM