![]() |
Warten bis Sprachausgabe beendet
Ich möchte per Sprachausgabe einen Text ausgeben und solange warten, bis entweder der Text komplett gesprochen wurde, oder irgendeine Taste gedrückt wird.
Wenn der Text komplett gesprochen wurde, möchte ich einen Timer "enablen", und den Text nach einer gewissen Wartezeit erneut ausgeben. Wurde aber durch Drücken einer Taste abgebrochen, soll der Timer nicht "enabled" werden. Mein untenstehender Versuch, zunächst einmal zu warten, bis entweder der Text komplett gesprochen wurde, oder eine Taste gedrückt wurde, funktioniert nicht, weil das MsgWaitForMultipleObjects zurückkehrt, bevor der Text komplett gesprochen wurde, auch wenn keine Taste gedrückt wurde. Wie kann ich das realisieren? Und Frage am Rande: Muss ich Voice beim beenden des Programms irgenwie "freigeben" oder brauche ich mich darum nicht kümmern?
Delphi-Quellcode:
procedure TMain.FormShow(Sender: TObject);
begin Voice:=CreateOleObject('SAPI.SpVoice'); end; procedure TMain.Button1Click(Sender: TObject); var Reason:Cardinal; Ev:THandle; begin Edit1.Text:=''; Application.ProcessMessages; Voice.Speak('Hallo, ich warte jetzt, bis der Text zu ende ist, oder eine '+ 'Taste gedrückt wird.', 1); Ev:=Voice.SpeakCompleteEvent; Reason:=MsgWaitForMultipleObjects(1, Ev, False, Infinite, QS_Key); Edit1.Text:=IntToStr(Reason); end; |
AW: Warten bis Sprachausgabe beendet
Du könntest die SpeechLib_TLB.pas benutzen.
Dort ist das Server-Object // ************************************************** *******************// // OLE-Server-Proxy-Klassendeklaration // Server-Objekt : TSpVoice // Hilfe-String : SpVoice Class // Standard-Interface: ISpeechVoice // Def. Intf. DISP? : No // Ereignis-Interface: _ISpeechVoiceEvents // TypeFlags : (2) CanCreate // ************************************************** *******************// TSpVoice = class(TOleServer) Mit SpVoice1.Skip('Sentence', MaxInt) kannst du die Sprachausgabe stoppen Mit SpVoice1.Pause pausieren etc. Der OleServer läßt keine Wünsche offen. |
AW: Warten bis Sprachausgabe beendet
@Gerd01:
Danke, jedoch leider löst das nicht mein Problem. Ich möchte nicht die Ausgabe der Sprache beenden, pausieren etc. Sondern ich möchte solange warten, bis entweder der zu sprechende Text komplett gesprochen wurde oder eine Taste gedrückt wurde. Und ich brauche eine Information, ob "das Warten" beendet wurde, weil der Text komplett gesprochen wurde oder weil eine Taste gedrückt wurde. |
AW: Warten bis Sprachausgabe beendet
Dein Code entspricht ja ziemlich genau
![]() Funktioniert es* denn, wenn du mit WaitUntilDone oder WaitForSingleObject wartest bzw. was ist der Rückgabewert von MsgWaitForMultipleObjects? * Damit meine ich natürlich nur das Warten auf die Sprachausgaben :stupid: |
AW: Warten bis Sprachausgabe beendet
@Bug:
WaitUntilDone funktioniert, wartet also bis entweder der Text gesprochen ist, oder die als Parameter mitgegebene Zeit abgelaufen ist. WaitForSingleObject dto MsgWaitForMultipleObjects Der Rückgabewert ist immer = 1 |
AW: Warten bis Sprachausgabe beendet
Das bedeutet imho, dass dein Problem beim Aufwecken durch den Tastendruck (QS_Key) liegt und nicht bei der Sprachausgabe.
Eventuell könnte man es so beheben:
Delphi-Quellcode:
speechCanceled könnte dann bei Bedarf (also einer gewünschten Tasten-Aktion) in der Message-Behandlung des Formulars gesetzt werden.
procedure TMain.Button1Click(Sender: TObject);
var Reason:Cardinal; Ev:THandle; begin Edit1.Text:=''; Application.ProcessMessages; Voice.Speak('Hallo, ich warte jetzt, bis der Text zu ende ist, oder eine '+ 'Taste gedrückt wird.', 1); Ev:=Voice.SpeakCompleteEvent; // >>> speechCanceled := false; // "global" repeat Reason:=MsgWaitForMultipleObjects(1, Ev, False, Infinite, QS_Key); if Reason = (WAIT_OBJECT_0 + 1) then Application.ProcessMessages; until speechCanceled or (Reason = WAIT_OBJECT_0); // <<< Edit1.Text:=IntToStr(Reason); end; |
AW: Warten bis Sprachausgabe beendet
@Bug:
Das wird so nicht funktionieren, weil (zumindest bei mir) MsgWaitForMultipleObjects sofort zurückkehrt und konstant 1 als Resultat liefert. Zum Drücken einer Taste kommt es also gar nicht. Ich habe mein Problem jetzt so gelöst:
Delphi-Quellcode:
fSpeakCancelled wird in FormShortCut dann auf True gesetzt, wenn eine Taste gedrückt wird.
PROCEDURE TMain.Speak(Const S:String);
var Res:DWord; EV:THandle; begin Timer.Enabled:=False; Voice.Skip('SENTENCE',MaxInt); fSpeakCancelled:=False; Voice.Speak(S,1); EV:=Voice.SpeakCompleteEvent; repeat Res:=WaitForSingleObject(Ev,100); if Res=WAIT_TIMEOUT then Application.Processmessages; until (Res<>WAIT_TIMEOUT) or SpeakCancelled; if not SpeakCancelled then Timer.Enabled:=True; end; Mit Voice.WaitUntilDone klappte das merkwürdigerweise nicht. Danke für Deinen Hinweis auf WaitForSingleObject, das ich von vornherein verworfen hatte. Da ich ja nicht nur auf das Ende der Sprachausgabe sondern parallel auch auf Tastendrücke warten wollte war ich auf MsgWaitForMultipleObjects fixiert. |
AW: Warten bis Sprachausgabe beendet
Zitat:
stehen bei der Komponente aber zur Verfügung: property OnStartStream: TSpVoiceStartStream read FOnStartStream write FOnStartStream; property OnEndStream: TSpVoiceEndStream read FOnEndStream write FOnEndStream; property OnVoiceChange: TSpVoiceVoiceChange read FOnVoiceChange write FOnVoiceChange; property OnBookmark: TSpVoiceBookmark read FOnBookmark write FOnBookmark; property OnWord: TSpVoiceWord read FOnWord write FOnWord; property OnSentence: TSpVoiceSentence read FOnSentence write FOnSentence; property OnPhoneme: TSpVoicePhoneme read FOnPhoneme write FOnPhoneme; property OnViseme: TSpVoiceViseme read FOnViseme write FOnViseme; property OnAudioLevel: TSpVoiceAudioLevel read FOnAudioLevel write FOnAudioLevel; property OnEnginePrivate: TSpVoiceEnginePrivate read FOnEnginePrivate write FOnEnginePrivate; |
AW: Warten bis Sprachausgabe beendet
Danke, Gerd.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:23 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz