Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 无法创建多个TTS“;wav";在C中使用MS-SAPI 5.1的文件#_C#_Wav_Text To Speech_Sapi - Fatal编程技术网

C# 无法创建多个TTS“;wav";在C中使用MS-SAPI 5.1的文件#

C# 无法创建多个TTS“;wav";在C中使用MS-SAPI 5.1的文件#,c#,wav,text-to-speech,sapi,C#,Wav,Text To Speech,Sapi,大家好 我正在从事一个项目,我将不得不创建使用TTS的WAV文件的名称 我将MS-SAPI 5.1 SDK安装在Windows Server 2003上,并使用C#编写TTS程序。除了默认的Microsoft Sam语音外,我还有服务器上安装的NeoSpeech TTS语音 我遇到的问题是,该程序生成的WAV文件不超过1个 更具体地说,如果我向程序发送4个名称,程序将创建4个WAV文件。但是,只有第一个名称被正确转换。文件大小大于1 kb,并且该文件也在media player中播放 其他3个文

大家好

我正在从事一个项目,我将不得不创建使用TTS的WAV文件的名称

我将MS-SAPI 5.1 SDK安装在Windows Server 2003上,并使用C#编写TTS程序。除了默认的Microsoft Sam语音外,我还有服务器上安装的NeoSpeech TTS语音

我遇到的问题是,该程序生成的WAV文件不超过1个

更具体地说,如果我向程序发送4个名称,程序将创建4个WAV文件。但是,只有第一个名称被正确转换。文件大小大于1 kb,并且该文件也在media player中播放

其他3个文件已创建,但大小为1KB,不能在任何媒体播放器中使用

我对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 Voice。我似乎只有用新语言的声音才有这个问题

这是否意味着我的代码是正确的,声音有问题?首先,我得到了客户的声音,所以对此我无能为力。第二,这些是为制作准备的声音。我很确定他们都经过了很好的测试,否则我们会听到很多关于它的消息

我仍然倾向于相信我写的代码出了问题


还有其他建议吗?我在这里遇到了一个真正的问题,任何帮助都将不胜感激。

我做TTS已经有一段时间了,但据我回忆,Speak方法是异步的,因此在第一次播放时,后续调用可能会被阻止


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

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

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

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

我找不到任何方法来“重置”语音系统,所以我试着每100行呼叫一次垃圾收集器。成功了

所以我建议你试试:

GC.Collect()


在ConvertStringToSpeechWav函数的末尾。

虽然我没有看到任何明显的导致TTS问题的原因,但是您可以使用一些最佳实践和代码简化

首先,不需要实例化包含Main()和SampleTTS的类来调用ConvertStringToSpeechWav():

示例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);
        }
    }
让GC来清理。您是否尝试过像PauloPinto建议的那样调用GC.Collect(),只是为了看看它是否有效?您不必为了让某些东西工作而坚持严格的编码原则。我们的目标应该始终是干净、有原则地编写代码,但更重要的是让代码处于工作状态,然后根据需要进行重构

我希望这能有所帮助


干杯。

谢谢你的评论,杜比。在查看MSDN:SpeechVoiceSpeakFlags.SVSFDefault后,我将代码更改为此。不幸的是,这也产生了同样的结果。不知何故,没有生成后续文件。这对GC来说不是一个好的做法。收集每一行“某些”行,我怀疑它是否真的解决了问题,如果它真的解决了问题,代码应该会有一些奇怪的地方。谢谢Paulo的评论。这次我想站在戴维德这边。我可以理解,在生产截止日期下,您会认为任何解决方案都是可以接受的,但这不是解决问题的正确方法。我将继续为这个问题寻找正确而优雅的解决方案,我建议您也这样做,即使GC.Collect()现在已经解决了您的问题@DavidePiras我已经在上面发布了我的代码,不知道您是否可以查看它,并让我知道我的代码是否有问题。谢谢你们两位,谢谢你们的时间@戴维德皮拉斯:我同意这不是“好的做法”,但我仍然会说一个工作计划比一个非工作计划好。调用GC解决了这个问题,这表明MS-SAPI SDK没有正确释放隐藏的资源。所以坏习惯可能来自内心深处@那么我的建议不起作用了吗?我明白你为什么不想在生产环境中使用它,但它可能会给你另一个错误的线索。我运行一台64位的笔记本电脑,声音是32位的,所以我唯一可以进行测试的地方就是实际的服务器。我和我的首席技术官谈过这件事,他甚至拒绝让我尝试:)(这是意料之中的)。我们现在使用AT&T语音,这与我上面的代码配合得很好。我现在有理由相信我从客户那里听到的声音是老旧的或有问题的。也许你也应该试试其他的声音。我不认为SAPI SDK存在缺陷。总是第三方供应商做得不好。谢谢你的评论。我使用java,所以我不太确定是否从StaticMain调用非静态方法。我同意你的观点,
ArrayList->List
更好,因为它是类型安全的。我已经设置了空检查,因为理想情况下,数据将来自DB,但我必须调整代码以便发布。我没有尝试GC.Collect()。有机会的话我会试一试的。但是看到你
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);
        }
    }
voice = new SpVoice();