Beispiel #1
0
static HRESULT
Test(int deviceId)
{
    HRESULT hr;
    WasapiWrap ww;

    HRR(ww.Init());
    HRG(ww.DoDeviceEnumeration());
    HRG(ww.ChooseDevice(deviceId));

    ww.PrintMixFormat();
    WWInspectArg inspectArg;

    inspectArg.Set(16, 16, 44100, 2);
    ww.Inspect(inspectArg);

    inspectArg.Set(16, 16, 48000, 2);
    ww.Inspect(inspectArg);

    inspectArg.Set(24, 24, 176400, 2);
    ww.Inspect(inspectArg);

    inspectArg.Set(32, 24, 176400, 2);
    ww.Inspect(inspectArg);

end:
    ww.Unsetup();
    ww.Term();
    return hr;
}
Beispiel #2
0
static WWBitsPerSampleType
InspectDeviceBitsPerSample(int deviceId)
{
    HRESULT hr;
    WWBitsPerSampleType deviceBitsPerSample = WWBpsNone;
    WasapiWrap ww;

    HRG(ww.Init());
    HRG(ww.DoDeviceEnumeration());
    HRG(ww.ChooseDevice(deviceId));

    WWInspectArg inspectArg;

    inspectArg.Set(32, 24, 176400, 2);
    if (SUCCEEDED(ww.Inspect(inspectArg))) {
        deviceBitsPerSample = WWBps32v24;
    }

    inspectArg.Set(24, 24, 176400, 2);
    if (SUCCEEDED(ww.Inspect(inspectArg))) {
        deviceBitsPerSample = WWBps24;
    }

end:
    ww.Unsetup();
    ww.Term();
    return deviceBitsPerSample;
}
static HRESULT
DeviceIdStringGet(IMMDeviceCollection *dc, UINT id, wchar_t *deviceIdStr, size_t deviceIdStrBytes)
{
    HRESULT hr = 0;

    IMMDevice *device  = nullptr;
    LPWSTR    s        = nullptr;

    assert(dc);
    assert(deviceIdStr);
    assert(0 < deviceIdStrBytes);

    deviceIdStr[0] = 0;

    HRG(dc->Item(id, &device));
    HRG(device->GetId(&s));

    wcsncpy_s(deviceIdStr, deviceIdStrBytes/2, s, deviceIdStrBytes/2 -1);

end:
    CoTaskMemFree(s);
    s = nullptr;
    SafeRelease(&device);
    return hr;
}
static HRESULT
DeviceNameGet(IMMDeviceCollection *dc, UINT id, wchar_t *name, size_t nameBytes)
{
    HRESULT hr = 0;

    IMMDevice *device  = nullptr;
    IPropertyStore *ps = nullptr;
    PROPVARIANT pv;

    assert(dc);
    assert(name);
    assert(0 < nameBytes);

    name[0] = 0;

    PropVariantInit(&pv);

    HRG(dc->Item(id, &device));
    HRG(device->OpenPropertyStore(STGM_READ, &ps));
    HRG(ps->GetValue(PKEY_Device_FriendlyName, &pv));

    wcsncpy_s(name, nameBytes/2, pv.pwszVal, nameBytes/2 -1);

end:
    PropVariantClear(&pv);
    SafeRelease(&ps);
    SafeRelease(&device);
    return hr;
}
Beispiel #5
0
HRESULT
WasapiWrap::DoDeviceEnumeration(void)
{
    HRESULT hr = 0;
    IMMDeviceEnumerator *deviceEnumerator = nullptr;

    m_deviceInfo.clear();

    HRR(CoCreateInstance(__uuidof(MMDeviceEnumerator),
        nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&deviceEnumerator)));

    HRR(deviceEnumerator->EnumAudioEndpoints(
        eRender, DEVICE_STATE_ACTIVE, &m_deviceCollection));

    UINT nDevices = 0;
    HRG(m_deviceCollection->GetCount(&nDevices));

    for (UINT i = 0; i<nDevices; ++i) {
        wchar_t name[WW_DEVICE_NAME_COUNT];
        HRG(DeviceNameGet(m_deviceCollection, i, name, sizeof name));
        m_deviceInfo.push_back(WWDeviceInfo(i, name));
    }

end:
    SafeRelease(&deviceEnumerator);
    return hr;
}
Beispiel #6
0
HRESULT
WWMFResampler::GetSampleDataFromMFTransform(WWMFSampleData *sampleData_return)
{
    HRESULT hr = S_OK;
    IMFMediaBuffer *pBuffer = NULL;
    MFT_OUTPUT_STREAM_INFO streamInfo;
    MFT_OUTPUT_DATA_BUFFER outputDataBuffer;
    DWORD dwStatus;
    memset(&streamInfo, 0, sizeof streamInfo);
    memset(&outputDataBuffer, 0, sizeof outputDataBuffer);

    assert(sampleData_return);
    assert(NULL == sampleData_return->data);

    HRG(MFCreateSample(&(outputDataBuffer.pSample)));
    HRG(MFCreateMemoryBuffer(sampleData_return->bytes, &pBuffer));
    HRG(outputDataBuffer.pSample->AddBuffer(pBuffer));
    outputDataBuffer.dwStreamID = 0;
    outputDataBuffer.dwStatus = 0;
    outputDataBuffer.pEvents = NULL;

    hr = m_pTransform->ProcessOutput(0, 1, &outputDataBuffer, &dwStatus);
    if (FAILED(hr)) {
        goto end;
    }

    HRG(ConvertMFSampleToWWSampleData(outputDataBuffer.pSample, sampleData_return));

end:
    SafeRelease(&pBuffer);
    SafeRelease(&outputDataBuffer.pSample);
    return hr;
}
Beispiel #7
0
void
WasapiWrap::PrintMixFormat(void)
{
    HRESULT hr = 0;
    WAVEFORMATEX *waveFormat = nullptr;

    assert(m_deviceToUse);
    assert(!m_audioClient);
    HRG(m_deviceToUse->Activate(
        __uuidof(IAudioClient), CLSCTX_INPROC_SERVER, nullptr, (void**)&m_audioClient));
    assert(m_audioClient);

    assert(!waveFormat);
    HRG(m_audioClient->GetMixFormat(&waveFormat));
    assert(waveFormat);

    WAVEFORMATEXTENSIBLE * wfext = (WAVEFORMATEXTENSIBLE*)waveFormat;

    printf("WASAPI shared mix format:\n");
    WaveFormatDebug(waveFormat);
    if (22 <= waveFormat->cbSize) {
        WFExtensibleDebug(wfext);
    }

end:
    if (waveFormat) {
        CoTaskMemFree(waveFormat);
        waveFormat = nullptr;
        wfext = nullptr;
    }
    SafeRelease(&m_audioClient);
}
Beispiel #8
0
HRESULT
WasapiWrap::Start(void)
{
    BYTE *pData = nullptr;
    HRESULT hr = 0;

    assert(m_pcmData);

    assert(!m_shutdownEvent);
    m_shutdownEvent = CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE);
    CHK(m_shutdownEvent);

    m_renderThread = CreateThread(nullptr, 0, RenderEntry, this, 0, nullptr);
    assert(m_renderThread);

    assert(m_renderClient);
    HRG(m_renderClient->GetBuffer(m_bufferFrameNum, &pData));

    memset(pData, 0, m_bufferFrameNum * m_frameBytes);

    HRG(m_renderClient->ReleaseBuffer(m_bufferFrameNum, 0));

    m_footerCount = 0;

    assert(m_audioClient);
    HRG(m_audioClient->Start());

end:
    return hr;
}
Beispiel #9
0
static HRESULT
Run(int deviceId, int latencyMillisec, WWPcmData &pcm)
{
    HRESULT hr;
    WasapiWrap ww;

    HRR(ww.Init());
    HRG(ww.DoDeviceEnumeration());
    HRG(ww.ChooseDevice(deviceId));

    WWSetupArg setupArg;
    setupArg.Set(pcm.bitsPerSample,pcm.validBitsPerSample, pcm.nSamplesPerSec, pcm.nChannels, latencyMillisec);
    HRG(ww.Setup(setupArg));
    ww.SetOutputData(pcm);
    ww.Start();

    while (!ww.Run(1000)) {
        printf("%d / %d\n", ww.GetPosFrame(), ww.GetTotalFrameNum());
    }
    hr = S_OK;

end:
    ww.Stop();
    ww.Unsetup();
    ww.Term();
    return hr;
}
static HRESULT
FixWavHeader(FILE *fpw, DWORD writeDataTotalBytes)
{
    HRESULT hr = E_FAIL;

    fseek(fpw, 4, SEEK_SET);
    HRG(WriteInt32(fpw, writeDataTotalBytes + 0x24));

    fseek(fpw, 0x28, SEEK_SET);
    HRG(WriteInt32(fpw, writeDataTotalBytes));

end:
    return hr;
}
Beispiel #11
0
HRESULT
WWMFResampler::Resample(const BYTE *buff, DWORD bytes, WWMFSampleData *sampleData_return)
{
    HRESULT hr = E_FAIL;
    IMFSample *pSample = NULL;
    WWMFSampleData tmpData;
    WWMFSampleData inputData((BYTE*)buff, bytes);
    DWORD dwStatus;
    DWORD cbOutputBytes = (DWORD)((int64_t)bytes * m_outputFormat.BytesPerSec() / m_inputFormat.BytesPerSec());
    // cbOutputBytes must be product of frambytes
    cbOutputBytes = (cbOutputBytes + (m_outputFormat.FrameBytes()-1)) / m_outputFormat.FrameBytes() * m_outputFormat.FrameBytes();
    // add extra receive size
    cbOutputBytes += 16 * m_outputFormat.FrameBytes();

    assert(sampleData_return);
    assert(NULL == sampleData_return->data);

    HRG(ConvertWWSampleDataToMFSample(inputData, &pSample));

    HRG(m_pTransform->GetInputStatus(0, &dwStatus));
    if ( MFT_INPUT_STATUS_ACCEPT_DATA != dwStatus) {
        dprintf("E: ApplyTransform() pTransform->GetInputStatus() not accept data.\n");
        hr = E_FAIL;
        goto end;
    }

    HRG(m_pTransform->ProcessInput(0, pSample, 0));

    // set sampleData_return->bytes = 0
    sampleData_return->Forget();
    for (;;) {
        tmpData.bytes = cbOutputBytes;
        hr = GetSampleDataFromMFTransform(&tmpData);
        if (MF_E_TRANSFORM_NEED_MORE_INPUT == hr) {
            hr = S_OK;
            goto end;
        }
        if (FAILED(hr)) {
            goto end;
        }
        sampleData_return->MoveAdd(tmpData);
        tmpData.Release();
    }

end:
    tmpData.Release();
    inputData.Forget();
    SafeRelease(&pSample);
    return hr;
}
Beispiel #12
0
static HRESULT
PrintDeviceList(void)
{
    HRESULT hr;
    WasapiWrap ww;

    HRR(ww.Init());
    HRG(ww.DoDeviceEnumeration());

    printf("Device list:\n");
    for (int i=0; i<ww.GetDeviceCount(); ++i) {
        wchar_t namew[WW_DEVICE_NAME_COUNT];
        ww.GetDeviceName(i, namew, sizeof namew);

        char    namec[WW_DEVICE_NAME_COUNT];
        memset(namec, 0, sizeof namec);
        WideCharToMultiByte(CP_ACP, 0, namew, -1, namec, sizeof namec-1, NULL, NULL);
        printf("    deviceId=%d: %s\n", i, namec);
    }
    printf("\n");

end:
    ww.Term();
    return hr;
}
Beispiel #13
0
DWORD
WasapiWrap::RenderMain(void)
{
    bool stillPlaying = true;
    HANDLE waitArray[2] = { m_shutdownEvent, m_audioSamplesReadyEvent };
    DWORD waitResult;
    HRESULT hr = 0;

    HRG(CoInitializeEx(nullptr, COINIT_MULTITHREADED));

    while (stillPlaying) {
        waitResult = WaitForMultipleObjects(2, waitArray, FALSE, INFINITE);
        switch (waitResult) {
        case WAIT_OBJECT_0 + 0:     // m_shutdownEvent
            stillPlaying = false;
            break;
        case WAIT_OBJECT_0 + 1:     // m_audioSamplesReadyEvent
            stillPlaying = AudioSamplesReadyProc();
            break;
        }
    }

end:
    CoUninitialize();
    return hr;
}
Beispiel #14
0
HRESULT
WWMFResampler::ConvertMFSampleToWWSampleData(IMFSample *pSample, WWMFSampleData *sampleData_return)
{
    HRESULT hr = E_FAIL;
#ifdef USE_ATL
    CComPtr<IMFMediaBuffer> spBuffer;
#else // USE_ATL
    IMFMediaBuffer *spBuffer = NULL;
#endif // USE_ATL
    BYTE  *pByteBuffer = NULL;
    assert(pSample);
    DWORD cbBytes = 0;

    assert(sampleData_return);
    assert(NULL == sampleData_return->data);

    HRG(pSample->ConvertToContiguousBuffer(&spBuffer));
    HRG(spBuffer->GetCurrentLength(&cbBytes));
    if (0 == cbBytes) {
        sampleData_return->bytes = 0;
        sampleData_return->data = NULL;
        hr = S_OK;
        goto end;
    }

    HRG(spBuffer->Lock(&pByteBuffer, NULL, NULL));

    assert(NULL == sampleData_return->data);
    sampleData_return->data = new BYTE[cbBytes];
    if (NULL == sampleData_return->data) {
        printf("no memory\n");
        goto end;
    }
    memcpy(sampleData_return->data, pByteBuffer, cbBytes);
    sampleData_return->bytes = cbBytes;

    m_outputFrameTotal += cbBytes / m_outputFormat.FrameBytes();

    pByteBuffer = NULL;
    HRG(spBuffer->Unlock());

end:
#ifndef USE_ATL
    SafeRelease(&spBuffer);
#endif // USE_ATL
    return hr;
}
Beispiel #15
0
static HRESULT
CreateResamplerMFT(
        const WWMFPcmFormat &fmtIn,
        const WWMFPcmFormat &fmtOut,
        int halfFilterLength,
        IMFTransform **ppTransform)
{
    HRESULT hr = S_OK;
#ifdef USE_ATL
    CComPtr<IMFMediaType> spInputType;
    CComPtr<IMFMediaType> spOutputType;
    CComPtr<IUnknown> spTransformUnk;
    CComPtr<IWMResamplerProps> spResamplerProps;
#else // USE_ATL
    IMFMediaType      *spInputType      = NULL;
    IMFMediaType      *spOutputType     = NULL;
    IUnknown          *spTransformUnk   = NULL;
    IWMResamplerProps *spResamplerProps = NULL;
#endif // USE_ATL
    IMFTransform *pTransform = NULL;
    assert(ppTransform);
    *ppTransform = NULL;

    HRG(CoCreateInstance(CLSID_CResamplerMediaObject, NULL, CLSCTX_INPROC_SERVER,
            IID_IUnknown, (void**)&spTransformUnk));

    HRG(spTransformUnk->QueryInterface(IID_PPV_ARGS(&pTransform)));

    HRG(CreateAudioMediaType(fmtIn, &spInputType));
    HRG(pTransform->SetInputType(0, spInputType, 0));

    HRG(CreateAudioMediaType(fmtOut, &spOutputType));
    HRG(pTransform->SetOutputType(0, spOutputType, 0));

    HRG(spTransformUnk->QueryInterface(IID_PPV_ARGS(&spResamplerProps)));
    HRG(spResamplerProps->SetHalfFilterLength(halfFilterLength));

    *ppTransform = pTransform;
    pTransform = NULL; //< prevent release

end:
    SafeRelease(&pTransform);

#ifndef USE_ATL
    SafeRelease(&spInputType);
    SafeRelease(&spOutputType);
    SafeRelease(&spTransformUnk);
    SafeRelease(&spResamplerProps);
#endif // USE_ATL

    return hr;
}
HRESULT
WWAudioDeviceEnumerator::BuildDeviceList(WWDeviceType t)
{
    HRESULT hr = 0;

    switch (t) {
    case WWDTPlay:
        m_dataFlow = eRender;
        break;
    case WWDTRec:
        m_dataFlow = eCapture;
        break;
    default:
        assert(0);
        return E_FAIL;
    }

    HRR(CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_deviceEnumerator)));

    if (m_deviceEnumerator) {
        for (auto it = m_notificationClientList.begin();
                it != m_notificationClientList.end(); ++it) {
            m_deviceEnumerator->RegisterEndpointNotificationCallback(*it);
        }
    }

    HRR(m_deviceEnumerator->EnumAudioEndpoints(m_dataFlow, DEVICE_STATE_ACTIVE, &m_deviceCollection));

    UINT nDevices = 0;
    HRG(m_deviceCollection->GetCount(&nDevices));

    for (UINT i=0; i<nDevices; ++i) {
        wchar_t name[WW_DEVICE_NAME_COUNT];
        wchar_t idStr[WW_DEVICE_IDSTR_COUNT];
        HRG(DeviceNameGet(m_deviceCollection, i, name, sizeof name));
        HRG(DeviceIdStringGet(m_deviceCollection, i, idStr, sizeof idStr));
        m_deviceInfo.push_back(WWDeviceInfo(i, name, idStr));
    }

end:
    return hr;
}
Beispiel #17
0
HRESULT
WWMFResampler::Initialize(const WWMFPcmFormat &inputFormat, const WWMFPcmFormat &outputFormat, int halfFilterLength)
{
    HRESULT hr = S_OK;
    m_inputFormat  = inputFormat;
    m_outputFormat = outputFormat;
    assert(m_pTransform == NULL);

    m_inputFrameTotal  = 0;
    m_outputFrameTotal = 0;

    HRG(MFStartup(MF_VERSION, MFSTARTUP_NOSOCKET));
    m_isMFStartuped = true;

    HRG(CreateResamplerMFT(m_inputFormat, m_outputFormat, halfFilterLength, &m_pTransform));

    HRG(m_pTransform->ProcessMessage(MFT_MESSAGE_COMMAND_FLUSH, NULL));
    HRG(m_pTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, NULL));
    HRG(m_pTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, NULL));

end:
    return hr;
}
Beispiel #18
0
HRESULT
WWMFResampler::Drain(DWORD resampleInputBytes, WWMFSampleData *sampleData_return)
{
    HRESULT hr = S_OK;
    WWMFSampleData tmpData;
    DWORD cbOutputBytes = (DWORD)((int64_t)resampleInputBytes * m_outputFormat.BytesPerSec() / m_inputFormat.BytesPerSec());
    // cbOutputBytes must be product of frambytes
    cbOutputBytes = (cbOutputBytes + (m_outputFormat.FrameBytes()-1)) / m_outputFormat.FrameBytes() * m_outputFormat.FrameBytes();

    assert(sampleData_return);
    assert(NULL == sampleData_return->data);

    HRG(m_pTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_END_OF_STREAM, NULL));
    HRG(m_pTransform->ProcessMessage(MFT_MESSAGE_COMMAND_DRAIN, NULL));

    // set sampleData_return->bytes = 0
    sampleData_return->Forget();
    for (;;) {
        tmpData.bytes = cbOutputBytes;
        hr = GetSampleDataFromMFTransform(&tmpData);
        if (MF_E_TRANSFORM_NEED_MORE_INPUT == hr) {
            // end
            HRG(m_pTransform->ProcessMessage(MFT_MESSAGE_NOTIFY_END_STREAMING, NULL));
            goto end;
        }
        if (FAILED(hr)) {
            goto end;
        }
        sampleData_return->MoveAdd(tmpData);
        tmpData.Release();
    }

end:
    tmpData.Release();
    return hr;
}
Beispiel #19
0
HRESULT
WWMFResampler::ConvertWWSampleDataToMFSample(WWMFSampleData &sampleData, IMFSample **ppSample)
{
    HRESULT hr = S_OK;
    IMFSample *pSample = NULL;
#ifdef USE_ATL
    CComPtr<IMFMediaBuffer> spBuffer;
#else // USE_ATL
    IMFMediaBuffer *spBuffer = NULL;
#endif // USE_ATL
    BYTE  *pByteBufferTo = NULL;
    //LONGLONG hnsSampleDuration;
    //LONGLONG hnsSampleTime;
    int frameCount;

    assert(ppSample);
    *ppSample = NULL;

    HRG(MFCreateMemoryBuffer(sampleData.bytes, &spBuffer));
    HRG(spBuffer->Lock(&pByteBufferTo, NULL, NULL));

    memcpy(pByteBufferTo, sampleData.data, sampleData.bytes);

    pByteBufferTo = NULL;
    HRG(spBuffer->Unlock());
    HRG(spBuffer->SetCurrentLength(sampleData.bytes));

    HRG(MFCreateSample(&pSample));
    HRG(pSample->AddBuffer(spBuffer));

    frameCount = sampleData.bytes / m_inputFormat.FrameBytes();
    /*
    hnsSampleDuration = (LONGLONG)(10.0 * 1000 * 1000 * frameCount        / m_inputFormat.sampleRate);
    hnsSampleTime     = (LONGLONG)(10.0 * 1000 * 1000 * m_inputFrameTotal / m_inputFormat.sampleRate);
    HRG(pSample->SetSampleDuration(hnsSampleDuration));
    HRG(pSample->SetSampleTime(hnsSampleTime));
    */

    m_inputFrameTotal += frameCount;

    // succeeded.

    *ppSample = pSample;
    pSample = NULL; //< prevent release

end:
    SafeRelease(&pSample);
#ifndef USE_ATL
    SafeRelease(&spBuffer);
#endif // uSE_ATL
    return hr;
}
Beispiel #20
0
HRESULT
WasapiWrap::ChooseDevice(int id)
{
    HRESULT hr = 0;

    if (id < 0) {
        goto end;
    }

    assert(m_deviceCollection);
    assert(!m_deviceToUse);

    HRG(m_deviceCollection->Item(id, &m_deviceToUse));

end:
    SafeRelease(&m_deviceCollection);
    return hr;
}
IMMDevice *
WWAudioDeviceEnumerator::GetDevice(int id)
{
    HRESULT   hr      = 0;
    IMMDevice *device = nullptr;

    if (id < 0 || (int)m_deviceInfo.size() <= id) {
        return nullptr;
    }

    if (!m_deviceCollection) {
        return nullptr;
    }

    HRG(m_deviceCollection->Item(id, &device));

end:
    return device;
}
Beispiel #22
0
HRESULT
WasapiWrap::Setup(const WWSetupArg & arg)
{
    HRESULT hr = 0;
    WAVEFORMATEX *waveFormat = nullptr;

    m_sampleRate = arg.nSamplesPerSec;
    m_bitsPerSample = arg.bitsPerSample;
    m_validBitsPerSample = arg.validBitsPerSample;

    m_audioSamplesReadyEvent =
        CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE);
    CHK(m_audioSamplesReadyEvent);

    assert(m_deviceToUse);
    assert(!m_audioClient);
    HRG(m_deviceToUse->Activate(
        __uuidof(IAudioClient), CLSCTX_INPROC_SERVER, nullptr, (void**)&m_audioClient));
    assert(m_audioClient);

    assert(!waveFormat);
    HRG(m_audioClient->GetMixFormat(&waveFormat));
    assert(waveFormat);

    WAVEFORMATEXTENSIBLE * wfex = (WAVEFORMATEXTENSIBLE*)waveFormat;

    printf("original Mix Format:\n");
    WaveFormatDebug(waveFormat);
    WFExtensibleDebug(wfex);

    if (waveFormat->wFormatTag != WAVE_FORMAT_EXTENSIBLE) {
        printf("E: unsupported device ! mixformat == 0x%08x\n", waveFormat->wFormatTag);
        hr = E_FAIL;
        goto end;
    }

    wfex->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
    wfex->Format.wBitsPerSample = m_bitsPerSample;
    wfex->Format.nSamplesPerSec = arg.nSamplesPerSec;

    wfex->Format.nBlockAlign = (m_bitsPerSample / 8) * waveFormat->nChannels;
    wfex->Format.nAvgBytesPerSec = wfex->Format.nSamplesPerSec*wfex->Format.nBlockAlign;
    wfex->Samples.wValidBitsPerSample = m_validBitsPerSample;

    printf("preferred Format:\n");
    WaveFormatDebug(waveFormat);
    WFExtensibleDebug(wfex);

    HRG(m_audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, waveFormat, nullptr));

    m_frameBytes = waveFormat->nBlockAlign;

    REFERENCE_TIME bufferDuration = arg.latencyInMillisec * 10000;

    hr = m_audioClient->Initialize(
        AUDCLNT_SHAREMODE_EXCLUSIVE,
        AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
        bufferDuration, bufferDuration, waveFormat, nullptr);
    if (hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED) {
        HRG(m_audioClient->GetBufferSize(&m_bufferFrameNum));

        SafeRelease(&m_audioClient);

        bufferDuration = (REFERENCE_TIME)(
            10000.0 *                         // (REFERENCE_TIME(100ns) / ms) *
            1000 *                            // (ms / s) *
            m_bufferFrameNum /                 // frames /
            waveFormat->nSamplesPerSec +     // (frames / s)
            0.5);

        HRG(m_deviceToUse->Activate(
            __uuidof(IAudioClient), CLSCTX_INPROC_SERVER, nullptr, (void**)&m_audioClient));

        hr = m_audioClient->Initialize(
            AUDCLNT_SHAREMODE_EXCLUSIVE,
            AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST | AUDCLNT_STREAMFLAGS_RATEADJUST,
            bufferDuration,
            bufferDuration,
            waveFormat,
            nullptr);
    }
    if (FAILED(hr)) {
        printf("E: audioClient->Initialize failed 0x%08x\n", hr);
        goto end;
    }

    HRG(m_audioClient->GetBufferSize(&m_bufferFrameNum));
    HRG(m_audioClient->SetEventHandle(m_audioSamplesReadyEvent));
    HRG(m_audioClient->GetService(IID_PPV_ARGS(&m_renderClient)));

end:
    if (waveFormat) {
        CoTaskMemFree(waveFormat);
        waveFormat = nullptr;
    }

    return hr;
}
Beispiel #23
0
int
WasapiWrap::Inspect(const WWInspectArg & arg)
{
    HRESULT hr = 0;
    WAVEFORMATEXTENSIBLE wfext;
    LPCWAVEFORMATEX pWfex = (LPCWAVEFORMATEX)&wfext;

    assert(m_deviceToUse);
    assert(!m_audioClient);
    HRG(m_deviceToUse->Activate(
        __uuidof(IAudioClient), CLSCTX_INPROC_SERVER, nullptr, (void**)&m_audioClient));
    assert(m_audioClient);

    hr = m_deviceToUse->Activate(__uuidof(IAudioClient2), CLSCTX_INPROC_SERVER, nullptr, (void**)&m_audioClient2);
    if (FAILED(hr)) {
        m_audioClient2 = nullptr;
    }

    ZeroMemory(&wfext, sizeof wfext);
    wfext.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
    wfext.Format.nChannels = arg.nChannels;
    wfext.Format.nSamplesPerSec = arg.nSamplesPerSec;
    wfext.Format.nBlockAlign = (arg.bitsPerSample / 8) * arg.nChannels;
    wfext.Format.nAvgBytesPerSec = arg.nSamplesPerSec * wfext.Format.nBlockAlign;
    wfext.Format.wBitsPerSample = arg.bitsPerSample;
    wfext.Format.cbSize = 22;

    wfext.Samples.wValidBitsPerSample = arg.validBitsPerSample;
    wfext.dwChannelMask = 3;
    wfext.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;

    printf("WAVEFORMATEXTENSIBLE KSFORMAT_SUBTYPE_PCM %dHz %dbit %dch: ",
        arg.nSamplesPerSec, arg.bitsPerSample, arg.nChannels);

    hr = m_audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, pWfex, nullptr);
    if (AUDCLNT_E_UNSUPPORTED_FORMAT == hr) {
        printf("not supported.\n");
        goto end;
    }
    if (FAILED(hr)) {
        printf("IAudioClient::IsFormatSupported failed: hr = 0x%08x.\n", hr);
        goto end;
    }

    printf("supported.\n");

    if (m_audioClient2 != nullptr) {
        for (int i = 0; i < AUDIO_STREAM_CATEGORY_NUM; ++i) {
            BOOL offloadCapable;
            HRG(m_audioClient2->IsOffloadCapable((AUDIO_STREAM_CATEGORY)i, &offloadCapable));
            printf("IsOffloadCapable(%22s)=%d\n", s_audioStreamCategoryStr[i], offloadCapable);
        }

        REFERENCE_TIME eventMinBufferDuration;
        REFERENCE_TIME eventMaxBufferDuration;
        REFERENCE_TIME timerMinBufferDuration;
        REFERENCE_TIME timerMaxBufferDuration;

        HRG(m_audioClient2->GetBufferSizeLimits(pWfex, true, &eventMinBufferDuration, &eventMaxBufferDuration));
        HRG(m_audioClient2->GetBufferSizeLimits(pWfex, false, &timerMinBufferDuration, &timerMaxBufferDuration));
        printf("Buffer size: eventMin=%lldms eventMax=%lldms timerMin=%lldms timerMax=%lldms\n",
            eventMinBufferDuration / 10000, eventMaxBufferDuration / 10000, timerMinBufferDuration / 10000, timerMaxBufferDuration / 10000);

    }

end:
    SafeRelease(&m_audioClient2);
    SafeRelease(&m_audioClient);
    return hr;
}
Beispiel #24
0
HRESULT
WWPlayPcmGroup::DoResample(WWPcmFormat &targetFmt, int conversionQuality)
{
    HRESULT hr = S_OK;
    WWMFResampler resampler;
    size_t n = m_playPcmDataList.size();
    const int PROCESS_FRAMES = 128 * 1024;
    BYTE *buff = new BYTE[PROCESS_FRAMES * m_pcmFormat.BytesPerFrame()];
    std::list<size_t> toPcmDataIdxList;
    size_t numConvertedPcmData = 0;
    assert(1 <= conversionQuality && conversionQuality <= 60);

    if (nullptr == buff) {
        hr = E_OUTOFMEMORY;
        goto end;
    }

    // 共有モードのサンプルレート変更。
    HRG(resampler.Initialize(
        WWMFPcmFormat(
            (WWMFBitFormatType)WWPcmDataSampleFormatTypeIsFloat(m_pcmFormat.sampleFormat),
            (WORD)m_pcmFormat.numChannels,
            (WORD)WWPcmDataSampleFormatTypeToBitsPerSample(m_pcmFormat.sampleFormat),
            m_pcmFormat.sampleRate,
            0, //< TODO: target dwChannelMask
            (WORD)WWPcmDataSampleFormatTypeToValidBitsPerSample(m_pcmFormat.sampleFormat)),
        WWMFPcmFormat(
            WWMFBitFormatFloat,
            (WORD)targetFmt.numChannels,
            32,
            targetFmt.sampleRate,
            0, //< TODO: target dwChannelMask
            32),
        conversionQuality));

    for (size_t i=0; i<n; ++i) {
        WWPcmData *pFrom = &m_playPcmDataList[i];
        WWPcmData pcmDataTo;

        if (!pcmDataTo.Init(pFrom->id, targetFmt.sampleFormat, targetFmt.numChannels,
                (int64_t)(((double)targetFmt.sampleRate / m_pcmFormat.sampleRate) * pFrom->nFrames),
                targetFmt.numChannels * WWPcmDataSampleFormatTypeToBitsPerSample(targetFmt.sampleFormat)/8, WWPcmDataContentMusicData, m_pcmFormat.streamType)) {
            dprintf("E: %s malloc failed. pcm id=%d\n", __FUNCTION__, pFrom->id);
            hr = E_OUTOFMEMORY;
            goto end;
        }
        m_playPcmDataList.push_back(pcmDataTo);
        pFrom = &m_playPcmDataList[i];

        toPcmDataIdxList.push_back(n+i);

        dprintf("D: pFrom stream=%p nFrames=%lld\n", pFrom->stream, pFrom->nFrames);

        for (size_t posFrames=0; ; posFrames += PROCESS_FRAMES) {
            WWMFSampleData mfSampleData;
            DWORD consumedBytes = 0;

            int buffBytes = pFrom->GetBufferData(posFrames * m_pcmFormat.BytesPerFrame(), PROCESS_FRAMES * m_pcmFormat.BytesPerFrame(), buff);
            dprintf("D: pFrom->GetBufferData posBytes=%Iu bytes=%d rv=%d\n",
                    posFrames * m_pcmFormat.BytesPerFrame(), PROCESS_FRAMES * m_pcmFormat.BytesPerFrame(), buffBytes);
            if (0 == buffBytes) {
                break;
            }

            HRG(resampler.Resample(buff, buffBytes, &mfSampleData));
            dprintf("D: resampler.Resample mfSampleData.bytes=%u\n",
                    mfSampleData.bytes);
            consumedBytes = 0;
            while (0 < toPcmDataIdxList.size() && consumedBytes < mfSampleData.bytes) {
                size_t toIdx = toPcmDataIdxList.front();
                WWPcmData *pTo = &m_playPcmDataList[toIdx];
                assert(pTo);
                int rv = pTo->FillBufferAddData(&mfSampleData.data[consumedBytes], mfSampleData.bytes - consumedBytes);
                dprintf("D: consumedBytes=%d/%d FillBufferAddData() pTo->stream=%p pTo->nFrames=%lld rv=%d\n",
                        consumedBytes, mfSampleData.bytes, pTo->stream, pTo->nFrames, rv);
                consumedBytes += rv;
                if (0 == rv) {
                    pTo->FillBufferEnd();
                    ++numConvertedPcmData;
                    toPcmDataIdxList.pop_front();
                }
            }
            mfSampleData.Release();
        }
        pFrom->Term();
    }

    {
        WWMFSampleData mfSampleData;
        DWORD consumedBytes = 0;

        HRG(resampler.Drain(PROCESS_FRAMES * m_pcmFormat.BytesPerFrame(), &mfSampleData));
        consumedBytes = 0;
        while (0 < toPcmDataIdxList.size() && consumedBytes < mfSampleData.bytes) {
            size_t toIdx = toPcmDataIdxList.front();
            WWPcmData *pTo = &m_playPcmDataList[toIdx];
            assert(pTo);
            int rv = pTo->FillBufferAddData(&mfSampleData.data[consumedBytes], mfSampleData.bytes - consumedBytes);
            consumedBytes += rv;
            if (0 == rv) {
                pTo->FillBufferEnd();
                ++numConvertedPcmData;
                toPcmDataIdxList.pop_front();
            }
        }
        mfSampleData.Release();
    }

    while (0 < toPcmDataIdxList.size()) {
        size_t toIdx = toPcmDataIdxList.front();
        WWPcmData *pTo = &m_playPcmDataList[toIdx];
        assert(pTo);

        pTo->FillBufferEnd();
        if (0 == pTo->nFrames) {
            hr = E_FAIL;
            goto end;
        }
        ++numConvertedPcmData;
        toPcmDataIdxList.pop_front();
    }

    assert(n == numConvertedPcmData);

    for (size_t i=0; i<n; ++i) {
        m_playPcmDataList[i] = m_playPcmDataList[n+i];
        m_playPcmDataList[n+i].Forget();
    }

    m_playPcmDataList.resize(numConvertedPcmData);

    // update pcm format info
    m_pcmFormat.sampleFormat  = targetFmt.sampleFormat;
    m_pcmFormat.sampleRate    = targetFmt.sampleRate;
    m_pcmFormat.numChannels   = targetFmt.numChannels;
    m_pcmFormat.dwChannelMask = targetFmt.dwChannelMask;

    // reduce volume level when out of range sample value is found
    {
        float maxV = 0.0f;
        float minV = 0.0f;
        const float  SAMPLE_VALUE_MAX_FLOAT  =  1.0f;
        const float  SAMPLE_VALUE_MIN_FLOAT  = -1.0f;

        for (size_t i=0; i<n; ++i) {
            float currentMax = 0.0f;
            float currentMin = 0.0f;
            m_playPcmDataList[i].FindSampleValueMinMax(&currentMin, &currentMax);
            if (currentMin < minV) {
                minV = currentMin;
            }
            if (maxV < currentMax) {
                maxV = currentMax;
            }
        }

        float scale = 1.0f;
        if (SAMPLE_VALUE_MAX_FLOAT < maxV) {
            scale = SAMPLE_VALUE_MAX_FLOAT / maxV;
        }
        if (minV < SAMPLE_VALUE_MIN_FLOAT && SAMPLE_VALUE_MIN_FLOAT / minV < scale) {
            scale = SAMPLE_VALUE_MIN_FLOAT / minV;
        }
        if (scale < 1.0f) {
            for (size_t i=0; i<n; ++i) {
                m_playPcmDataList[i].ScaleSampleValue(scale);
            }
        }
    }

end:
    resampler.Finalize();
    delete [] buff;
    buff = nullptr;
    return hr;
}
Beispiel #25
0
int
main(int argc, char *argv[])
{
    HRESULT hr;

    if (argc != 2) {
        printf("Usage: %s readWavFile\n", argv[0]);
        return 1;
    }

    FILE *fpr = fopen(argv[1], "rb");
    if (NULL == fpr) {
        printf("read error %s\n", argv[1]);
        return 1;
    }

    WWMFPcmFormat fmt;
    DWORD remainBytes = 0;
    unsigned char *pUC = NULL;
    unsigned short *pUS = NULL;
    int readBytes = 0;
    int prevValue = INT_MAX;
    int prevPosition = INT_MAX;
    int *histogram16 = NULL;
    int *histogram24 = NULL;

    HRG(ReadWavHeader(fpr, &fmt, &remainBytes));
    pUC = new unsigned char[remainBytes];
    pUS = (unsigned short *)pUC;

    readBytes = fread(pUC, 1, remainBytes, fpr);
    if (readBytes != remainBytes) {
        printf("read error\n");
        hr = E_FAIL;
        goto end;
    }
    int totalSamples = readBytes/(fmt.bits/8);

    switch (fmt.bits) {
    case 16:
        histogram16 = new int[65536];
        memset(histogram16, 0, 65536*4);
        for (int i=0; i<remainBytes/2; ++i) {
            ++histogram16[pUS[i]];
        }
        prevPosition = 32767;
        for (int i=32768; i<65536; ++i) {
            if (prevValue == histogram16[i]) {
                continue;
            }
            if (prevPosition != i-1) {
                printf("%d %d %f\n", i-1-65536, prevValue, (double)prevValue / totalSamples);
            }
            prevValue = histogram16[i];
            prevPosition = i;
            printf("%d %d %f\n", i-65536, histogram16[i], (double)histogram16[i] / totalSamples);
        }
        prevPosition -= 65536;
        for (int i=0; i<32768; ++i) {
            if (prevValue == histogram16[i]) {
                continue;
            }
            if (prevPosition != i-1) {
                printf("%d %d %f\n", i-1, prevValue, (double)prevValue / totalSamples);
            }
            prevValue = histogram16[i];
            prevPosition = i;
            printf("%d %d %f\n", i, histogram16[i], (double)histogram16[i] / totalSamples);
        }
        break;
    case 24:
        histogram24 = new int[16777216];
        memset(histogram24, 0, 16777216*4);
        for (int i=0; i<remainBytes/3; ++i) {
            unsigned int v = pUC[i*3] + 256*pUC[i*3+1] + 65536*pUC[i*3+2];
            ++histogram24[v];
        }
        prevPosition = 8388607;
        for (int i=8388608; i<16777216; ++i) {
            if (abs(prevValue - histogram24[i]) < 1) {
                continue;
            }
            if (prevPosition != i-1) {
                printf("%12d %12d %f\n", i-1-16777216, prevValue, (double)prevValue / totalSamples);
            }
            prevValue = histogram24[i];
            prevPosition = i;
            printf("%12d %12d %f\n", i-16777216, histogram24[i], (double)histogram24[i] / totalSamples);
        }
        for (int i=0; i<8388608; ++i) {
            if (abs(prevValue - histogram24[i]) < 1) {
                continue;
            }
            if (prevPosition != i-1) {
                printf("%12d %12d %f\n", i-1, prevValue, (double)prevValue / totalSamples);
            }
            prevValue = histogram24[i];
            prevPosition = i;
            printf("%12d %12d %f\n", i, histogram24[i], (double)histogram24[i] / totalSamples);
        }
        break;
    default:
        printf("fmt.bits is not 16 nor 24\n");
        break;
    }

end:
    fclose(fpr);
    fpr = NULL;

    delete [] histogram16;
    histogram16 = NULL;

    delete [] histogram24;
    histogram24 = NULL;

    delete [] pUC;
    pUC = NULL;

    pUS = NULL;

    return hr == S_OK ? 0 : 1;
}
int wmain(int argc, wchar_t *argv[])
{
    // _CrtSetBreakAlloc(35);
    // COM leak cannot be detected by debug heap manager ...
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

    HRESULT hr = S_OK;
    bool bCoInitialize = false;
    FILE *fpr = NULL;
    FILE *fpw = NULL;
    errno_t ercd;
    BYTE *buff = NULL;
    DWORD buffBytes = 0;
    DWORD readBytes = 0;
    DWORD remainBytes = 0;
    DWORD expectedOutputDataBytes = 0;
    DWORD result = 0;
    DWORD writeDataTotalBytes = 0;
    int conversionQuality = 60;
    WWMFResampler resampler;
    WWMFPcmFormat inputFormat;
    WWMFPcmFormat outputFormat;
    WWMFSampleData sampleData;

    if (argc != 6) {
        PrintUsage(argv[0]);
        return 1;
    }

    HRG(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));
    bCoInitialize = true;

    ercd = _wfopen_s(&fpr, argv[1], L"rb");
    if (0 != ercd) {
        printf("file open error %S\n", argv[1]);
        PrintUsage(argv[0]);
        hr = E_FAIL;
        goto end;
    }

    ercd = _wfopen_s(&fpw, argv[2], L"wb");
    if (0 != ercd) {
        printf("file open error %S\n", argv[2]);
        PrintUsage(argv[0]);
        hr = E_FAIL;
        goto end;
    }

    HRG(ReadWavHeader(fpr, &inputFormat, &remainBytes));

    outputFormat = inputFormat;
    outputFormat.sampleRate = _wtoi(argv[3]);
    outputFormat.bits = (short)_wtoi(argv[4]);

    conversionQuality = _wtoi(argv[5]);

    if (0 == outputFormat.sampleRate ||
        0 == conversionQuality) {
        PrintUsage(argv[0]);
        hr = E_FAIL;
        goto end;
    }

    outputFormat.validBitsPerSample = outputFormat.bits;

    switch (outputFormat.bits) {
    case 16:
    case 24:
        outputFormat.sampleFormat = WWMFBitFormatInt;
        break;
    case 32:
        outputFormat.sampleFormat = WWMFBitFormatFloat;
        break;
    default:
        PrintUsage(argv[0]);
        hr = E_FAIL;
        goto end;
    }

    expectedOutputDataBytes = (int64_t)remainBytes
        * outputFormat.BytesPerSec()
        / inputFormat .BytesPerSec();

    HRG(WriteWavHeader(fpw, outputFormat, expectedOutputDataBytes));

    HRG(resampler.Initialize(inputFormat, outputFormat, conversionQuality));

    buffBytes = 128 * 1024 * inputFormat.FrameBytes();
    buff = new BYTE[buffBytes];

    for (;;) {
        // read PCM data from file
        readBytes = buffBytes;
        if (remainBytes < readBytes) {
            readBytes = remainBytes;
        }
        remainBytes -= readBytes;

        result = fread(buff, 1, readBytes, fpr);
        if (result != readBytes) {
            printf("file read error\n");
            hr = E_FAIL;
            goto end;
        }

        // convert
        HRG(resampler.Resample(buff, readBytes, &sampleData));

        // write to file
        result = fwrite(sampleData.data, 1, sampleData.bytes, fpw);
        if (result != sampleData.bytes) {
            printf("file write error\n");
            hr = E_FAIL;
            goto end;
        }
        writeDataTotalBytes += sampleData.bytes;
        sampleData.Release();

        if (remainBytes == 0) {
            // end
            HRG(resampler.Drain(buffBytes, &sampleData));

            // write remaining PCM data to file
            result = fwrite(sampleData.data, 1, sampleData.bytes, fpw);
            if (result != sampleData.bytes) {
                printf("file write error\n");
                hr = E_FAIL;
                goto end;
            }
            writeDataTotalBytes += sampleData.bytes;
            sampleData.Release();
            break;
        }
    }

    // data chunk align is 2 bytes
    if (writeDataTotalBytes & 1) {
        if (0 != fputc(0, fpw)) {
            printf("file write error\n");
            hr = E_FAIL;
            goto end;
        }
        ++writeDataTotalBytes;
    }
    HRG(FixWavHeader(fpw, writeDataTotalBytes));

    hr = S_OK;

end:
    resampler.Finalize();

    if (bCoInitialize) {
        CoUninitialize();
        bCoInitialize = false;
    }

    delete[] buff;
    buff = NULL;

    if (fpw != NULL) {
        fclose(fpw);
        fpw = NULL;
    }
    if (fpr != NULL) {
        fclose(fpr);
        fpr = NULL;
    }

    return SUCCEEDED(hr) ? 0 : 1;
}
static HRESULT
WriteWavHeader(FILE *fpw, WWMFPcmFormat &format, DWORD dataBytes)
{
    HRESULT hr = E_FAIL;
    int dataChunkSize = ((dataBytes+1)&(~1)) + 4;

    HRG(WriteBytes(fpw, "RIFF", 4U));
    HRG(WriteInt32(fpw, dataChunkSize + 0x24));
    HRG(WriteBytes(fpw, "WAVE", 4U));

    HRG(WriteBytes(fpw, "fmt ", 4U));
    HRG(WriteInt32(fpw, 16));

    // fmt audioFormat size==2 1==int 3==float
    switch (format.sampleFormat) {
    case WWMFBitFormatInt:
        HRG(WriteInt16(fpw, 1));
        break;
    case WWMFBitFormatFloat:
        HRG(WriteInt16(fpw, 3));
        break;
    default:
        goto end;
    }

    // fmt numChannels size==2
    HRG(WriteInt16(fpw, format.nChannels));

    // fmt sampleRate size==4
    HRG(WriteInt32(fpw, format.sampleRate));

    // fmt byteRate size==4
    HRG(WriteInt32(fpw, format.BytesPerSec()));

    // fmt blockAlign size==2
    HRG(WriteInt16(fpw, format.FrameBytes()));

    // fmt bitspersample size==2
    HRG(WriteInt16(fpw, format.bits));

    HRG(WriteBytes(fpw, "data", 4U));
    HRG(WriteInt32(fpw, dataChunkSize));

end:
    return hr;
}
static HRESULT
ReadWavHeader(FILE *fpr, WWMFPcmFormat *format_return, DWORD *dataBytes_return)
{
    HRESULT hr = E_FAIL;
    BYTE buff[16];
    int chunkBytes = 0;
    int fmtChunkSize = 0;
    short shortValue;
    int intValue;

    HRG(ReadBytes(fpr, 12U, buff));

    if (0 != memcmp(buff, "RIFF", 4)) {
        printf("file is not riff wave file\n");
        goto end;
    }
    if (0 != memcmp(&buff[8], "WAVE", 4)) {
        printf("file is not riff wave file\n");
        goto end;
    }

    for (;;) {
        HRG(ReadBytes(fpr, 4U, buff));

        if (0 == memcmp(buff, "fmt ", 4)) {
            // fmt chunk

            // chunkSize size==4
            HRG(ReadInt32(fpr, &fmtChunkSize));
            if (16 != fmtChunkSize && 18 != fmtChunkSize && 40 != fmtChunkSize) {
                printf("unrecognized format");
                goto end;
            }
            // audioFormat size==2
            HRG(ReadInt16(fpr, &shortValue));
            if (1 == shortValue) {
                format_return->sampleFormat = WWMFBitFormatInt;
            } else if (3 == shortValue) {
                format_return->sampleFormat = WWMFBitFormatFloat;
            } else if (0xfffe == (unsigned short)shortValue) {
                // SampleFormat is written on WAVEFORMATEXTENSIBLE
                format_return->sampleFormat = WWMFBitFormatUnknown;
            } else {
                printf("unrecognized format");
                goto end;
            }

            // numChannels size==2
            HRG(ReadInt16(fpr, &shortValue));
            format_return->nChannels = shortValue;

            // sampleRate size==4
            HRG(ReadInt32(fpr, &intValue));
            format_return->sampleRate = intValue;

            // byteRate size==4
            HRG(ReadInt32(fpr, &intValue));

            // blockAlign size==2
            HRG(ReadInt16(fpr, &shortValue));

            // bitspersample size==2
            HRG(ReadInt16(fpr, &shortValue));
            format_return->bits = shortValue;
            format_return->validBitsPerSample = shortValue;

            if (16 < fmtChunkSize) {
                // subchunksize
                HRG(ReadInt16(fpr, &shortValue));
                if (0 == shortValue) {
                    hr = S_OK;
                    goto end;
                } else if (22 == shortValue) {
                    // validbitspersample
                    HRG(ReadInt16(fpr, &shortValue));
                    format_return->validBitsPerSample = shortValue;

                    // dwChannelMask
                    HRG(ReadInt32(fpr, (int*)&format_return->dwChannelMask));

                    // format GUID
                    HRG(ReadBytes(fpr, 16U, buff));
                    if (0 == memcmp(buff, &MFAudioFormat_Float, 16)) {
                        format_return->sampleFormat = WWMFBitFormatFloat;
                    } else if (0 == memcmp(buff, &MFAudioFormat_PCM, 16)) {
                        format_return->sampleFormat = WWMFBitFormatInt;
                    } else {
                        printf("unrecognized format guid");
                        goto end;
                    }
                } else {
                    printf("unrecognized format");
                    goto end;
                }
            }

        } else if (0 == memcmp(buff, "data", 4)) {
            // data chunk
            HRG(ReadInt32(fpr, (int*)dataBytes_return));
            break;
        } else {
            // skip this chunk
            HRG(ReadInt32(fpr, &chunkBytes));
            if (chunkBytes < 4) {
                printf("E: chunk bytes == %d\n", chunkBytes);
                goto end;
            }
            fseek(fpr, chunkBytes, SEEK_CUR);
        }

    }
end:
    if (S_OK == hr && format_return->sampleFormat == WWMFBitFormatUnknown) {
        printf("unrecognized format");
        hr = E_FAIL;
    }

    return hr;
}
Beispiel #29
0
static HRESULT
CreateAudioMediaType(const WWMFPcmFormat &fmt, IMFMediaType** ppMediaType)
{
    HRESULT hr;
    IMFMediaType *pMediaType = NULL;
    *ppMediaType = NULL;

    HRG(MFCreateMediaType(&pMediaType) );
    HRG(pMediaType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio));
    HRG(pMediaType->SetGUID(MF_MT_SUBTYPE,
            (fmt.sampleFormat == WWMFBitFormatInt) ? MFAudioFormat_PCM : MFAudioFormat_Float));
    HRG(pMediaType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS,         fmt.nChannels));
    HRG(pMediaType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND,   fmt.sampleRate));
    HRG(pMediaType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT,      fmt.FrameBytes()));
    HRG(pMediaType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, fmt.BytesPerSec()));
    HRG(pMediaType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE,      fmt.bits));
    HRG(pMediaType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT,    TRUE));
    if (0 != fmt.dwChannelMask) {
        HRG(pMediaType->SetUINT32(MF_MT_AUDIO_CHANNEL_MASK, fmt.dwChannelMask));
    }
    if (fmt.bits != fmt.validBitsPerSample) {
        HRG(pMediaType->SetUINT32(MF_MT_AUDIO_VALID_BITS_PER_SAMPLE, fmt.validBitsPerSample));
    }

    *ppMediaType = pMediaType;
    pMediaType = NULL; //< prevent release

end:
    SafeRelease(&pMediaType);
    return hr;
}