Как использовать лексикон с SpeechSynthesizer?

Я выполняю некоторые тексты в речь, и я хотел бы указать некоторые специальные произношения в файле лексики. Я выполнил MSDN AddLexicon example дословно, и он произносит предложение, но он не использует данный лексикон, что-то кажется сломанным.

Здесь приведенный пример:

using System;
using Microsoft.Speech.Synthesis;

namespace SampleSynthesis
{
  class Program
  {
    static void Main(string[] args)
    {

      // Initialize a new instance of the SpeechSynthesizer.
      using (SpeechSynthesizer synth = new SpeechSynthesizer())
      {

        // Configure the audio output. 
        synth.SetOutputToDefaultAudioDevice();

        PromptBuilder builder = new PromptBuilder();
        builder.AppendText("Gimme the whatchamacallit.");

        // Append the lexicon file.
        synth.AddLexicon(new Uri("c:\\test\\whatchamacallit.pls"), "application/pls+xml");

        // Speak the prompt and play back the output file.
        synth.Speak(builder);
      }

      Console.WriteLine();
      Console.WriteLine("Press any key to exit...");
      Console.ReadKey();
    }
  }
}

и файл лексики:

<lexicon version="1.0" 
      xmlns="http://www.w3.org/2005/01/pronunciation-lexicon"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://www.w3.org/2005/01/pronunciation-lexicon 
        http://www.w3.org/TR/2007/CR-pronunciation-lexicon-20071212/pls.xsd"
      alphabet="x-microsoft-ups" xml:lang="en-US">


  <lexeme>
    <grapheme> whatchamacallit </grapheme>
    <phoneme> W S1 AX T CH AX M AX K S2 AA L IH T </phoneme>
  </lexeme>

</lexicon>

Консоль открывается, текст говорит, но новое произношение не используется. Я, конечно, сохранил файл в c:\test\whatchamacallit.pls, как указано.

Я пробовал варианты местоположения Uri и файла (например, @"C:\Temp\whatchamacallit.pls", @"file:///c:\test\whatchamacallit.pls"), абсолютные и относительные пути, копирование их в папку сборки и т.д.

Я запустил Process Monitor, и файл не доступен. Если это была проблема с правами на доступ к каталогу/файлу (а это не так), я все равно увижу сообщения об отказах в доступе, однако я не регистрирую ссылку вообще, за исключением случайного из моего текстового редактора. Я вижу доступ к файлу при попытке File.OpenRead.

К сожалению, при использовании мусора Uri нет сообщений об ошибках.

В ходе дальнейшего исследования я понял, что этот пример из Microsoft.Speech.Synthesis, тогда как я использую System.Speech.Synthesis здесь. Однако из того, что я могу сказать, они идентичны, за исключением некоторой дополнительной информации и примеров, и оба указывают на ту же спецификацию. Может ли это быть проблемой?

Я подтвердил, что проект настроен на использование правильной .NET Framework 4.

Я сравнил пример из MSDN с примерами из ссылочной спецификации, а также попробовал их прямо, но это не помогло. Учитывая, что файл, похоже, не доступен, я не удивлен.

(Я могу использовать PromptBuilder.AppendTextWithPronunciation просто отлично, но это плохая альтернатива для моего использования.)

Является ли пример на MSDN сломанным? Как использовать лексикон с SpeechSynthesizer?

Ответы

Ответ 1

После многих исследований и подводных камней я могу заверить вас, что ваше предположение просто неверно. По какой-то причине System.Speech.Synthesis.SpeechSynthesizer.AddLexicon() добавляет лексикон во внутренний список, но не использует его вообще. Похоже, что никто не пытался использовать его раньше, и эта ошибка осталась незамеченной.

Microsoft.Speech.Synthesis.SpeechSynthesizer.AddLexicon() (который принадлежит Microsoft Speech SDK), с другой стороны работает как ожидалось (он передает лексику на COM-объект, который интерпретирует его как рекламируемый).

В этом руководстве описано, как установить SDK: http://msdn.microsoft.com/en-us/library/hh362873%28v=office.14%29.aspx

Примечания:

  • люди сообщали, что 64-разрядная версия вызывает исключения COM (потому что библиотека не устанавливается корректно), я подтвердил это на 64-битной машине Windows 7
    • использование версии x86 обходит проблему
  • обязательно установите время выполнения перед SDK
  • не забудьте также установить язык выполнения (как указано на связанной странице), поскольку SDK не использует системный речевой механизм по умолчанию.