Prima di tutto: questo non è un duplicato di Delphi and SAPI. Ho un problema specifico con l'argomento "SAPI in Delphi".Delphi SAPI Text-To-Speech
Ho utilizzato l'eccellente guida alla libreria dei tipi di importazione in Delphi 2009 per ottenere un componente TSpVoice nella palette dei componenti. Funziona alla grande Con
var
SpVoice: TSpVoice;
posso scrivere
SpVoice.Speak('This is an example.', 1);
per ottenere asincrono uscita audio.
Prima domanda
Secondo la documentazione, sarei in grado di scrivere
SpVoice.Speak('This is an example.', 0);
per ottenere sincrona uscita audio, ma invece io ottenere un'eccezione EZeroDivide. Perché?
Seconda domanda
Ma ancora più importante, vorrei essere in grado di creare l'oggetto SpVoice dinamicamente (credo che questo è chiamato a "tardo-bind" l'oggetto SpVoice), in parte perché solo una piccola parte di tutte le sessioni della mia app lo utilizzerà, in parte perché non voglio assumere l'esistenza del server SAPI sul sistema dell'utente finale.
A tal fine, ho provato
procedure TForm1.FormClick(Sender: TObject);
var
SpVoice: Variant;
begin
SpVoice := CreateOleObject('SAPI.SpVoice');
SpVoice.Speak('this is a test', 0);
end;
che apparentemente non fa nulla a tutti! (Sostituzione del 0 con 1 mi dà l'eccezione EZeroDivide.)
responsabilità
Sono piuttosto nuovo per l'automazione COM/OLE. Mi dispiace per qualsiasi ignoranza o stupidità mostrata da me in questo post ...
Aggiornamento
Per il bene di tutti incontrare lo stesso problema come ho fatto io, il video di François spiegato c'è un bug in SAPI/Windows (certa incompatibilità da qualche parte), il che rende il codice seguente sollevare l'eccezione EZeroDivide:
procedure TForm1.FormClick(Sender: TObject);
var
SpVoice: variant;
begin
SpVoice := CreateOleObject('SAPI.SpVoice');
SpVoice.Speak('This is a text.');
end;
la soluzione, così come presentato dal video, è di alterare la parola di controllo 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;
E, inoltre, se si desidera riprodurre un suono in modo asincrono, è necessario assicurarsi che il lettore non vada fuori campo!
Ah, grazie mille! Quindi non ero semplicemente stupido, allora! –
BTW: Sentiti libero di rimuovere il punto interrogativo accanto al tuo nome se vuoi prendere il merito del video! :) –