SAPI con Dephi: el habla asincrónica no funciona
Frecuentes
Visto 2,353 veces
5
The following works perfectly (Delphi 7):
procedure TMainForm.SayIt(s:string); // s is the string to be spoken
var
voice: OLEVariant;
begin
memo1.setfocus;
voice := CreateOLEObject ('SAPI.SpVoice');
voice.Voice := voice.GetVoices.Item(combobox1.ItemIndex); // current voice selected
voice.volume := tbVolume.position;
voice.rate := tbRate.position;
voice.Speak (s, SVSFDefault);
end;
The above works in "sync" mode (SVSFDefault flag), but if I change the flag to SVSFlagsAsync in an attempt to play the sound in async mode, no soud is produced. No error messages are given, but nothing is played on the speakers.
What might the problem be? I have the SpeechLib_TLB unit in Delphi's Imports folder.
EDIT: This is in Windows XP
Thanks, Bruno.
1 Respuestas
7
Cuando usa el SVSFlagsAsync flag, the voice stream is queued in an internal buffer and stay waiting to be executed by the speech service, So I think which you issue is related to the lifetime of the voice object, because is a local variable , the instance is destroyed before to execute the sound.
As workaround you can wait for the sound, using the WaitUntilDone
Método
voice.Speak (s, SVSFlagsAsync);
repeat Sleep(100); until voice.WaitUntilDone(10);
or declare the voice
variable in you form definition.
TMainForm = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
voice: OLEVariant;
procedure SayIt(const s:string);
end;
var
MainForm: TMainForm;
implementation
uses
ComObj;
{$R *.dfm}
procedure TMainForm.SayIt(const s:string); // s is the string to be spoken
const
SVSFDefault = 0;
SVSFlagsAsync = 1;
SVSFPurgeBeforeSpeak= 2;
begin
memo1.setfocus;
voice.Voice := voice.GetVoices.Item(combobox1.ItemIndex); // current voice selected
voice.volume := tbVolume.position;
voice.rate := tbRate.position;
voice.Speak (s, SVSFlagsAsync {or SVSFPurgeBeforeSpeak});
end;
procedure TMainForm.Button1Click(Sender: TObject);
begin
SayIt('Hello');
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
voice := CreateOLEObject('SAPI.SpVoice');
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
voice := Unassigned;
end;
end.
As additional note, since you are using late binding you don't need the SpeechLib_TLB unit.
Respondido 25 ago 12, 18:08
WaitUntilDone turns it into synchronous. So prob not what's needed. Last paragraph could alternatively be stated: if you are using import lib, then you could switch to early binding. +1 - David Heffernan
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas delphi delphi-7 sapi text-to-speech or haz tu propia pregunta.
Long time ago I played with SAPI, in order to make it async, I've created a thread with a queue which proved to work quite nice. - user497849