TomP
TomP

Reputation: 67

Getting bytes from GraphFilter SampleGrabber to Audio raw data WinApi

I am having a big issue getting raw audio data from the SampleGrabber GraphFilter and writing it to an audio file in the proper format.

What i'm trying to achieve is:

  1. grabbing the data from: Microphone->SampleGrabber->Null Rendrer
  2. Write the raw data captured to a proper audio file (MP3\AVI\WAVE)

Some questions:

  1. Am I setting the proper MediaType for the SampleGrabber?
  2. How can you compress the audio data to a proper audio file?

My current code below:


struct sRecortdingData {
    std::vector<BYTE> recordingData;
    double totalRecordingTime;
};

class CFakeCallback : public ISampleGrabberCB
{
        public:
            sRecortdingData sRecording;
            STDMETHODIMP_(ULONG) AddRef() { return 2; }
            STDMETHODIMP_(ULONG) Release() { return 1; }

            STDMETHODIMP_(HRESULT __stdcall) QueryInterface(REFIID riid, void** ppv)
            {
                if (riid == IID_ISampleGrabberCB || riid == IID_IUnknown)
                {
                    *ppv = (void*) static_cast<ISampleGrabberCB*>(this);
                    return NOERROR;
                }
                return E_NOINTERFACE;
            }

            STDMETHODIMP_(HRESULT __stdcall) SampleCB(double SampleTime, IMediaSample* pSample)
            {
                return S_OK;
            }

            STDMETHODIMP_(HRESULT __stdcall) BufferCB(double SampleTime, BYTE* pBuffer, long BufferLen)
            {
                sRecording.recordingData.push_back(*pBuffer);
                sRecording.totalRecordingTime = SampleTime;
                return S_OK;
            }
};


void Microphone::RecordAudio()
{
    
    HRESULT hr;
    AM_MEDIA_TYPE mt;
    
    long recordingEventCode;
    IMediaControl* pMediaControl = NULL;
    ISampleGrabber* pISampleGrabber = NULL;
    IBaseFilter* pSampleGrabberFilter;
    IGraphBuilder* pGraphBuilder = NULL;
    IMediaEventEx* pEvent = NULL;
    IBaseFilter* pMicrophoneFilter = NULL;
    ISampleGrabber* pSampleGrabber = NULL;
    ICreateDevEnum* pDeviceEnum = NULL;
    IBaseFilter* pNullRender = NULL;

    hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    if (FAILED(hr))
    {
        HR_Failed(hr);
       return;
    }

    // Filter graph
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGraphBuilder));
    if (FAILED(hr))
    {
        HR_Failed(hr);
        return;
    }

    // Device enum
    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDeviceEnum));
    if (FAILED(hr))
    {
        HR_Failed(hr);
        return;
    }
    // Null renderer
    hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pNullRender));
    if (FAILED(hr))
    {
        HR_Failed(hr);
        return;
    }

    // Get the even control
    hr = pGraphBuilder->QueryInterface(IID_PPV_ARGS(&pEvent));
    if (FAILED(hr))
    {
        HR_Failed(hr);
        return;
    }

    // Sample Grabber
    hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pSampleGrabberFilter));
    if (FAILED(hr))
    {
        HR_Failed(hr);
        return;
    }

    // Get Media Control
    hr = pGraphBuilder->QueryInterface(IID_PPV_ARGS(&pMediaControl));
    if (FAILED(hr))
    {
        HR_Failed(hr);
        return;
    }

    // Setup input device filter
    pMicrophoneFilter = Microphone::SetupDeviceFilter(CLSID_AudioInputDeviceCategory, pGraphBuilder, pDeviceEnum,
        Utils::s2ws("My Microphone");
    if (pMicrophoneFilter == NULL) {
        HR_Failed(hr);
        return;
    }
    // Setup sample grabber filter
    pSampleGrabberFilter = Microphone::SetupDeviceFilter(CLSID_LegacyAmFilterCategory, 
        pGraphBuilder, pDeviceEnum, L"SampleGrabber");
    if (pSampleGrabberFilter == NULL) {
        HR_Failed(hr);
        return;
    }
    // Connect both pins together
    Device_Connect(pMicrophoneFilter, pSampleGrabberFilter);

    // Setup null renderer filter
    pNullRender = Microphone::SetupDeviceFilter(CLSID_LegacyAmFilterCategory, 
        pGraphBuilder, pDeviceEnum, L"Null Renderer");
    if (pNullRender == NULL) {
        HR_Failed(hr);
        return;
    }
    // Connect both pins together
    Device_Connect(pSampleGrabberFilter, pNullRender);


    // Get the ISampleGranner interface
    hr = pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber, (LPVOID*)&pISampleGrabber);
    if (FAILED(hr))
    {
        HR_Failed(hr);
        return;
    }
   
    hr = pISampleGrabber->SetCallback(&CB, 1);
    
    ZeroMemory(&mt, sizeof(mt));
    mt.majortype = MEDIATYPE_Audio;
    mt.subtype = MEDIASUBTYPE_PCM;
    // Set the media type
    hr = pISampleGrabber->SetMediaType(&mt);
    if (FAILED(hr))
    {
        HR_Failed(hr);
        return;
    }
    pISampleGrabber->SetBufferSamples(FALSE);
    if (FAILED(hr))
    {
        HR_Failed(hr);
        return;
    }
    hr = pMediaControl->Run();
    if (FAILED(hr))
    {
        HR_Failed(hr);
        return;
    }
    DWORD recordingTime = 20000;
    hr = pEvent->WaitForCompletion(recordingTime, &recordingEventCode);
    std::string str(CB.sRecording.recordingData.begin(), CB.sRecording.recordingData.end());

    // Do something with the data from callback and write it to audio file 
}

Upvotes: 0

Views: 109

Answers (0)

Related Questions