使用其他语音时的文本到语音 SAPI5 AccessViolationException

Posted

技术标签:

【中文标题】使用其他语音时的文本到语音 SAPI5 AccessViolationException【英文标题】:Text-to-speech SAPI5 AccessViolationException when using another voice 【发布时间】:2012-12-16 04:40:33 【问题描述】:

我已经为 SAPI5 Eliska22k 安装了捷克语语音。它在 Windows 7 上运行良好。现在我有 Windows 8 并且在调用 Speak 方法时它给了我 Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

我还尝试使用来自 .NET System.Speech 的 SpeechSynthesizer。它还可以看到已安装的语音 Eliska22k(在 W7 上它仅适用于 SAPI5),但它不会写入任何不会启动的异常。在SelectVoice("Eliska22k") 方法程序上直接退出。

默认语音在 SAPI5 中也可以在默认语音中正常工作。

我已经安装了SpeechPad,它可以很好地与语音 Eliska22k 配合使用。我找不到问题所在。

SpeechSynthesizer voice = new SpeechSynthesizer();

voice.SelectVoice("Eliska22k");// here program just exit without any exeption
voice.Rate = 2;

voice.SpeakAsync("Ahoj, jak se máš?");

SAPI5

SpVoice voice = new SpVoice();

voice.Voice = voice.GetVoices().Item(6);// index of eliska voice
voice.Rate = 2;

voice.Speak("Ahoj, jak se máš?", SpeechVoiceSpeakFlags.SVSFlagsAsync);//here occurs exeption

感谢您的想法。

【问题讨论】:

+1 for Ahoj, jak se máš? 看到与标准文本到语音包相同的问题 在 msdn social.msdn.microsoft.com/Forums/windowsapps/en-US/… 上添加了对该线程的简单复制 【参考方案1】:

据我所知,该软件尚不兼容 Windows 8。

Xtranormal 开发了这些语音包,以将其文本添加到动画软件中。

查看PC World 对该软件的评论表明,他们的 2.5 测试版规格适用于 Windows XP 和 Windows Vista。

请注意,PCWorld 审查是在 2010 年进行的。这次审查后集成了 Windows 7 支持。

注意到 Windows 7 发布滞后以及该软件升级到 Windows 7 兼容性也加强了我的论点,即 Windows 8 尚未准备好。 (windows 7 发布 5 个月后 pc world 审查了这个软件,它与 windows 7 不兼容,windows 8 还没有推出那么久,升级软件需要时间;)

在their own website 上查看他们的技术详细信息,建议最迟使用 Windows 7 的建议设置。

这对我来说表明他们尚未将其更新到 Windows 8。

(作为一个额外的脚注,YouTube 上没有关于 Windows 8 软件的单一教程,而是其他操作系统的大量教程,人们最近制作了关于任何东西的教程,并且缺少该操作系统的教程(尽管应用程序越来越多)两年来的流行再次表明,还没有 Windows 8 ;)

脚注上的注释,Software Informer 是一个网站,几乎所有可用的软件都经过审查,旧版本收到了 2 - 3 条评论,而最新版本提交了 260 条评论,因此已知受欢迎程度有所提高 )

脚注 2;我专注于该软件的原因是因为声音最初是为该软件设计的。因此,如果语音要升级,他们打算首先使用的软件可能会先升级)

你认为他们会在他们的网站上某个地方说他们支持什么操作系统:/

【讨论】:

【参考方案2】:

不确定这是否是答案,但每当我试图重复使用相同的媒体元素来一遍又一遍地播放不同的流时,我都会遇到同样的错误(例如,用户是按钮混搭)。解决方案是使用显式 GC.Collect()。虽然有 5 个媒体元素也不错,因为它似乎可以通过停止和重新启动音频来加快速度。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Media.SpeechSynthesis;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace SpeechMark

  /// <summary>
  /// An empty page that can be used on its own or navigated to within a Frame.
  /// </summary>
  public sealed partial class BlankPage1 : Page
  
    public BlankPage1()
    
      this.InitializeComponent();

      m_button.Click += m_button_Click;

      m_audioPlayerPool = new MediaElement[5];
      for(int index = 0; index < m_audioPlayerPool.Length; index++)
      
        var audioPlayer = new MediaElement();
        audioPlayer.AutoPlay = true;
        m_audioPlayerPool[index] = audioPlayer;
        m_grid.Children.Add(audioPlayer);
      

      m_textToSpeech = new SpeechSynthesizer();
    

    async void m_button_Click(object sender, RoutedEventArgs e)
    
      m_button.IsEnabled = false;
      if (m_audioPlayer != null)
      
        m_audioPlayer.Stop();
      

      if (m_stream != null)
      
        m_stream.Dispose();
        m_stream = null;
      

      GC.Collect();

      m_audioPlayer = m_audioPlayerPool[m_nextAudioPlayerToUse];
      m_nextAudioPlayerToUse = (m_nextAudioPlayerToUse + 1) % m_audioPlayerPool.Length;

      string ssml = "<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xml:lang=\"en\"><voice gender=\"female\" xml:lang=\"en\"><prosody rate=\"1\">how are you doing</prosody><mark name=\"utteranceComplete\"/></voice></speak>";
      m_stream = await m_textToSpeech.SynthesizeSsmlToStreamAsync(ssml);
      m_audioPlayer.SetSource(m_stream, m_stream.ContentType);

      m_button.IsEnabled = true;
    

    private MediaElement m_audioPlayer;
    private MediaElement[] m_audioPlayerPool;
    private int m_nextAudioPlayerToUse = 0;
    private SpeechSynthesizer m_textToSpeech;
    public SpeechSynthesisStream m_stream  get; set; 
  

xaml:

<Page
    x:Class="SpeechMark.BlankPage1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:SpeechMark"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid x:Name="m_grid" Background="ThemeResource ApplicationPageBackgroundThemeBrush">
    <Button x:Name="m_button" Height="128" Margin="446,303,0,337" Width="256"/>
  </Grid>
</Page>

【讨论】:

以上是关于使用其他语音时的文本到语音 SAPI5 AccessViolationException的主要内容,如果未能解决你的问题,请参考以下文章

语音/语音到文本[关闭]

如何在 C# 中使用 SpInprocRecoContext 识别语音事件?

从自己的声音文件语音到文本

树莓派怎么调用科大讯飞的语音库实现语音识别

如何自定义NeoSpeech语音库的发音

如何使用Microsoft speech将文本到语音和语音到文本功能添加到SIP软件