10

まず第一に、これはDelphi と SAPIの複製ではありません。「Delphi の SAPI」という件名に特定の問題があります。

コンポーネント パレットで TSpVoice コンポーネントを取得するために、Delphi 2009 の優れた Import Type-Library ガイドを使用しました。これはうまくいきます。と

var
  SpVoice: TSpVoice;

私は書くことができます

SpVoice.Speak('This is an example.', 1);

非同期オーディオ出力を取得します。

最初の質問

ドキュメントによると、私は書くことができるでしょう

SpVoice.Speak('This is an example.', 0);

同期オーディオ出力を取得しますが、代わりに EZeroDivide 例外が発生します。なぜですか?

2 番目の質問

しかし、もっと重要なことは、SpVoice オブジェクトを動的に作成できるようにしたいということです (これは、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;

さらに、サウンドを非同期で再生したい場合は、プレーヤーが範囲外にならないようにする必要があります。

4

2 に答える 2

4

この CodeRage 4 セッション「Delphi アプリケーションの音声認識 (zip)」を参照 すると、お探しの「ハウツー」が得られます... (Vista または + を使用していると思いますXPではゼロ除算は発生しませんでした)

于 2010-06-13T21:46:23.627 に答える
1

Delphi XE2 でも同じ問題が発生していました。質問で提示されたSet8087CW(SavedCW or $4)解決策は私にとってはうまくいきませんでした。ゼロ除算例外を別の浮動小数点例外に置き換えただけです。

私にとってうまくいったのはこれです:

SavedCW := Get8087CW;
SetFPUExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]);
SpVoice.Speak('All floating point exceptions disabled!', 0);
Set8087CW(SavedCW);
于 2012-12-28T02:10:43.743 に答える