C++ 如何使用微软媒体库的Sink编写音频播放 我试图用微软媒体基金会创建一个音频可视化工具。为此,我需要截取样本并同时播放它们。使用具有拓扑结构和示例抓取器接收器的媒体会话似乎不切实际且过于复杂,因此我尝试使用接收器读取器和接收器写入器的组合来实现这一点(请参见上的右半部分图像)。不幸的是,它并没有真正解释如何做到这一点。开发微软MediaFoundation应用程序的书包含第92页的源到汇循环,但这仍然没有真正帮助我。

C++ 如何使用微软媒体库的Sink编写音频播放 我试图用微软媒体基金会创建一个音频可视化工具。为此,我需要截取样本并同时播放它们。使用具有拓扑结构和示例抓取器接收器的媒体会话似乎不切实际且过于复杂,因此我尝试使用接收器读取器和接收器写入器的组合来实现这一点(请参见上的右半部分图像)。不幸的是,它并没有真正解释如何做到这一点。开发微软MediaFoundation应用程序的书包含第92页的源到汇循环,但这仍然没有真正帮助我。,c++,audio,com,playback,ms-media-foundation,C++,Audio,Com,Playback,Ms Media Foundation,创建源阅读器工作得很好,我正在读取非零样本。将它们写入Sink Writer(使用流音频渲染器)不会给我任何错误,但我没有听到任何声音。我尝试了多种方法,如选择其他媒体类型和显式选择渲染设备(尽管我只有一个,如图所示),但都没有效果。不过请注意,使用媒体会话播放音频效果很好 我的代码基于以下问题: 这是我此刻的代码: #include <iostream> #include <cassert> #include <mfidl.h> #include <

创建源阅读器工作得很好,我正在读取非零样本。将它们写入Sink Writer(使用流音频渲染器)不会给我任何错误,但我没有听到任何声音。我尝试了多种方法,如选择其他媒体类型和显式选择渲染设备(尽管我只有一个,如图所示),但都没有效果。不过请注意,使用媒体会话播放音频效果很好

我的代码基于以下问题:

这是我此刻的代码:

#include <iostream>

#include <cassert>

#include <mfidl.h>
#include <mfapi.h>
#include <mfreadwrite.h>
#include <Mferror.h>
#pragma comment(lib, "mf")
#pragma comment(lib, "mfplat")
#pragma comment(lib, "mfreadwrite")

#include <winrt/base.h>
#pragma comment(lib, "windowsapp")

void winHr(const HRESULT result) { winrt::check_hresult(result); }

template<class T>
struct ComPtr : winrt::com_ptr<T>
{
    auto operator&() noexcept { return this->put(); }

    operator T*() noexcept
    {
        assert(this->get());
        return this->get();
    }
};

int main() noexcept
{
    winHr(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));
    winHr(MFStartup(MF_VERSION));

    {
        ComPtr<IMFSourceReader> reader;
        winHr(MFCreateSourceReaderFromURL(
            LR"(test.wav)",
            nullptr, &reader));

        constexpr auto inStreamIndex = MF_SOURCE_READER_FIRST_AUDIO_STREAM;

        // Select only the audio stream
        winHr(reader->SetStreamSelection(MF_SOURCE_READER_ALL_STREAMS, false));
        winHr(reader->SetStreamSelection(inStreamIndex, true));

        ComPtr<IMFMediaSink> mediaSink;
        winHr(MFCreateAudioRenderer(nullptr, &mediaSink));

        ComPtr<IMFSinkWriter> writer;

        {
            ComPtr<IMFStreamSink> streamSink;
            winHr(mediaSink->GetStreamSinkByIndex(0, &streamSink));

            ComPtr<IMFMediaTypeHandler> typeHandler;
            winHr(streamSink->GetMediaTypeHandler(&typeHandler));

            ComPtr<IMFMediaType> inputType;
            winHr(reader->GetCurrentMediaType(inStreamIndex, &inputType));

            ComPtr<IMFMediaType> closestSupportedType;
            const auto result = typeHandler->IsMediaTypeSupported(inputType, &closestSupportedType);
            if (result == MF_E_INVALIDMEDIATYPE)
            {
                if (!closestSupportedType)
                {
                    std::cerr << "Media type not supported" << std::endl;
                    winHr(mediaSink->Shutdown());
                    goto end; //:o
                }
                winHr(reader->SetCurrentMediaType(inStreamIndex, nullptr, closestSupportedType));
                winHr(typeHandler->SetCurrentMediaType(closestSupportedType));
                winHr(MFCreateSinkWriterFromMediaSink(mediaSink, nullptr, &writer));
                winHr(writer->SetInputMediaType(0, closestSupportedType, nullptr));
            }
            else {
                winHr(result);
                winHr(reader->SetCurrentMediaType(inStreamIndex, nullptr, inputType));
                winHr(typeHandler->SetCurrentMediaType(inputType));
                winHr(MFCreateSinkWriterFromMediaSink(mediaSink, nullptr, &writer));
                winHr(writer->SetInputMediaType(0, inputType, nullptr));
            }
        }

        winHr(writer->BeginWriting());
        while (true)
        {
            ComPtr<IMFSample> sample;
            DWORD streamFlags;
            MFTIME timestamp;
            winHr(reader->ReadSample(inStreamIndex, 0, nullptr, &streamFlags, &timestamp, &sample));

            if (streamFlags & MF_SOURCE_READERF_ENDOFSTREAM)
            {
                winHr(writer->NotifyEndOfSegment(0));
                break;
            }
            if (streamFlags & MF_SOURCE_READERF_STREAMTICK)
                winHr(writer->SendStreamTick(0, timestamp));

            if (!sample) continue;

            winHr(sample->SetSampleTime(timestamp));
            winHr(writer->WriteSample(0, sample));
        }
        winHr(writer->Flush(0));

        std::cout << "(Press enter to stop)" << std::endl;
        std::cin.get();

        winHr(writer->Finalize());
        writer.attach(nullptr);
        winHr(mediaSink->Shutdown());
    }

end:
    winHr(MFShutdown());
    CoUninitialize();
}
#包括
#包括
#包括
#包括
#包括
#包括
#pragma注释(lib,“mf”)
#pragma注释(lib,“mfplat”)
#pragma注释(lib,“mfreadwrite”)
#包括
#pragma注释(lib,“windowsapp”)
void winHr(const HRESULT result){winrt::check_HRESULT(result);}
模板
结构ComPtr:winrt::com\u ptr
{
自动运算符(&()noexcept{返回此->放置();}
运算符T*()无例外
{
断言(this->get());
返回此->获取();
}
};
int main()不例外
{
winHr(coinitializex(nullptr,COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));
winHr(MFStartup(MF_版本));
{
ComPtr阅读器;
winHr(MFCreateSourceReaderFromURL(
LR“(测试波形)”,
空读取器(PTR和读取器));
constexpr auto inStreamIndex=MF\源\读取器\第一\音频\流;
//仅选择音频流
winHr(读卡器->设置流选择(MF\U源\读卡器\所有\流,false));
winHr(读卡器->设置流选择(流内索引,true));
ComPtr-mediaSink;
winHr(MFCreateAudioRenderer(nullptr和mediaSink));
编剧;
{
ComPtr-streamSink;
winHr(mediaSink->GetStreamSinkByIndex(0和streamSink));
ComPtr-typeHandler;
winHr(streamSink->GetMediaTypeHandler(&typeHandler));
ComPtr输入型;
winHr(读卡器->GetCurrentMediaType(流内索引和输入类型));
ComPtr closestSupportedType;
const auto result=typeHandler->IsMediaTypeSupported(inputType和closestSupportedType);
如果(结果==MF_E_INVALIDMEDIATYPE)
{
如果(!closestSupportedType)
{
标准::cerr SetCurrentMediaType(流内索引、nullptr、closestSupportedType));
winHr(typeHandler->SetCurrentMediaType(closestSupportedType));
winHr(MFCreateSinkWriterFromMediaSink(mediaSink、nullptr和writer));
winHr(writer->SetInputMediaType(0,closestSupportedType,nullptr));
}
否则{
winHr(结果);
winHr(reader->SetCurrentMediaType(流内索引、nullptr、inputType));
winHr(typeHandler->SetCurrentMediaType(inputType));
winHr(MFCreateSinkWriterFromMediaSink(mediaSink、nullptr和writer));
winHr(writer->SetInputMediaType(0,inputType,nullptr));
}
}
winHr(writer->BeginWriting());
while(true)
{
ComPtr样品;
德沃德河旗;
时间戳;
winHr(读卡器->读取样本(流内索引、0、空ptr、流标志、时间戳和样本));
if(streamFlags&MF\u SOURCE\u READERF\u ENDOFSTREAM)
{
winHr(writer->NotifyEndOfSegment(0));
打破
}
if(streamFlags&MF\u SOURCE\u READERF\u STREAMTICK)
winHr(writer->SendStreamTick(0,时间戳));
如果(!sample)继续;
winHr(样本->设置样本时间(时间戳));
winHr(writer->WriteSample(0,sample));
}
winHr(writer->Flush(0));
std::cout Shutdown());
}
完:
winHr(MFShutdown());
coninitialize();
}
只是想澄清一下:当我运行此程序时,它会打印
(按enter键停止)
,我可以从耳机中听到噪音(读取:电子信号的失真),我可以推断在很短的时间内音频端口打开然后关闭,但没有播放实际的音频。我如何才能让它工作

编辑1:我刚刚修复了如果
result!=MF\u E\u INVALIDMEDIATYPE
我没有设置媒体类型,但是现在我经常(但不总是,出于某种原因)在
winHr(writer->SetInputMediaType(0,inputType,nullptr));
行中找到
MF\u E\u TOPO\u CODEC\u not\u
。为什么会这样呢?(无论如何,仍然没有播放音频。)


编辑2:显然,当我创建writer时,它很重要,所以现在我只是在最后一刻才这样做,但现在我得到了“媒体类型不受支持”错误。也许我需要手动选择一些媒体类型,但我稍后会查看它,除非有人知道答案。

这段代码对我处理wav文件(Win7,默认声卡)很好:

//----------------------------------------------------------------------------------------------
//Main.cpp
//----------------------------------------------------------------------------------------------
#布拉格语一次
#定义WIN32_精益_和_平均值
#定义严格
#pragma注释(lib,“mfplat”)
#pragma注释(lib,“mfreadwrite”)
#pragma注释(lib,“mf”)
#pragma注释(lib,“mfuuid”)
//----------------------------------------------------------------------------------------------
//适用于Windows 7的Microsoft Windows SDK
#包括
#包括
#包括
//----------------------------------------------------------------------------------------------
// Main.cpp
//----------------------------------------------------------------------------------------------
#pragma once
#define WIN32_LEAN_AND_MEAN
#define STRICT

#pragma comment(lib, "mfplat")
#pragma comment(lib, "mfreadwrite")
#pragma comment(lib, "mf")
#pragma comment(lib, "mfuuid")

//----------------------------------------------------------------------------------------------
// Microsoft Windows SDK for Windows 7
#include <WinSDKVer.h>
#include <new>
#include <windows.h>
#include <strsafe.h>
#include <mfapi.h>
#include <mfidl.h>
#include <mferror.h>
#include <mfreadwrite.h>

template <class T> inline void SAFE_RELEASE(T*& p){

    if(p){
        p->Release();
        p = NULL;
    }
}

#define AUDIO_FILE L"C:\\Project\\Media\\Audio\\test.wav"

HRESULT ProcessAudio(const WCHAR*);

void main(){

    HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

    if(SUCCEEDED(hr)){

        hr = MFStartup(MF_VERSION, MFSTARTUP_LITE);

        if(SUCCEEDED(hr)){

            hr = ProcessAudio(AUDIO_FILE);

            hr = MFShutdown();
        }

        CoUninitialize();
    }
}

HRESULT ProcessAudio(const WCHAR*){

    IMFSourceReader* pSourceReader = NULL;
    IMFMediaType* pType = NULL;
    DWORD dwMediaTypeIndex = 0;
    IMFMediaSink* pAudioSink = NULL;
    IMFStreamSink* pStreamSink = NULL;
    IMFMediaTypeHandler* pMediaTypeHandler = NULL;
    IMFSinkWriter* pSinkWriter = NULL;

    HRESULT hr = MFCreateSourceReaderFromURL(AUDIO_FILE, NULL, &pSourceReader);

    // Check native media type
    if(SUCCEEDED(hr))
        hr = pSourceReader->GetNativeMediaType((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, dwMediaTypeIndex, &pType);

    SAFE_RELEASE(pType);

    // Get current media type
    if(SUCCEEDED(hr))
        hr = pSourceReader->GetCurrentMediaType(dwMediaTypeIndex, &pType);

    if(SUCCEEDED(hr))
        hr = MFCreateAudioRenderer(NULL, &pAudioSink);

    if(SUCCEEDED(hr))
        hr = pAudioSink->GetStreamSinkByIndex(0, &pStreamSink);

    if(SUCCEEDED(hr))
        hr = pStreamSink->GetMediaTypeHandler(&pMediaTypeHandler);

    if(FAILED(hr = pMediaTypeHandler->IsMediaTypeSupported(pType, NULL))){

        SAFE_RELEASE(pType);

        // This is a compatible type with my soundcard
        // MF_MT_MAJOR_TYPE                     MFMediaType_Audio
        // MF_MT_SUBTYPE                        MFAudioFormat_PCM
        // MF_MT_AUDIO_NUM_CHANNELS             2
        // MF_MT_AUDIO_SAMPLES_PER_SECOND       48000
        // MF_MT_AUDIO_BLOCK_ALIGNMENT          4
        // MF_MT_AUDIO_AVG_BYTES_PER_SECOND     192000
        // MF_MT_AUDIO_BITS_PER_SAMPLE          16
        // MF_MT_ALL_SAMPLES_INDEPENDENT        1
        // MF_MT_AUDIO_PREFER_WAVEFORMATEX      1

        hr = MFCreateMediaType(&pType);

        if(SUCCEEDED(hr))
            hr = pType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio);

        if(SUCCEEDED(hr))
            hr = pType->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_PCM);

        if(SUCCEEDED(hr))
            hr = pType->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, 2);

        if(SUCCEEDED(hr))
            hr = pType->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);

        if(SUCCEEDED(hr))
            hr = pType->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4);

        if(SUCCEEDED(hr))
            hr = pType->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 192000);

        if(SUCCEEDED(hr))
            hr = pType->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16);

        if(SUCCEEDED(hr))
            hr = pType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);

        if(SUCCEEDED(hr))
            hr = pType->SetUINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, TRUE);
    }

    if(SUCCEEDED(hr))
        hr = pMediaTypeHandler->SetCurrentMediaType(pType);

    if(SUCCEEDED(hr))
        hr = MFCreateSinkWriterFromMediaSink(pAudioSink, NULL, &pSinkWriter);

    if(SUCCEEDED(hr))
        hr = pSinkWriter->BeginWriting();

    BOOL bProcess = (hr == S_OK ? TRUE : FALSE);
    DWORD streamIndex;
    DWORD flags;
    LONGLONG llTimeStamp;
    IMFSample* pSample = NULL;

    while(bProcess){

        hr = pSourceReader->ReadSample((DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, &streamIndex, &flags, &llTimeStamp, &pSample);

        if(SUCCEEDED(hr) && (flags == 0)){

            if(pSample){

                hr = pSinkWriter->WriteSample(0, pSample);

                SAFE_RELEASE(pSample);
            }
        }
        else{

            bProcess = FALSE;
        }
    }

    if(pSinkWriter)
        pSinkWriter->Finalize();

    if(pAudioSink)
        pAudioSink->Shutdown();

    SAFE_RELEASE(pSample);
    SAFE_RELEASE(pSinkWriter);
    SAFE_RELEASE(pMediaTypeHandler);
    SAFE_RELEASE(pStreamSink);
    SAFE_RELEASE(pAudioSink);
    SAFE_RELEASE(pType);
    SAFE_RELEASE(pSourceReader);

    return hr;
}
#include <iostream>

#include <cassert>

#include <mfidl.h>
#include <mfapi.h>
#include <mfreadwrite.h>
#include <Mferror.h>
#pragma comment(lib, "mf")
#pragma comment(lib, "mfplat")
#pragma comment(lib, "mfreadwrite")

#include <winrt/base.h>
#pragma comment(lib, "windowsapp")

void winHr(const HRESULT result) { winrt::check_hresult(result); }

template<class T>
struct ComPtr : winrt::com_ptr<T>
{
    auto operator&() noexcept { return this->put(); }

    operator T*() noexcept
    {
        assert(this->get());
        return this->get();
    }
};

int main() noexcept
{
    winHr(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));
    winHr(MFStartup(MF_VERSION));

    {
        ComPtr<IMFSourceReader> reader;
        winHr(MFCreateSourceReaderFromURL(
            LR"(test.wav)",
            nullptr, &reader));

        constexpr auto inStreamIndex = MF_SOURCE_READER_FIRST_AUDIO_STREAM;

        // Select only the audio stream
        winHr(reader->SetStreamSelection(MF_SOURCE_READER_ALL_STREAMS, false));
        winHr(reader->SetStreamSelection(inStreamIndex, true));

        ComPtr<IMFMediaSink> mediaSink;
        winHr(MFCreateAudioRenderer(nullptr, &mediaSink));

        ComPtr<IMFSinkWriter> writer;

        {
            ComPtr<IMFStreamSink> streamSink;
            winHr(mediaSink->GetStreamSinkByIndex(0, &streamSink));

            ComPtr<IMFMediaTypeHandler> typeHandler;
            winHr(streamSink->GetMediaTypeHandler(&typeHandler));

            DWORD dwCount = 0;
            ComPtr<IMFMediaType> inputType;
            winHr(typeHandler->GetMediaTypeCount(&dwCount));

            for (INT i = 0; i < dwCount; i++)
            {
                inputType.attach(nullptr);
                winHr(typeHandler->GetMediaTypeByIndex(i, &inputType));
                if (SUCCEEDED(typeHandler->IsMediaTypeSupported(inputType, NULL)))
                    break;
            }

            //ComPtr<IMFMediaType> inputType;
            //winHr(reader->GetCurrentMediaType(inStreamIndex, &inputType));

            winHr(reader->SetCurrentMediaType(inStreamIndex, NULL, inputType));


            //ComPtr<IMFMediaType> closestSupportedType;
            //const auto result = typeHandler->IsMediaTypeSupported(inputType, &closestSupportedType);
            //if (result == MF_E_INVALIDMEDIATYPE)
            //{
            //  if (!closestSupportedType)
            //  {
            //      std::cerr << "Media type not supported" << std::endl;
            //      winHr(mediaSink->Shutdown());
            //      goto end; //:o
            //  }
            //  winHr(reader->SetCurrentMediaType(inStreamIndex, nullptr, closestSupportedType));
            //  winHr(typeHandler->SetCurrentMediaType(closestSupportedType));
            //  winHr(MFCreateSinkWriterFromMediaSink(mediaSink, nullptr, &writer));
            //  winHr(writer->SetInputMediaType(0, closestSupportedType, nullptr));
            //}
            //else 
            {
                //winHr(result);
                //winHr(reader->SetCurrentMediaType(inStreamIndex, nullptr, inputType));
                winHr(typeHandler->SetCurrentMediaType(inputType));
                winHr(MFCreateSinkWriterFromMediaSink(mediaSink, nullptr, &writer));
                winHr(writer->SetInputMediaType(0, inputType, nullptr));
            }
        }

        winHr(writer->BeginWriting());
        while (true)
        {
            ComPtr<IMFSample> sample;
            DWORD streamFlags;
            MFTIME timestamp;
            winHr(reader->ReadSample(inStreamIndex, 0, nullptr, &streamFlags, &timestamp, &sample));

            if (streamFlags & MF_SOURCE_READERF_ENDOFSTREAM)
            {
                winHr(writer->NotifyEndOfSegment(0));
                break;
            }
            if (streamFlags & MF_SOURCE_READERF_STREAMTICK)
                winHr(writer->SendStreamTick(0, timestamp));

            if (!sample) 
                continue;

            // SetSampleTime is redundant
            //winHr(sample->SetSampleTime(timestamp));
            winHr(writer->WriteSample(0, sample));
        }

        // Flush shouldn't be called! 
        // winHr(writer->Flush(0));

        std::cout << "(Press enter to stop)" << std::endl;
        std::cin.get();

        winHr(writer->Finalize());
        writer.attach(nullptr);
        winHr(mediaSink->Shutdown());
    }

end:
    winHr(MFShutdown());
    CoUninitialize();
}