首先:这不是Delphi 和 SAPI的副本。我对“SAPI in Delphi”主题有一个特定的问题。
我使用 Delphi 2009 中出色的 Import Type-Library 指南在组件面板中获取 TSpVoice 组件。这很好用。和
var
SpVoice: TSpVoice;
我可以写
SpVoice.Speak('This is an example.', 1);
获得异步音频输出。
第一个问题
根据文档,我可以写
SpVoice.Speak('This is an example.', 0);
获得同步音频输出,但我得到一个 EZeroDivide 异常。为什么?
第二个问题
但更重要的是,我希望能够动态创建 SpVoice 对象(我认为这被称为“后期绑定”SpVoice 对象),部分原因是我的应用程序的所有会话中只有一小部分会使用它,部分原因是我不想假设最终用户系统上存在 SAPI 服务器。
为此,我尝试了
procedure TForm1.FormClick(Sender: TObject);
var
SpVoice: Variant;
begin
SpVoice := CreateOleObject('SAPI.SpVoice');
SpVoice.Speak('this is a test', 0);
end;
这显然什么都不做!(用 1 替换 0 会给我 EZeroDivide 异常。)
免责声明
我对 COM/OLE 自动化相当陌生。对于我在这篇文章中表现出的任何无知或愚蠢,我深表歉意......
更新
为了让遇到与我相同的问题的每个人都受益,François 的视频解释了 SAPI/Windows 中存在一个错误(某些地方不兼容),这使得以下代码引发了 EZeroDivide 异常:
procedure TForm1.FormClick(Sender: TObject);
var
SpVoice: variant;
begin
SpVoice := CreateOleObject('SAPI.SpVoice');
SpVoice.Speak('This is a text.');
end;
如视频所示,解决方案是更改 FPU 控制字:
procedure TForm1.FormClick(Sender: TObject);
var
SpVoice: variant;
SavedCW: Word;
begin
SpVoice := CreateOleObject('SAPI.SpVoice');
SavedCW := Get8087CW;
Set8087CW(SavedCW or $4);
SpVoice.Speak('This is a text.');
Set8087CW(SavedCW);
end;
此外,如果您想异步播放声音,则必须确保播放器不会超出范围!