I am writing an app to capture sound from mic with Microsoft Media Foundation. Here is code
#include <stdio.h>
#include <assert.h>
#include <mfapi.h>
#include <mfidl.h>
#include <Mfreadwrite.h>
#include <Mferror.h>
template <class T> void SafeRelease(T **ppT)
{
if (*ppT)
{
(*ppT)->Release();
*ppT = NULL;
}
}
HRESULT ProcessSamples(IMFSourceReader *pReader, IMFSinkWriter *writer)
{
HRESULT hr = S_OK;
IMFSample *pSample = NULL;
size_t cSamples = 0;
bool quit = false;
while (!quit)
{
DWORD streamIndex, flags;
LONGLONG llTimeStamp;
hr = pReader->ReadSample(
MF_SOURCE_READER_ANY_STREAM, // Stream index.
0, // Flags.
&streamIndex, // Receives the actual stream index.
&flags, // Receives status flags.
&llTimeStamp, // Receives the time stamp.
&pSample // Receives the sample or NULL.
);
if (FAILED(hr))
{
break;
}
wprintf(L"Stream %d (%I64d)\n", streamIndex, llTimeStamp);
if (flags & MF_SOURCE_READERF_ENDOFSTREAM)
{
wprintf(L"\tEnd of stream\n");
quit = true;
}
if (flags & MF_SOURCE_READERF_NEWSTREAM)
{
wprintf(L"\tNew stream\n");
}
if (flags & MF_SOURCE_READERF_NATIVEMEDIATYPECHANGED)
{
wprintf(L"\tNative type changed\n");
}
if (flags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED)
{
wprintf(L"\tCurrent type changed\n");
}
if (flags & MF_SOURCE_READERF_STREAMTICK)
{
wprintf(L"\tStream tick\n");
}
if (pSample)
{
writer->WriteSample(streamIndex, pSample);
++cSamples;
if (cSamples > 300)quit = true;
}
SafeRelease(&pSample);
}
if (FAILED(hr))
{
wprintf(L"ProcessSamples FAILED, hr = 0x%x\n", hr);
}
else
{
wprintf(L"Processed %d samples\n", cSamples);
}
SafeRelease(&pSample);
return hr;
}
int _tmain(int argc, _TCHAR* argv[])
{
IMFMediaSource *source = 0;
IMFMediaSession* m_pSession;
IMFAttributes *pAttributes = NULL;
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
hr = MFStartup(MF_VERSION);
}
hr = MFCreateAttributes(&pAttributes, 2);
if (SUCCEEDED(hr))
{
hr = pAttributes->SetGUID(
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID
);
}
if (SUCCEEDED(hr))
{
hr = MFCreateDeviceSource(pAttributes, &source);
}
SafeRelease(&pAttributes);
hr = MFCreateAttributes(&pAttributes, 1);
IMFSourceReader *pReader;
hr = MFCreateSourceReaderFromMediaSource(source, NULL, &pReader);
IMFMediaType *type;
IMFSinkWriter *writer = 0;
hr = MFCreateSinkWriterFromURL(L"D:\\wma.wma", NULL, NULL, &writer);
IMFMediaType *inputType = 0;
hr = MFCreateMediaType(&inputType);
hr = inputType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);
hr = inputType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_Float);
hr = inputType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, 2);
hr = inputType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
hr = inputType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8);
hr =inputType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 352800);
hr = inputType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32);
hr = inputType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1);
hr = inputType->SetUINT32(MF_MT_AUDIO_CHANNEL_MASK, 3);
writer->SetInputMediaType(0, inputType, NULL);
DWORD streamNum = 0;
hr = writer->AddStream(inputType, &streamNum);
hr = writer->BeginWriting();
ProcessSamples(pReader,writer);
writer->Finalize();
return 0;
}
It works fine for capture sound from mic, but there is unwanted feature after calling pReader->ReadSample
- the sound volume in my headphones is lowered. I suppose that it is feature of media foundation for best capture quality, but I don't need it. Is there some way to disable this behavior? Thanks in advance!
First off, welcome to StackOverflow!
The behavior you are describing is called Automatic ducking or Stream Attenuation (new feature for Win7). It is intended for communication applications. Since your headset is a communication device, it is included and impacted by this behavior. In simplest terms, the volume of other devices are reduce during an incoming 'call'.
The easiest way to turn this off is by navigation to the last tab on the 'Sound' control panel (shown below) where you can change the volume options.
Otherwise, you can provide a custom ducking behavior shown here.
You can also disable the automatic ducking using code similar to that shown here, but remember you will be mixing WASAPI and Media Foundation, and will need to manage the sessions accordingly.
Hope this helps.