2010-06-13 10 views
11

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!

risposta

4

Potresti trovare interessante vedere this CodeRage 4 session su "Speech Enabling Delphi Applications (zip)" Otterrai il "how-to" che stai cercando ... (e suppongo che tu sia su Vista o + perché il divario zero non è accaduto su XP)

+0

Ah, grazie mille! Quindi non ero semplicemente stupido, allora! –

+0

BTW: Sentiti libero di rimuovere il punto interrogativo accanto al tuo nome se vuoi prendere il merito del video! :) –

1

Avevo lo stesso problema in Delphi XE2. La soluzione Set8087CW(SavedCW or $4) presentata nella domanda non ha funzionato per me. Ha semplicemente sostituito la divisione per eccezione zero con un'altra eccezione in virgola mobile.

Che cosa ha fatto il lavoro per me è questo:

SavedCW := Get8087CW; 
SetFPUExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]); 
SpVoice.Speak('All floating point exceptions disabled!', 0); 
Set8087CW(SavedCW);