0

皆さん、こんにちは!

TTS を使用して名前の WAV ファイルを作成する必要があるプロジェクトに取り組んでいます。

MS-SAPI 5.1 SDK を Windows Server 2003 にインストールし、C# を使用して TTS プログラムを作成しています。デフォルトの Microsoft Sam の声とは別に、NeoSpeech TTS からの声がサーバーにインストールされています。

私が抱えている問題は、プログラムが複数の作業 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 の音声のみです。

それは私のコードが正しく、声に何か問題があるということですか? 一つには、お客様から声をいただいたので、どうしようもありません。第二に、これらはプロダクション対応の声です。私は彼らが十分にテストされていると確信しています。

私はまだ、私が書いたコードに何か問題があると信じがちです。

他に利用可能な提案はありますか?私はここで本当の修正をしています。助けていただければ幸いです。

4

3 に答える 3

2

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()を呼び出して、機能するかどうかを確認しましたか?何かを機能させるためだけに、厳密なコーディングの原則に固執する必要はありません。目標は常にクリーンで原則に従ってコーディングすることですが、コードを動作状態にし、必要に応じてリファクタリングすることも目標です。

これがお役に立てば幸いです。

乾杯。

于 2011-02-19T00:02:24.017 に答える
0

私は、別のベンダー (NeoSpeech ではない) の音声を使用していたことと、300 ほどの wav ファイルが正常に生成された後にのみ問題が発生したことを除いて、同様の問題を抱えていました。

しかし、症状は同じでした。機能しないすべての wav ファイルのサイズは 1K 未満でした。

失敗した行をリストの一番上に移動しても、同様の結果が得られることに気付きました。最初の 300 行程度は成功しました (それらの行の一部は前回の実行で失敗していましたが)。つまり、問題は回線自体ではなく、処理される量の問題でした。

音声システムを「リセット」する方法が見つからなかったので、100 行ごとにガベージ コレクターを呼び出してみました。出来た!

だから私はあなたが試してみることをお勧めします:

GC.Collect();

ConvertStringToSpeechWav 関数の最後に。

于 2011-02-18T00:25:38.163 に答える
0

TTS を行ってからしばらく経ちましたが、私が思い出す限り、Speakメソッドは非同期であるため、最初の呼び出しが再生されている間、後続の呼び出しはおそらくブロックされます。

「SpeechVoiceSpeakFlags.SVSFlagsAsync」フラグを使用して明示的に行っているように見えるので、最初に変更してみてください。

于 2010-12-05T06:42:50.160 に答える