Pregunta

En primer lugar: esto no es un duplicado de Delphi y Sapi. Tengo un problema específico con el tema "SAPI en Delphi".

He utilizado la excelente guía de bibliotecas de tipo de importación en Delphi 2009 para obtener un componente TSPVOICE en la paleta de componentes. Esto funciona muy bien. Con

var
  SpVoice: TSpVoice;

puedo escribir

SpVoice.Speak('This is an example.', 1);

Llegar asincrónico salida de audio.

Primera pregunta

Según la documentación, podría escribir

SpVoice.Speak('This is an example.', 0);

Llegar sincrónico Salida de audio, pero en cambio obtengo una excepción de EzeroDivide. ¿Porque eso?

Segunda pregunta

Pero lo que es más importante, me gustaría poder crear dinámicamente el objeto Spvoice (creo que esto se llama a "unión tardía" el objeto Spvoice), en parte porque solo una fracción muy pequeña de todas las sesiones de mi aplicación lo usará, Y en parte porque no quiero asumir la existencia del servidor SAPI en el sistema del usuario final.

Para este fin, lo intenté

procedure TForm1.FormClick(Sender: TObject);
var
  SpVoice: Variant;
begin
  SpVoice := CreateOleObject('SAPI.SpVoice');
  SpVoice.Speak('this is a test', 0);
end;

¡Lo que aparentemente no hace nada en absoluto! (Reemplazar el 0 con 1 me da la excepción de Ezerodivide).

Descargo de responsabilidad

Soy bastante nuevo en la automatización de com/ole. Lo siento por cualquier ignorancia o estupidez que me muestre en esta publicación ...

Actualizar

En beneficio de que todos se encuentren con el mismo problema que yo, el video de François explicó que hay un error en SAPI/Windows (algo de incompatibilidad en algún lugar), lo que hace que el siguiente código aumente la excepción de EzeroDivide:

procedure TForm1.FormClick(Sender: TObject);
var
  SpVoice: variant;
begin
  SpVoice := CreateOleObject('SAPI.SpVoice');
  SpVoice.Speak('This is a text.');
end;

La solución, según lo presentado por el video, es alterar la palabra de control de 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;

Y, además, si quieres tocar un sonido asincrónico, ¡entonces debes asegurarte de que el jugador no salga del alcance!

¿Fue útil?

Solución

Puede que te parezca interesante ver Esta sesión de Coderage 4 en "Discurso que habilita las aplicaciones Delphi (ZIP)"Obtendrás el "cómo hacer" estás buscando ... (y supongo que estás en Vista o + como la división cero no sucedió en XP)

Otros consejos

Estaba teniendo el mismo problema en Delphi XE2. los Set8087CW(SavedCW or $4) La solución presentada en la pregunta no funcionó para mí. Simplemente reemplazó la división por cero excepción con otra excepción de punto flotante.

Lo que funcionó para mí es esto:

SavedCW := Get8087CW;
SetFPUExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]);
SpVoice.Speak('All floating point exceptions disabled!', 0);
Set8087CW(SavedCW);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top