alter code to write to memory

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
How can I alter the given code to write this wav file to memory instead of to a file?

<pre class="prettyprint // extraction.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>
#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include <stdint.h>
#include <Mferror.h>

using namespace System;
using namespace System::IO;

/* prototypes */
HRESULT WriteWaveFile(IMFSourceReader *pReader, HANDLE hFile, LONG msecAudioData);
HRESULT FixUpChunkSizes(HANDLE, DWORD cbHeader, DWORD cbAudioData);
HRESULT WriteWaveData(HANDLE hFile, IMFSourceReader *pReader, DWORD cbMaxAudioData, DWORD *pcbDataWritten);
DWORD CalculateMaxAudioDataSize(IMFMediaType *pAudioType, DWORD cbHeader, DWORD msecAudioData);
HRESULT WriteToFile(HANDLE hFile, void* p, DWORD cb);
HRESULT WriteWaveHeader(HANDLE hFile, IMFMediaType *pMediaType, DWORD *pcbWritten);
HRESULT ConfigureAudioStream(IMFSourceReader *pReader, IMFMediaType **ppPCMAudio);
HRESULT WriteWaveFile(IMFSourceReader *pReader, HANDLE hFile, LONG msecAudioData);
template <class T> void SafeRelease(T **ppT);

/* pre processor */
#define SAMPLING_AUDIO 44100
#define CHANNEL_AUDIO 2



int _tmain(int argc, _TCHAR* argv[])//_TCHAR*
{


HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
/*if (argc != 3)
{
printf("arguments: input_file output_file.wavn");
return 1;
}*/




const WCHAR *wszSourceFile = argv[1];
const WCHAR *wszTargetFile = argv[2];

const LONG MAX_AUDIO_DURATION_MSEC = 10000; // 5 seconds

HRESULT hr = S_OK;

IMFSourceReader *pReader = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;

// Initialize the COM library.
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

// Initialize the Media Foundation platform.
if (SUCCEEDED(hr))
{
hr = MFStartup(MF_VERSION);
}

// Create the source reader to read the input file.
if (SUCCEEDED(hr))
{
hr = MFCreateSourceReaderFromURL(wszSourceFile, NULL, &pReader);
if (FAILED(hr))
{
printf("Error opening input file: %Sn", wszSourceFile, hr);
}
}

// Open the output file for writing.
if (SUCCEEDED(hr))
{
hFile = CreateFile(wszTargetFile, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, 0, NULL);

if (hFile == INVALID_HANDLE_VALUE)
{
hr = HRESULT_FROM_WIN32(GetLastError());
printf("Cannot create output file: %Sn", wszTargetFile, hr);
}
}

// Write the WAVE file.
if (SUCCEEDED(hr))
{
hr = WriteWaveFile(pReader, hFile, MAX_AUDIO_DURATION_MSEC);
}

if (FAILED(hr))
{
printf("Failed, hr = 0x%Xn", hr);
}

// Clean up.
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
}

SafeRelease(&pReader);
MFShutdown();
CoUninitialize();

return SUCCEEDED(hr) ? 0 : 1;

};


//-------------------------------------------------------------------
// WriteWaveFile
//
// Writes a WAVE file by getting audio data from the source reader.
//
//-------------------------------------------------------------------

HRESULT WriteWaveFile(
IMFSourceReader *pReader, // Pointer to the source reader.
HANDLE hFile, // Handle to the output file.
LONG msecAudioData // Maximum amount of audio data to write, in msec.
)
{
HRESULT hr = S_OK;

DWORD cbHeader = 0; // Size of the WAVE file header, in bytes.
DWORD cbAudioData = 0; // Total bytes of PCM audio data written to the file.
DWORD cbMaxAudioData = 0;

IMFMediaType *pAudioType = NULL; // Represents the PCM audio format.

// Configure the source reader to get uncompressed PCM audio from the source file.

hr = ConfigureAudioStream(pReader, &pAudioType);

// Write the WAVE file header.
if (SUCCEEDED(hr))
{
hr = WriteWaveHeader(hFile, pAudioType, &cbHeader);
}
// write the wave file header to byte array


// Calculate the maximum amount of audio to decode, in bytes.
if (SUCCEEDED(hr))
{
cbMaxAudioData = CalculateMaxAudioDataSize(pAudioType, cbHeader, msecAudioData);

// Decode audio data to the file.
hr = WriteWaveData(hFile, pReader, cbMaxAudioData, &cbAudioData);
}

// Fix up the RIFF headers with the correct sizes.
if (SUCCEEDED(hr))
{
hr = FixUpChunkSizes(hFile, cbHeader, cbAudioData);
}

SafeRelease(&pAudioType);
return hr;
}



//-------------------------------------------------------------------
// ConfigureAudioStream
//
// Selects an audio stream from the source file, and configures the
// stream to deliver decoded PCM audio.
//-------------------------------------------------------------------

HRESULT ConfigureAudioStream(
IMFSourceReader *pReader, // Pointer to the source reader.
IMFMediaType **ppPCMAudio // Receives the audio format.
)
{
IMFMediaType *pUncompressedAudioType = NULL;
IMFMediaType *pPartialType = NULL;

// Select the first audio stream, and deselect all other streams.
HRESULT hr = pReader->SetStreamSelection(
(DWORD)MF_SOURCE_READER_ALL_STREAMS, FALSE);

if (SUCCEEDED(hr))
{
hr = pReader->SetStreamSelection(
(DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, TRUE);
}

// Create a partial media type that specifies uncompressed PCM audio.
hr = MFCreateMediaType(&pPartialType);

if (SUCCEEDED(hr))
{
hr = pPartialType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
}

if (SUCCEEDED(hr))
{
hr = pPartialType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);
}

// Set this type on the source reader. The source reader will
// load the necessary decoder.
if (SUCCEEDED(hr))
{
hr = pReader->SetCurrentMediaType(
(DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
NULL, pPartialType);
}

// Get the complete uncompressed format.
if (SUCCEEDED(hr))
{
hr = pReader->GetCurrentMediaType(
(DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
&pUncompressedAudioType);
}

// Ensure the stream is selected.
if (SUCCEEDED(hr))
{
hr = pReader->SetStreamSelection(
(DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
TRUE);
}

// Return the PCM format to the caller.
if (SUCCEEDED(hr))
{
*ppPCMAudio = pUncompressedAudioType;
(*ppPCMAudio)->AddRef();
}

SafeRelease(&pUncompressedAudioType);
SafeRelease(&pPartialType);
return hr;
}


//-------------------------------------------------------------------
// WriteWaveHeader
//
// Write the WAVE file header.
//
// Note: This function writes placeholder values for the file size
// and data size, as these values will need to be filled in later.
//-------------------------------------------------------------------

HRESULT WriteWaveHeader(
HANDLE hFile, // Output file.
IMFMediaType *pMediaType, // PCM audio format.
DWORD *pcbWritten // Receives the size of the header.
)
{
HRESULT hr = S_OK;
UINT32 cbFormat = 0;

WAVEFORMATEX *pWav = NULL;

*pcbWritten = 0;

// Convert the PCM audio format into a WAVEFORMATEX structure.
hr = MFCreateWaveFormatExFromMFMediaType(pMediaType, &pWav, &cbFormat);

// Write the RIFF header and the start of the fmt chunk.
if (SUCCEEDED(hr))
{
DWORD header[] = {
// RIFF header
FCC(RIFF),
0,
FCC(WAVE),
// Start of fmt chunk
FCC(fmt ),
cbFormat
};

DWORD dataHeader[] = { FCC(data), 0 };

hr = WriteToFile(hFile, header, sizeof(header)); // first writes the header

// Write the WAVEFORMATEX structure.
if (SUCCEEDED(hr))
{
hr = WriteToFile(hFile, pWav, cbFormat); // 2. write the waveformat ex struct to file
}

// Write the start of the data chunk

if (SUCCEEDED(hr))
{
hr = WriteToFile(hFile, dataHeader, sizeof(dataHeader)); // 3. write the dataheader
}

if (SUCCEEDED(hr))
{
*pcbWritten = sizeof(header) + cbFormat + sizeof(dataHeader);
}
}


CoTaskMemFree(pWav);
return hr;
}


//-------------------------------------------------------------------
//
// Writes a block of data to a file
//
// hFile: Handle to the file.
// p: Pointer to the buffer to write.
// cb: Size of the buffer, in bytes.
//
//-------------------------------------------------------------------

HRESULT WriteToFile(HANDLE hFile, void* p, DWORD cb)
{
DWORD cbWritten = 0;
HRESULT hr = S_OK;

printf("p currently is %sn",p);
printf("cb currently is %sn", &cb);

// cb is number of bytes to write
// p is the buffer
// cb written is number of bytes written
// NULL value is overlapped bytes

BOOL bResult = WriteFile(hFile, p, cb, &cbWritten, NULL);
if (!bResult)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
return hr;
}




//-------------------------------------------------------------------
// CalculateMaxAudioDataSize
//
// Calculates how much audio to write to the WAVE file, given the
// audio format and the maximum duration of the WAVE file.
//-------------------------------------------------------------------

DWORD CalculateMaxAudioDataSize(
IMFMediaType *pAudioType, // The PCM audio format.
DWORD cbHeader, // The size of the WAVE file header.
DWORD msecAudioData // Maximum duration, in milliseconds.
)
{
UINT32 cbBlockSize = 0; // Audio frame size, in bytes.
UINT32 cbBytesPerSecond = 0; // Bytes per second.

// Get the audio block size and number of bytes/second from the audio format.

cbBlockSize = MFGetAttributeUINT32(pAudioType, MF_MT_AUDIO_BLOCK_ALIGNMENT, 0);
cbBytesPerSecond = MFGetAttributeUINT32(pAudioType, MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 0);

// Calculate the maximum amount of audio data to write.
// This value equals (duration in seconds x bytes/second), but cannot
// exceed the maximum size of the data chunk in the WAVE file.

// Size of the desired audio clip in bytes:
DWORD cbAudioClipSize = (DWORD)MulDiv(cbBytesPerSecond, msecAudioData, 1000);

// Largest possible size of the data chunk:
DWORD cbMaxSize = MAXDWORD - cbHeader;

// Maximum size altogether.
cbAudioClipSize = min(cbAudioClipSize, cbMaxSize);

// Round to the audio block size, so that we do not write a partial audio frame.
cbAudioClipSize = (cbAudioClipSize / cbBlockSize) * cbBlockSize;

return cbAudioClipSize;
}


//-------------------------------------------------------------------
// WriteWaveData
//
// Decodes PCM audio data from the source file and writes it to
// the WAVE file.
//-------------------------------------------------------------------

HRESULT WriteWaveData(
HANDLE hFile, // Output file.
IMFSourceReader *pReader, // Source reader.
DWORD cbMaxAudioData, // Maximum amount of audio data (bytes).
DWORD *pcbDataWritten // Receives the amount of data written.
)
{
HRESULT hr = S_OK;
DWORD cbAudioData = 0;
DWORD cbBuffer = 0;
BYTE *pAudioData = NULL;

IMFSample *pSample = NULL;
IMFMediaBuffer *pBuffer = NULL;

// Get audio samples from the source reader.
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 (FAILED(hr)) { break; }

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 samplen");
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);

if (FAILED(hr)) { break; }

// 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);
}

if (SUCCEEDED(hr))
{
printf("Wrote %d bytes of audio data.n", cbAudioData);

*pcbDataWritten = cbAudioData;
}

if (pAudioData)
{
pBuffer->Unlock();
}

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


//-------------------------------------------------------------------
// FixUpChunkSizes
//
// Writes the file-size information into the WAVE file header.
//
// WAVE files use the RIFF file format. Each RIFF chunk has a data
// size, and the RIFF header has a total file size.
//-------------------------------------------------------------------

HRESULT FixUpChunkSizes(
HANDLE hFile, // Output file.
DWORD cbHeader, // Size of the fmt chuck.
DWORD cbAudioData // Size of the data chunk.
)
{
HRESULT hr = S_OK;

LARGE_INTEGER ll;
ll.QuadPart = cbHeader - sizeof(DWORD);

if (0 == SetFilePointerEx(hFile, ll, NULL, FILE_BEGIN))
{
hr = HRESULT_FROM_WIN32(GetLastError());
}

// Write the data size.

if (SUCCEEDED(hr))
{
hr = WriteToFile(hFile, &cbAudioData, sizeof(cbAudioData));
}

if (SUCCEEDED(hr))
{
// Write the file size.
ll.QuadPart = sizeof(FOURCC);

if (0 == SetFilePointerEx(hFile, ll, NULL, FILE_BEGIN))
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}

if (SUCCEEDED(hr))
{
DWORD cbRiffFileSize = cbHeader + cbAudioData - 8;

// NOTE: The "size" field in the RIFF header does not include
// the first 8 bytes of the file. (That is, the size of the
// data that appears after the size field.)

hr = WriteToFile(hFile, &cbRiffFileSize, sizeof(cbRiffFileSize));
}

return hr;
}


template <class T> void SafeRelease(T **ppT)
{
if (*ppT)
{
(*ppT)->Release();
*ppT = NULL;
}
}[/code]
<br/>
Any help would be great!

View the full article
 
Back
Top