2010-05-07 9 views
5

Ich habe versucht herauszufinden, wie man einen Text mit Windows SAPI 5.1 in einen Speicherpuffer "spricht", aber bisher kein Erfolg, obwohl es scheint, dass es ziemlich einfach sein sollte.C++ Microsoft SAPI: Wie Windows Text-zu-Sprache-Ausgabe zu einem Speicherpuffer festlegen?

Es gibt an example Streaming der synthetisierten Sprache in eine WAV-Datei, aber keine Beispiele, wie Sie es in einen Speicherpuffer streamen.

Am Ende muss ich die synthetisierte Sprache in einem char * -Array in 16-kHz-16-Bit-Little-Endian-PCM-Format haben. Momentan erstelle ich eine temporäre .wav-Datei, leite die Sprachausgabe dorthin um und lese sie dann, aber es scheint eine ziemlich dumme Lösung zu sein.

Wer weiß, wie man das macht?

Danke!

+0

haben Sie es geschafft, es zu tun? – Yashasvi

Antwort

0

Wissen Sie, wie Sie eine Memory-Mapped-Datei erstellen? Sie können sehen, ob die ISpStream an sie bindet.

6

Betrachten Sie ISpStream :: SetBaseStream. Hier ist ein kleiner Helfer:

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, Wie können Sie herausfinden, welche Größe Sie für den GlobalAlloc-Aufruf benötigen, um den HGLOBAL-Speicherzugriff zu erhalten? Ich vermute, es würde variieren, je nachdem wie viel gesprochen wird, aber wie kann man das herausfinden? –

+0

Sie müssen nicht. Der Speicherstream, der von :: CreateStreamOnHGlobal verwaltet wird, wird den Speicher nach Bedarf neu zuordnen. –

+0

Ich habe dieses Beispiel als Grundlage für meine Implementierung von Streaming-Sprache in einen Puffer verwendet. Aber beim Lesen aus dem IStream-Objekt bekomme ich immer null Bytes gelesen. Beim Betrachten des Stream-Objekts wurden Bytes geschrieben (unter Verwendung von Stream :: Stat). Muss ich IStream :: LockRegion verwenden, um die Daten zu erhalten? – pettersson

1

Ich erreichte es mit dem ISpStream. Verwenden Sie die Setbasestream-Funktion des ispstream, um sie an einen istream zu binden, und setzen Sie dann die Ausgabe von ispvoice auf diesen ispstream.

Hier ist meine Arbeitslösung, wenn jemand es will:

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

Verwandte Themen