zoukankan      html  css  js  c++  java
  • win32

    仅供参考

    文档: Rendering a Stream

    代码示例:

    #include <cstdio>
    #include <Windows.h>
    
    // Windows multimedia device
    #include <Mmdeviceapi.h>
    #include <Functiondiscoverykeys_devpkey.h>
    
    // WASAPI
    #include <Audiopolicy.h>
    #include <Audioclient.h>
    
    #include <random>
    
    
    class Noise_Gen {
    public:
        Noise_Gen() : format(), engine(__rdtsc()), float_dist(-1.f, 1.f) {};
    
        void SetFormat(WAVEFORMATEX* wfex) {
            if (wfex->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
                format = *reinterpret_cast<WAVEFORMATEXTENSIBLE*>(wfex);
            }
            else {
                format.Format = *wfex;
                format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
                INIT_WAVEFORMATEX_GUID(&format.SubFormat, wfex->wFormatTag);
                format.Samples.wValidBitsPerSample = format.Format.wBitsPerSample;
                format.dwChannelMask = 0;
            }
        }
    
        // (The size of an audio frame = nChannels * wBitsPerSample)
        void FillBuffer(UINT32 bufferFrameCount, BYTE* pData, DWORD* flags) {
            const UINT16 formatTag = EXTRACT_WAVEFORMATEX_ID(&format.SubFormat);
            if (formatTag == WAVE_FORMAT_IEEE_FLOAT) {
                float* fData = (float*)pData;
                for (UINT32 i = 0; i < format.Format.nChannels * bufferFrameCount; i++) {
                    fData[i] = float_dist(engine);
                }
            }
            else if (formatTag == WAVE_FORMAT_PCM) {
                using rndT = decltype(engine)::result_type;
                UINT32 iterations = format.Format.nBlockAlign * bufferFrameCount / sizeof(rndT);
                UINT32 leftoverBytes = format.Format.nBlockAlign * bufferFrameCount % sizeof(rndT);
                rndT* iData = (rndT*)pData;
                UINT32 i = 0;
                for (; i < iterations; i++) {
                    iData[i] = engine();
                }
                if (leftoverBytes != 0) {
                    rndT lastRnd = engine();
                    BYTE* pLastBytes = pData + i * sizeof(rndT);
                    for (UINT32 j = 0; j < leftoverBytes; ++j) {
                        pLastBytes[j] = lastRnd >> (j * 8) & 0xFF;
                    }
                }
            }
            else {
                //memset(pData, 0, wfex.Format.nBlockAlign * bufferFrameCount);
                *flags = AUDCLNT_BUFFERFLAGS_SILENT;
            }
        }
    
    private:
        WAVEFORMATEXTENSIBLE format;
    
        std::mt19937_64 engine;
        std::uniform_real_distribution<float> float_dist;
    };
    
    // REFERENCE_TIME time units per second and per millisecond
    #define REFTIMES_PER_SEC  10000000ll
    #define REFTIMES_PER_MILLISEC  10000
    
    #define EXIT_ON_ERROR(hres)  
                  if (FAILED(hres)) { goto Exit; }
    #define SAFE_RELEASE(punk)  
                  if ((punk) != NULL)  
                    { (punk)->Release(); (punk) = NULL; }
    
    HRESULT PlayAudioStream(Noise_Gen* pMySource) {
        HRESULT hr;
        REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;
        REFERENCE_TIME hnsActualDuration;
        IMMDeviceEnumerator* pEnumerator = NULL;
        IPropertyStore* pPropertyStore = NULL;
        IMMDevice* pDevice = NULL;
        IAudioClient* pAudioClient = NULL;
        IAudioRenderClient* pRenderClient = NULL;
        WAVEFORMATEX* pwfx = NULL;
        UINT32 bufferFrameCount;
        BYTE* pData;
        DWORD flags = 0;
        PROPVARIANT name;
    
        hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL,
            CLSCTX_ALL, IID_PPV_ARGS(&pEnumerator));
        EXIT_ON_ERROR(hr);
        hr = pEnumerator->GetDefaultAudioEndpoint(
            eRender, eConsole, &pDevice);
        EXIT_ON_ERROR(hr);
    
        hr = pDevice->OpenPropertyStore(STGM_READ, &pPropertyStore);
        EXIT_ON_ERROR(hr);
        PropVariantInit(&name);
        hr = pPropertyStore->GetValue(PKEY_Device_FriendlyName, &name);
        EXIT_ON_ERROR(hr);
        printf("%S", name.pwszVal);
        printf("
    ");
        hr = pDevice->Activate(__uuidof(pAudioClient), CLSCTX_ALL,
            NULL, (void**)&pAudioClient);
        EXIT_ON_ERROR(hr);
        hr = pAudioClient->GetMixFormat(&pwfx);
        EXIT_ON_ERROR(hr);
    
        hr = pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED,
            0, hnsRequestedDuration,
            0, pwfx, NULL);
        EXIT_ON_ERROR(hr);
        // Tell the audio source which format to use.
        pMySource->SetFormat(pwfx);
        // Get the actual size of the allocated buffer.
        hr = pAudioClient->GetBufferSize(&bufferFrameCount);
        EXIT_ON_ERROR(hr);
        hr = pAudioClient->GetService(IID_PPV_ARGS(&pRenderClient));
        EXIT_ON_ERROR(hr);
        // Grab the entire buffer for the initial fill operation.
        hr = pRenderClient->GetBuffer(bufferFrameCount, &pData);
        EXIT_ON_ERROR(hr);
    
        // Load the initial data into the shared buffer.
        pMySource->FillBuffer(bufferFrameCount, pData, &flags);
    
        hr = pRenderClient->ReleaseBuffer(bufferFrameCount, flags);
        EXIT_ON_ERROR(hr);
        // Calculate the actual duration of the allocated buffer.
        hnsActualDuration = REFTIMES_PER_SEC * bufferFrameCount / pwfx->nSamplesPerSec;
        hr = pAudioClient->Start();  // Start playing.
        EXIT_ON_ERROR(hr);
        // Each loop fills about half of the shared buffer.
        DWORD sleepTime;
        while (flags != AUDCLNT_BUFFERFLAGS_SILENT) {
            // Sleep for half the buffer duration.
            sleepTime = (DWORD)(hnsActualDuration / REFTIMES_PER_MILLISEC / 2);
            if (sleepTime != 0)
                Sleep(sleepTime);
            // See how much buffer space is available.
            UINT32 numFramesPadding;
            hr = pAudioClient->GetCurrentPadding(&numFramesPadding);
            EXIT_ON_ERROR(hr);
    
            UINT32 numFramesAvailable = bufferFrameCount - numFramesPadding;
            // Grab all the available space in the shared buffer.
            hr = pRenderClient->GetBuffer(numFramesAvailable, &pData);
            EXIT_ON_ERROR(hr);
    
            // Get next 1/2-second of data from the audio source.
            pMySource->FillBuffer(numFramesAvailable, pData, &flags);
    
            hr = pRenderClient->ReleaseBuffer(numFramesAvailable, flags);
            EXIT_ON_ERROR(hr);
        }
        // Wait for last data in buffer to play before stopping.
        sleepTime = (DWORD)(hnsActualDuration / REFTIMES_PER_MILLISEC / 2);
        if (sleepTime != 0)
            Sleep(sleepTime);
        hr = pAudioClient->Stop();  // Stop playing.
        EXIT_ON_ERROR(hr);
    
    Exit:
        CoTaskMemFree(pwfx);
        SAFE_RELEASE(pRenderClient);
        SAFE_RELEASE(pAudioClient);
        SAFE_RELEASE(pDevice);
        SAFE_RELEASE(pPropertyStore); // you forgot to free the property store
        SAFE_RELEASE(pEnumerator);
        return hr;
    }
    
    int main() {
        HRESULT hr = CoInitialize(nullptr);
        if (FAILED(hr)) { return hr; }
    
        Noise_Gen ng;
        PlayAudioStream(&ng);
    
        CoUninitialize();
    }

    结果: 播放噪音

    外文链接:Filling audio endpoint buffer provided by WASAPI not playing sound

  • 相关阅读:
    12864
    经常使用的正則表達式归纳—JavaScript正則表達式
    官方原版Windows XP SP3(VOL)中文简体版ISO下载
    java final keyword
    ssh 实体关系分析确立(ER图-实体关系图)
    android uiautomator自己主动化測试
    NYOJ 891 找点
    第十一届GPCT杯大学生程序设计大赛完美闭幕
    前端学习——JQuery Ajax使用经验
    VC中获取窗体句柄的各种方法
  • 原文地址:https://www.cnblogs.com/strive-sun/p/14178722.html
Copyright © 2011-2022 走看看