Delphi SAPI Text-to-Speech

Tout d'abord: ce n'est pas un doublon de Delphi et SAPI. J'ai un problème spécifique avec le "SAPI en Delphi" objet.

J'ai utilisé l'excellent Type d'Importation de la Bibliothèque-guide en Delphi 2009 pour obtenir un TSpVoice composant dans la palette de composants. Cela fonctionne très bien. Avec

var
  SpVoice: TSpVoice;

Je peux écrire

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

pour obtenir asynchrone de sortie audio.

Première question

Selon la documentation, je serais capable d'écrire

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

pour obtenir synchrone sortie audio, mais au lieu de cela, je reçois un EZeroDivide exception. Pourquoi?

Deuxième question

Mais plus important encore, je voudrais être en mesure de créer le SpVoice objet dynamiquement (je pense que c'est appelé à la "fin de l'-lier" la SpVoice objet), en partie parce que seule une très petite fraction de toutes les sessions de mon application va utiliser, et en partie parce que je ne veux pas présumer de l'existence de la SAPI server sur le système de l'utilisateur final.

À cette fin, j'ai essayé

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

qui, apparemment, ne fait rien du tout! (En remplaçant le 0 par 1 me donne la EZeroDivide exception).

Avertissement

Je suis plutôt nouveau COM/OLE automation. Je suis désolé pour tout à l'ignorance ou la stupidité montré par moi dans ce post...

Mise à jour

Pour le bénéfice de tout le monde rencontre le même problème que moi, la vidéo de François expliqué il y a un bug dans SAPI/Windows (d'une incompatibilité quelque part), ce qui rend le code suivant élever le EZeroDivide exception:

procedure TForm1.FormClick(Sender: TObject);
var
  SpVoice: variant;
begin
  SpVoice := CreateOleObject('SAPI.SpVoice');
  SpVoice.Speak('This is a text.');
end;

La solution, tel que présenté par la vidéo, est de modifier la FPU mot de contrôle:

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;

Et, en outre, si vous voulez jouer un son en mode asynchrone, vous devez vous assurer que le joueur n'est pas hors de portée!