[Delphi GUI vs控制台中的SAPI 5.4 / 11日文TTS

问题描述 投票:0回答:1

[试图在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();
    //5.4 only but won't hurt
    v.Voice := v.GetVoices('language=411', '').Item(0);

    v.Speak('時間', SVSFDefault);
end;

这将导致错误“灾难性故障”(HRESULT 0x8000FFFF,E_UNEXPECTED)。我认为应该等效的代码可以在C ++项目中使用:

#include <windows.h>
#import "libid:d3c4a7f2-7d27-4332-b41f-593d71e16db1" rename_namespace("SAPI") //v11
//#import "libid:C866CA3A-32F7-11D2-9602-00C04F8EE628" rename_namespace("SAPI") //v5.4

int wmain()
{
    CoInitializeEx(0, COINIT_APARTMENTTHREADED);
    {
        SAPI::ISpeechVoicePtr v;
        v.CreateInstance(__uuidof(SAPI::SpVoice));

        //Needed for 5.4 only, but won't hurt
        SAPI::ISpeechObjectTokensPtr voices(v->GetVoices(L"language=411", L""));
        v->Voice = voices->Item(0);

        v->Speak(L"時間", SAPI::SVSFDefault);
    }
    CoUninitialize();
    return 0;
}

这行之有效。因此,SAPI 本身

在计算机上没有损坏。在两个项目中,平台均为Win32,而不是Win64。日语声音是默认声音(无需明确设置)。

与SAPI 5.4正确的结果相同(不是OneCore,尽管日语声音不是默认声音,并且我不得不添加几行以将其设置为默认声音。


[进一步的调试揭示了在Delphi方面,与在第一行引起相同错误E_UNEXPECTED之后立即调用v.Voice属性getter一样多。同时,如果您从Voice传递有效的语音令牌对象,则GetVoices() setter

将起作用。似乎语音对象在C ++中正确地将其自身初始化为默认值,但在Delphi项目中却以某种方式跳过了它。

尽管在带有SAPI 5.4的Delphi中,构造后仍可立即请求v.Voice。调用Speak()仍会引发E_UNEXPECTED。

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适当

(类型库定义了两者),仍然从E_UNEXPECTED获得了Speak()。没有错误信息。

这里是另一个漂亮的数据点:具有基于自动化API的SAPI 5.4 TTS可以按预期工作和对话在Delphi控制台应用程序中>]。因此,它甚至不是特定于Delphi的,而是特定于VCL的。 Delphi GUI是什么?

[试图在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;
    n: Cardinal;
begin
    v := CoSpVoice.Create();
    hr := v.GetVoice(tok);
    tok.GetCategory(cat);
    cat.EnumTokens('language=411', '', toks); //411 means Japanese
    toks.GetCount(n);
    if n = 0 then
        exit; // No Japanese voices installed
    toks.Item(0, tok); //Take the first one - typically Ayumi
    v.SetVoice(tok);

    v.Speak('時間', 0, sno);
end;

请注意,将日语字符串文字传递给COM方法无需显式转换为宽字符串即可。

delphi com text-to-speech
1个回答
1
投票

不是答案,而是解决方法。

© www.soinside.com 2019 - 2024. All rights reserved.