不是答案,而是解决方法。
[试图在Delphi 10.3中将MS Speech API v11与日语引擎(MS Haruka)一起使用]]
我有一个带有表单和按钮的示例应用程序。点击处理程序转到:
uses SpeechLib11_TLB; // Imported from "Microsoft Speech Object Library" v.B.0 procedure TForm1.Button1Click(Sender: TObject); var v: ISpeechVoice; begin v := CoSpVoice.Create(); v.Speak('時間', SVSFDefault); end;
这将导致错误“灾难性故障”(HRESULT 0x8000FFFF,E_UNEXPECTED)。我认为应该等效的代码可以在C ++项目中使用:
在计算机上没有损坏。在两个项目中,平台均为Win32,而不是Win64。日语声音是默认声音(无需明确设置)。#include <windows.h> #import "libid:d3c4a7f2-7d27-4332-b41f-593d71e16db1" rename_namespace("SAPI") //v11 int wmain() { CoInitializeEx(0, COINIT_APARTMENTTHREADED); { SAPI::ISpeechVoicePtr v; v.CreateInstance(__uuidof(SAPI::SpVoice)); v->Speak(L"時間", SAPI::SVSFDefault); } CoUninitialize(); return 0; }
这行之有效。因此,SAPI 本身
[进一步的调试揭示了在Delphi方面,与在第一行引起相同错误E_UNEXPECTED之后立即调用v.Voice
属性getter一样多。同时,如果您从Voice
传递有效的语音令牌对象,则GetVoices()
setter
C ++和Delphi之间在进程/线程范围执行上下文上有什么不同?
不是线程语言环境。 COM线程模型在这两者中都是共同的。[同一Delphi代码使用英语短语和英语语音(MS Helen)。因此,无论有什么初始化失败,都可能是Haruka特有的。
SAPI 11运行时可用here。 TTS的语言数据为here。
另一个数据点。我已经在Delphi中重写了SAPI逻辑以改为使用SAPI 5.4 OneCore(不适用于SAPI 5.4)。与5.4和11不同,它没有公开基于IDispatch的接口,并且在Delphi中特别笨拙,但是日语TTS可以工作。最初提出的问题仍然没有答案,但是至少有一种解决方法。我会写一个答案,但我不会接受。
但是,不是归咎于习惯与双重区别。我已经更改了逻辑,以使用自定义接口代替自动化接口使用SAPI 5.4适当
(typelib定义了两者),仍然从E_UNEXPECTED
获得了Speak()
。[试图在Delphi 10.3中将MS Speech API v11与日语引擎(MS Haruka)一起使用。我有一个带有表单和按钮的示例应用程序。点击处理程序变为:使用SpeechLib11_TLB; //从“ ...
导入>不是答案,而是解决方法。
Windows 10带有两种32位SAPI。有适当的SAPI 5.4(在system32\speech
中),还有SAPI 5.4 OneCore(在system32\speech_onecore
中)。后者,即使表面上是一样的,但暴露了不同的typelib-没有自动化支持,所有接口都是自定义的,而不是双重的。更重要的是,当您在Windows 10设置应用程序中下载日语TTS语音时,最终在OneCore(Sayaka, somehow, missing)下只有3种语音,而在5.4以下,只有一种Haruka。
Delphi可以在typelib中使用自定义接口,但是这些方法看起来有些笨拙。此外,自动化API中的声音枚举更加清晰。无论如何,这里去。
uses SpeechLib54Core_TLB; // This time it's OneCore
procedure TForm1.Button1Click(Sender: TObject);
var
v: ISpVoice;
cat: ISpObjectTokenCategory;
toks: IEnumSpObjectTokens;
tok: ISpObjectToken;
sno: LongWord;
hr: HResult;
begin
cat := CoSpObjectTokenCategory.Create();
hr := cat.SetId('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech_OneCore\Voices', 0);
hr := cat.EnumTokens('language=411', '', toks);
v := CoSpVoice.Create();
hr := toks.Item(0, tok);
v.SetVoice(tok);
v.Speak('時間', 0, sno);
end;
不是答案,而是解决方法。