首先:这不是Delphi and SAPI的重复项。我对“Delphi中的SAPI”主题有特定的疑问。

我使用了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对象(我认为这是“后期绑定(bind)” SpVoice对象),部分原因是我的应用程序中只有很小一部分会使用它,部分是因为我不想假设最终用户系统上存在SAPI服务器。

为此,我尝试了
procedure TForm1.FormClick(Sender: TObject);
var
  SpVoice: Variant;
begin
  SpVoice := CreateOleObject('SAPI.SpVoice');
  SpVoice.Speak('this is a test', 0);
end;

显然什么也没做! (将0替换为1会给我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;

另外,如果您要异步播放声音,则必须确保播放器不会超出范围!

最佳答案

您可能会发现在this CodeRage 4 session上看到"Speech Enabling Delphi Applications (zip)"很有趣
您将获得所需的“方法”。
(我猜您使用的是Vista或+,因为XP上没有发生过零差)

10-07 19:22
查看更多