Question

I am trying to play mp3/wma using xaudio2. I managed to use the Media Foundation Source Reader object to do the decoding. My problem is, it is not playing the full audio; I could get only a part of the audio played.

What I am trying to do is, get the next sample from IMFSourceReader and submit this as the next buffer of sourcevoice. This is repeated util all the data is read from IMFSourceReader.

 while (true)
{
    DWORD dwFlags = 0;

    // Read the next sample.
    hr = pReader->ReadSample(
        (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
        0, NULL, &dwFlags, NULL, &pSample );


    if (dwFlags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED)
    {
        printf("Type change - not supported by WAVE file format.\n");
        break;
    }
    if (dwFlags & MF_SOURCE_READERF_ENDOFSTREAM)
    {
        printf("End of input file.\n");
        break;
    }

    if (pSample == NULL)
    {
        printf("No sample\n");
        continue;
    }

    // Get a pointer to the audio data in the sample.

    hr = pSample->ConvertToContiguousBuffer(&pBuffer);

    if (FAILED(hr)) { break; }


    hr = pBuffer->Lock(&pAudioData, NULL, &cbBuffer);

    if (FAILED(hr)) { break; }


    // Make sure not to exceed the specified maximum size.
    if (cbMaxAudioData - cbAudioData < cbBuffer)
    {
        cbBuffer = cbMaxAudioData - cbAudioData;
    }

    // Write this data to the output file.
    hr = WriteToFile(hFile, pAudioData, cbBuffer);

    int audioBufferLength = cbBuffer;


    if (FAILED(hr)) { break; }
    SubmitBuffer(pAudioData, audioBufferLength);
    // Unlock the buffer.
    hr = pBuffer->Unlock();



    pAudioData = NULL;

    if (FAILED(hr)) { break; }

    // Update running total of audio data.
    cbAudioData += cbBuffer;

    if (cbAudioData >= cbMaxAudioData)
    {
        break;
    }

    SafeRelease(&pSample);
    SafeRelease(&pBuffer);
}

void AudioDecoder::SubmitBuffer(byte *pAudioData, int audioBufferLength)
{

    byte * pAudioBuffer = new byte[audioBufferLength];
    CopyMemory(pAudioBuffer, pAudioData, audioBufferLength);
    if (pAudioBuffer != nullptr)
    {
     // Create an XAUDIO2_BUFFER for submitting audio data
     XAUDIO2_BUFFER buffer = {0};
     buffer.AudioBytes = audioBufferLength;
     buffer.pAudioData = pAudioBuffer;
     buffer.pContext = pAudioBuffer;
     HRESULT hresult = m_pSourceVoice->SubmitSourceBuffer(&buffer);
    }

}

After this I am calling m_pSourceVoice->Start(). This will start the audio, but not playing the full audio. Do I need to add anything else?

Was it helpful?

Solution

This loop doesn't look like it accounts for if any buffers have been completed before submitting more, so could be running into the limit of XAUDIO2_MAX_QUEUED_BUFFERS. Can you create a counter on your while loop to see how many buffers are submitted to the source voice?

If you've hit a limit you could start playback before fully decoding the file and submit additional buffers via source voice callbacks. http://msdn.microsoft.com/en-us/library/windows/desktop/ee415769(v=vs.85).aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top