0

问候各位!

我正在做一个项目,我将不得不使用 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 的声音我似乎有这个问题。

这是否意味着我的代码是正确的,而声音有问题?一方面,我从客户那里得到了声音,所以我对此无能为力。其次,这些是生产就绪的声音。我很确定它们经过了很好的测试,否则我们会听到很多关于它的信息。

我仍然倾向于相信我编写的代码有问题。

还有其他可用的建议吗?我在这里得到了真正的修复,任何帮助将不胜感激。

4

3 回答 3

2

While I don't see anything glaring that is causing the TTS issue, there are some best practices and code simplifications you could be using.

First off, the class which includes Main(), SampleTTS doesn't need to be instantiated in order to call ConvertStringToSpeechWav():

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

        try
        {
            processor = new SampleTTS();

The Sample TTS class can be rewritten as follows:

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);
        }
    }

Note I also changed the list from ArrayList -> List<String> as a best practice because List(T) performs better than ArrayList and is type safe. I also removed the if (unProcessedItems != null check) as you're already instantiating the list above, so it will either be non null or throw an exception.

Lastly you're creating a new voice object each time ConvertStringToSpeechWav() is called:

voice = new SpVoice();

and letting GC clean it up. Have you tried calling GC.Collect() like PauloPinto suggested above, just to see if it works? You don't have to stick to rigid coding principles just to get something working. The goal should always be to code cleanly and with principles, but more so to get your code in a working state, and then refactoring as needed.

I hope some of this helps.

Cheers.

于 2011-02-19T00:02:24.017 回答
0

自从我做 TTS 以来已经有一段时间了,但据我记得Speak方法是异步的,因此后续调用可能在第一次播放时被阻塞。

看起来您是通过使用“SpeechVoiceSpeakFlags.SVSFlagsAsync”标志明确执行此操作的,因此请先尝试更改它。

于 2010-12-05T06:42:50.160 回答
0

我遇到了类似的问题,除了我使用的是来自不同供应商(不是 NeoSpeech)的声音,而且该问题仅在生成大约 300 个左右的成功 wav 文件后才出现。

但症状是一样的:所有不起作用的 wav 文件的大小都小于 1K。

我注意到将失败的行移到列表顶部仍然会产生类似的结果:最初的 300 左右行成功了(即使其中一些行在之前的运行中失败了)。所以问题不在于线路本身,而在于处理了多少。

我找不到任何“重置”语音系统的方法,所以我尝试每 100 行调用一次垃圾收集器。有效!

所以我建议你试试:

GC.Collect();

在 ConvertStringToSpeechWav 函数的末尾。

于 2011-02-18T00:25:38.163 回答