Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SAPI with Dephi: Async speech doesn't work

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.

like image 263
BrunoBL Avatar asked Aug 24 '12 23:08

BrunoBL


1 Answers

When you uses the 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 method

  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.

like image 157
RRUZ Avatar answered Sep 19 '22 14:09

RRUZ