2010-05-07 17 views
5

He estado tratando de encontrar la forma de "hablar" un texto en un búfer de memoria utilizando Windows SAPI 5.1 pero hasta ahora no ha tenido éxito, aunque parece que debería ser bastante simple.C++ Microsoft SAPI: ¿Cómo establecer la salida de texto a voz de Windows en un búfer de memoria?

Hay an example de transmisión de voz sintetizada en un archivo .wav, pero no hay ejemplos de cómo transmitirlo a un búfer de memoria.

Al final necesito tener el discurso sintetizado en una matriz de caracteres * en formato PCM 16-bit 16-bitian little-endian. Actualmente creo un archivo .wav temporal, redirijo la salida de voz allí, luego lo leo, pero parece ser una solución bastante estúpida.

¿Alguien sabe cómo hacer eso?

Gracias!

+0

hiciste para hacerlo? – Yashasvi

Respuesta

0

¿Sabes cómo crear un archivo mapeado en memoria? Podrías ver si el ISpStream se enlazará.

6

Mire ISpStream :: SetBaseStream. Aquí hay un pequeño ayudante:

inline HRESULT SPCreateStreamOnHGlobal(
        HGLOBAL hGlobal,   //Memory handle for the stream object 
        BOOL fDeleteOnRelease,  //Whether to free memory when the object is released 
        const WAVEFORMATEX * pwfex, //WaveFormatEx for stream 
        ISpStream ** ppStream)  //Address of variable to receive ISpStream pointer 
{ 
    HRESULT hr; 
    IStream * pMemStream; 
    *ppStream = NULL; 
    hr = ::CreateStreamOnHGlobal(hGlobal, fDeleteOnRelease, &pMemStream); 
    if (SUCCEEDED(hr)) 
    { 
     hr = ::CoCreateInstance(CLSID_SpStream, NULL, CLSCTX_ALL, __uuidof(*ppStream), (void **)ppStream); 
     if (SUCCEEDED(hr)) 
     { 
      hr = (*ppStream)->SetBaseStream(pMemStream, SPDFID_WaveFormatEx, pwfex); 
      if (FAILED(hr)) 
      { 
       (*ppStream)->Release(); 
       *ppStream = NULL; 
      } 
     } 
     pMemStream->Release(); 
    } 
    return hr; 
} 
+0

Eric, ¿Cómo podría averiguar el tamaño que necesita para la llamada de GlobalAlloc para obtener el asa de memoria HGLOBAL? Supongo que variaría dependiendo de la cantidad de habla que se hable, pero ¿cómo puedes averiguarlo? –

+0

No es necesario. La secuencia de memoria administrada por :: CreateStreamOnHGlobal reasignará la memoria según sea necesario. –

+0

Utilicé este ejemplo como base para la implementación de la transmisión de voz a un búfer. Pero cuando leo desde el objeto IStream, siempre obtengo cero bytes leídos. Al observar el objeto de transmisión, se escribieron bytes (utilizando Stream :: Stat). ¿Debo usar IStream :: LockRegion para obtener los datos? – pettersson

1

Lo logré utilizando el ISpStream. Utilice la función Setbasestream de ispstream para vincularla a istream y luego establezca el resultado de ispvoice en ispstream.

Aquí está mi solución de trabajo si alguien lo quiere:

https://github.com/itsyash/MS-SAPI-demo

Cuestiones relacionadas