locked
[C++] Reading from an IStream to a Buffer (Audio) RRS feed

  • Question

  • I am basically trying to read the contents of an audio stream into a char * buffer to apply an FFT. I am using SAPI to simplify the transformations I will need to make after applying my FFT.

    I have an IStream buffer I allocated on HGLOBAL

    // Address of IStream* pointer variable that receives the interface pointer to the new stream object.
    CComPtr<IStream> pMemStream;
    // A memory handle allocated by the GlobalAlloc function, or if NULL a new handle is to be allocated instead.
    HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, sizeof(pMemStream));
    // Create stream object that uses an HGLOBAL memory handle to store the stream contents.
    hr = ::CreateStreamOnHGlobal(hGlobal, TRUE, &pMemStream);

    I then wrote wav contents to this stream

    // Variable to receive ISpStream pointer
    CComPtr<ISpStream> cpSpStream;
    hr = cpSpStream.CoCreateInstance(CLSID_SpStream);
    hr = cpSpStream->SetBaseStream(pMemStream, SPDFID_WaveFormatEx, defaultStreamFormat.WaveFormatExPtr());
    hr = cpVoice->SetOutput(cpSpStream, TRUE);
    hr = cpVoice->Speak(L"This is a phrase.", SPF_DEFAULT, NULL);

    I can verify that the stream contains the wav contents by speaking the stream:

    // Speak the modified stream.
    cpVoice->SetOutput(NULL, FALSE);
    cpVoice->SpeakStream(cpSpStream, SPF_DEFAULT, NULL);

    However, when I try and get the buffer for the stream, I read only garbage data (all '=' in buffer).

    IStream *pIstream;
    cpSpStream->GetBaseStream(&pIstream);
    STATSTG stats;
    pIstream->Stat(&stats, STATFLAG_NONAME);
    ULONG sSize = stats.cbSize.QuadPart;
    ULONG bytesRead;
    char *pBuffer = new char[sSize];
    pIstream->Read(pBuffer, sSize, &bytesRead);

    What am I doing wrong? This is driving me nuts.

    Thanks,

    -Francisco


    -Francisco Aguilera University of Washington Student | Prospective Computer Science Major | Microsoft Student Partner http://students.washington.edu/falven | http://www.facebook.com/falven

    Wednesday, March 13, 2013 6:15 AM

Answers

All replies

  • Let me make sure I understand what you're trying to accomplish.

    You're using SAPI to do text-to-speech, using the Microsoft provided voice.

    Then you want to apply some effects to the captured audio, and play it back.

    Is that correct?


    Matthew van Eerde

    Wednesday, March 13, 2013 2:32 PM
  • Yes, that is correct. However, the default SAPI effects applied using XML in the string are not sufficient. I need to calculate the DFT and extract some information to be able to apply my custom transformations.


    -Francisco Aguilera University of Washington Student | Prospective Computer Science Major | Microsoft Student Partner http://students.washington.edu/falven | http://www.facebook.com/falven

    Wednesday, March 13, 2013 4:05 PM
  • After SAPI writes the stream, the stream position is at the end, so IStream::Read will set its "read" output to zero bytes.

    Before reading from the stream, call IStream::Seek(zero, STREAM_SEEK_SET, NULL) and you will be able to read the data.


    Matthew van Eerde

    Wednesday, March 13, 2013 5:07 PM
  • Wednesday, March 13, 2013 6:00 PM
  • Worked great, thanks.
    And great job on the Blog entry.

    It is rather difficult to find information like this in bing/google for some reason.

    -Falven


    -Francisco Aguilera University of Washington Student | Prospective Computer Science Major | Microsoft Student Partner http://students.washington.edu/falven | http://www.facebook.com/falven

    Wednesday, March 13, 2013 10:53 PM