小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Core Audio APIs 技術(shù)筆記一(揚(yáng)聲器音量設(shè)置)

 mediatv 2019-10-29

        最近在做winsows上音頻方面的程序,用到Core Audio APIs系列API來(lái)設(shè)置相關(guān)音頻設(shè)備參數(shù),所以對(duì)用到這方面的知識(shí)做一個(gè)總結(jié)。Core Audio APIs是Windows Vista家族后提供一套新的底層API,主要有以下幾個(gè)內(nèi)容

 Multimedia Device (MMDevice) API:用來(lái)枚舉操作系統(tǒng)自帶的音頻終端設(shè)備對(duì)象。
 Windows Audio Session API (WASAPI):根據(jù)第一步枚舉處理終端設(shè)備對(duì)象創(chuàng)建和管理音頻流。
 DeviceTopology API:使用此類(lèi)API可以直接訪(fǎng)問(wèn)音頻適配器中的硬件數(shù)據(jù)通路的拓?fù)涮匦裕ㄈ缫袅靠刂?,多路?fù)用器等)。
 EndpointVolume API:使用此類(lèi)API可以直接訪(fǎng)問(wèn)音頻設(shè)備的聲音控制,這類(lèi)API主要是給那些毒戰(zhàn)模式管理音頻流的應(yīng)用程序。

下面讓我們用代碼事例設(shè)置麥克風(fēng)和揚(yáng)聲器音量大小,以及設(shè)置麥克風(fēng)加強(qiáng)來(lái)說(shuō)明相關(guān)用法:

  1. 首先我們定義相關(guān)COM接口如下,后面要用到:

  1. CComPtr<IMMDeviceEnumerator > m_pIMMEnumerator; //主要用于枚舉設(shè)備接口
  2. CComPtr<IAudioEndpointVolume> m_pRenderEndptVol; //揚(yáng)聲器音量控制接口
  3. CComPtr<ISimpleAudioVolume> m_pRenderSimpleVol; //揚(yáng)聲器的會(huì)話(huà)音量控制接口

 2.創(chuàng)建IMMDeviceEnumerator接口,IMMDeviceEnumerator接口是獲取后面設(shè)備對(duì)象的根本,所以先要?jiǎng)?chuàng)建這個(gè)接口,用常用創(chuàng)建COM接口的CoCreateInstance()來(lái)創(chuàng)建,指定相應(yīng)的參數(shù),很基本用法,不做過(guò)多說(shuō)明。

  1. HRESULT hr = S_OK;
  2. hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, (void**)&m_pIMMEnumerator);

pIMMEnumerator對(duì)象創(chuàng)建好,我們可以看看這個(gè)接口可以用的方法:

  1. class IMMDeviceEnumerator : public IUnknown
  2. {
  3. public:
  4. virtual HRESULT STDMETHODCALLTYPE EnumAudioEndpoints(EDataFlow dataFlow, DWORD dwStateMask, IMMDeviceCollection **ppDevices) = 0;
  5. virtual HRESULT STDMETHODCALLTYPE GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, IMMDevice **ppEndpoint) = 0;
  6. virtual HRESULT STDMETHODCALLTYPE GetDevice(LPCWSTR pwstrId, IMMDevice **ppDevice) = 0;
  7. virtual HRESULT STDMETHODCALLTYPE RegisterEndpointNotificationCallback(IMMNotificationClient *pClient) = 0;
  8. virtual HRESULT STDMETHODCALLTYPE UnregisterEndpointNotificationCallback(IMMNotificationClient *pClient) = 0;
  9. };

可以看到除過(guò)IUnKonwn接口方法外有屬于自己的五個(gè)方法,分別如下:

  1. //枚舉系統(tǒng)所有設(shè)備
  2. EnumAudioEndpoints(EDataFlow dataFlow, DWORD dwStateMask, IMMDeviceCollection **ppDevices);
  3. //獲取系統(tǒng)默認(rèn)音頻設(shè)備,類(lèi)似主音頻設(shè)備
  4. GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, IMMDevice **ppEndpoint);
  5. //根據(jù)設(shè)備ID獲取指定的設(shè)備,設(shè)備ID可以通過(guò)EnumAudioEndpoints()獲取,也可以通過(guò)DSound函數(shù)DirectSoundEnumerate()等獲取。
  6. GetDevice(LPCWSTR pwstrId, IMMDevice **ppDevice);
  7. //注冊(cè)給終端設(shè)備一些通知事件,注冊(cè)后比如當(dāng)設(shè)備撥出、插入、有變化時(shí)會(huì)收到相應(yīng)的通知事件。
  8. RegisterEndpointNotificationCallback(IMMNotificationClient *pClient);
  9. //注銷(xiāo)掉之前注冊(cè)的通知回調(diào)。
  10. UnregisterEndpointNotificationCallback();

本次我們主要是用GetDefaultAudioEndpoint()和GetDevice()這兩個(gè)接口方法。

4.獲取IAudioEndpointVolume揚(yáng)聲器m_pRenderEndptVol接口,首先我們要定義一個(gè)IMMDevice對(duì)象,根據(jù)剛剛創(chuàng)建的m_pIMMEnumerator對(duì)象獲取相應(yīng)的IMMDevice對(duì)象,然后用獲取的IMMDevice對(duì)象激活m_pRenderEndptVol接口。

如果之前沒(méi)有獲取終端ID則可以使用

  1. //EDataFlow/有三個(gè)常用的變量:
  2. //eAll : 會(huì)列舉出系統(tǒng)中所有的音頻設(shè)備包括Render --- 揚(yáng)聲器, Capture --- Microphone, Stereo Mixer;
  3. //eRender: 會(huì)列舉出系統(tǒng)中所有的音頻播放設(shè)備;
  4. //eCapture: 會(huì)列舉出系統(tǒng)中所有音頻采集設(shè)備;
  5. //ERole 設(shè)備角色,假如系統(tǒng)中有多個(gè)音頻設(shè)備,那么一個(gè)設(shè)備可能用戶(hù)是用來(lái)播放電影的,另一個(gè)可能是用來(lái)玩游戲的,因此就引入了角色的概念。
  6. //eConsole : 與計(jì)算機(jī)交互; eCommunications : 與他人的聲音交流; eMultimedia : 播放或者錄制電影和音樂(lè),一般默認(rèn)使用eConsole。
  7. //ppEndpoint:需要接收獲取設(shè)備對(duì)象指針。
  8. HRESULT GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role, IMMDevice **ppEndpoint);

如果之前已經(jīng)枚舉出設(shè)備ID,想要根據(jù)設(shè)備ID過(guò)去指定的設(shè)備對(duì)象,可以使用

  1. //pwstrId: 已經(jīng)獲取的設(shè)備ID;
  2. //ppDevice:需要接收獲取設(shè)備對(duì)象二重指針;
  3. HRESULT GetDevice(LPCWSTR pwstrId, IMMDevice **ppDevice)

示例代碼如下:

  1. HRESULT hr = S_OK;
  2. CComPtr<IMMDevice> pIMMDeivce = NULL;
  3. if(strEndPointID.empty())
  4. {
  5. hr = m_pIMMEnumerator->GetDefaultAudioEndpoint(eRender,eConsole,&pIMMDeivce);
  6. }
  7. else
  8. {
  9. hr = m_pIMMEnumerator->GetDevice(strEndPointID.c_s(),&pIMMDeivce);
  10. }
獲取pIMMDeivce對(duì)象后,就可以用這個(gè)對(duì)象接口激活自己想要控制的相應(yīng)音量設(shè)備的接口了,先看下IMMDevice接口擁有屬于自己的方法:
  1. class IMMDevice : public IUnknown
  2. {
  3. public:
  4. virtual HRESULT STDMETHODCALLTYPE Activate(REFIID iid, DWORD dwClsCtx, PROPVARIANT *pActivationParams, void **ppInterface) = 0;
  5. virtual HRESULT STDMETHODCALLTYPE OpenPropertyStore(DWORD stgmAccess,IPropertyStore **ppProperties) = 0;
  6. virtual HRESULT STDMETHODCALLTYPE GetId(LPWSTR *ppstrId) = 0;
  7. virtual HRESULT STDMETHODCALLTYPE GetState(DWORD *pdwState) = 0;
  8. };
簡(jiǎn)單注釋下這個(gè)幾個(gè)函數(shù)意義:
  1. //激活這個(gè)設(shè)備下指定接口的COM對(duì)象;
  2. //iid:指定獲取接口的GUID;
  3. //dwClsCtx:執(zhí)行上下文,一般指定CLSCTX_ALL獲取所有信息;
  4. //pActivationParams:對(duì)于IID_IAudioEndpointVolume接口設(shè)置為NULL。
  5. //ppInterface:需要接收獲取設(shè)備對(duì)象二重指針;
  6. HRESULT Activate(REFIID iid, DWORD dwClsCtx, PROPVARIANT *pActivationParams, void **ppInterface)
  7. //打開(kāi)一個(gè)設(shè)備的屬性存儲(chǔ)接口;
  8. HRESULT OpenPropertyStore(DWORD stgmAccess,IPropertyStore **ppProperties)
  9. //獲取設(shè)備ID;
  10. HRESULT GetId(LPWSTR *ppstrId)
  11. //獲取設(shè)備狀態(tài)信息; 
  12. HRESULT GetState(DWORD *pdwState)  
我們主要用的是Activate()方法,首先我們獲取揚(yáng)聲器音量控制接口m_pRenderEndptVol,如下
  1. //主聲音設(shè)備
  2. hr = pIMMDeivce->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**)&m_pRenderEndptVol);
獲取到m_pRenderEndptVol接口后我們就可以用這個(gè)接口設(shè)置系統(tǒng)揚(yáng)聲器音量了。
5.設(shè)置系統(tǒng)揚(yáng)聲器音量,也就是主音量,先看看剛剛我們獲取m_pRenderEndptVol接口擁有屬于自己的方法:
  1. class IAudioEndpointVolume : public IUnknown
  2. {
  3. public:
  4. virtual HRESULT STDMETHODCALLTYPE RegisterControlChangeNotify(IAudioEndpointVolumeCallback *pNotify) = 0;
  5. virtual HRESULT STDMETHODCALLTYPE UnregisterControlChangeNotify(IAudioEndpointVolumeCallback *pNotify) = 0;
  6. virtual HRESULT STDMETHODCALLTYPE GetChannelCount(UINT *pnChannelCount) = 0;
  7. virtual HRESULT STDMETHODCALLTYPE SetMasterVolumeLevel(float fLevelDB,LPCGUID pguidEventContext) = 0;
  8. virtual HRESULT STDMETHODCALLTYPE SetMasterVolumeLevelScalar(float fLevel,LPCGUID pguidEventContext) = 0;
  9. virtual HRESULT STDMETHODCALLTYPE GetMasterVolumeLevel(float *pfLevelDB) = 0;
  10. virtual HRESULT STDMETHODCALLTYPE GetMasterVolumeLevelScalar(float *pfLevel) = 0;
  11. virtual HRESULT STDMETHODCALLTYPE SetChannelVolumeLevel(UINT nChannel,float fLevelDB,LPCGUID pguidEventContext) = 0;
  12. virtual HRESULT STDMETHODCALLTYPE SetChannelVolumeLevelScalar(UINT nChannel,float fLevel,LPCGUID pguidEventContext) = 0;
  13. virtual HRESULT STDMETHODCALLTYPE GetChannelVolumeLevel(UINT nChannel,float *pfLevelDB) = 0;
  14. virtual HRESULT STDMETHODCALLTYPE GetChannelVolumeLevelScalar(UINT nChannel,float *pfLevel) = 0;
  15. virtual HRESULT STDMETHODCALLTYPE SetMute(BOOL bMute,LPCGUID pguidEventContext) = 0;
  16. virtual HRESULT STDMETHODCALLTYPE GetMute(BOOL *pbMute) = 0;
  17. virtual HRESULT STDMETHODCALLTYPE GetVolumeStepInfo(UINT *pnStep,UINT *pnStepCount) = 0;
  18. virtual HRESULT STDMETHODCALLTYPE VolumeStepUp(LPCGUID pguidEventContext) = 0;
  19. virtual HRESULT STDMETHODCALLTYPE VolumeStepDown(LPCGUID pguidEventContext) = 0;
  20. virtual HRESULT STDMETHODCALLTYPE QueryHardwareSupport(DWORD *pdwHardwareSupportMask) = 0;
  21. virtual HRESULT STDMETHODCALLTYPE GetVolumeRange(float *pflVolumeMindB,float *pflVolumeMaxdB,float *pflVolumeIncrementdB) = 0;
  22. };
這個(gè)IAudioEndpointVolume接口方法很多,不仔細(xì)介紹每一個(gè)了,只介紹我們需要用到的幾個(gè)方法,大家可以根據(jù)自己的需要,顧名思義找到自己需要用的方法。
  1. /*
  2. 設(shè)置音頻終端的主音量電;
  3. fLevel:主音量數(shù)值級(jí)別,這個(gè)值范圍在0到1之間;
  4. pguidEventContext):此參數(shù)指向一個(gè)事件上下文的GUID,如果SetMasterVolumeLevelScalar調(diào)用更改端點(diǎn)的音量,所有已注冊(cè)客戶(hù)IAudioEndpointVolumeCallback接口與端點(diǎn)將接收通知。
  5. */
  6. HRESULT SetMasterVolumeLevelScalar(float fLevel,LPCGUID pguidEventContext);
  7. //獲取音頻終端的主音量電平;
  8. HRESULT GetMasterVolumeLevelScalar(float *pfLevel);
  9. //設(shè)置音頻終端是否為靜音狀態(tài);
  10. HRESULT SetMute(BOOL bMute,LPCGUID pguidEventContext);
  11. //獲取音頻終端是靜音狀態(tài);
  12. HRESULT GetMute(BOOL *pbMute);
其余幾個(gè)參數(shù)很簡(jiǎn)單,看名字就知道什么意思,不作過(guò)多介紹。

設(shè)置系統(tǒng)揚(yáng)聲器音量代碼示例:

  1. float level = 0.5f;//這個(gè)值可以跟進(jìn)相應(yīng)比例換算所得
  2. hr = m_pRenderEndptVol->SetMasterVolumeLevelScalar(level, NULL);
獲取系統(tǒng)揚(yáng)聲器音量代碼示例:
  1. float level = 0.0f;
  2. hr = m_pRenderEndptVol->GetMasterVolumeLevelScalar(&level);
注意level這個(gè)值一般根據(jù)界面滑動(dòng)條最大值按比例換算所得。
設(shè)置系統(tǒng)揚(yáng)聲器靜音示例:
hr = m_pRenderSimpleVol->SetMute(TRUE, NULL);

獲取系統(tǒng)揚(yáng)聲器靜音狀態(tài)示例: 

  1. BOOL bMute = 0;
  2. hr = m_pRenderSimpleVol->GetMute(&bMute);
這只是簡(jiǎn)單的幾種參數(shù)設(shè)置,大家可以根據(jù)自己的需要來(lái)選擇不同方法達(dá)到自己目的。

6.設(shè)置應(yīng)用程序會(huì)話(huà)音量
        上面設(shè)置的都是系統(tǒng)揚(yáng)聲器的音量,即相應(yīng)的設(shè)置會(huì)影響系統(tǒng)上所有軟件的音量,下面我們來(lái)設(shè)置屬于應(yīng)用程序本身的會(huì)話(huà)音量,所謂會(huì)話(huà)音量即時(shí)這個(gè)應(yīng)用程序本身的音量,設(shè)置會(huì)話(huà)音量的大小只會(huì)影響應(yīng)用程序本身的音量大小,不會(huì)影響系統(tǒng)其它程序音量的大小。首先我們要獲取IAudioSessionManager接口對(duì)象,方法是通過(guò)已經(jīng)獲取IMMDevice接口對(duì)象來(lái)激活I(lǐng)AudioSessionManager接口對(duì)象,然后就可以通過(guò)IAudioSessionManager接口來(lái)獲取ISimpleAudioVolume接口對(duì)象了,最后通過(guò)ISimpleAudioVolume接口對(duì)象就可以操作會(huì)話(huà)音量的大小了。示例代碼如下:

  1. //合成器界面
  2. CComPtr<IAudioSessionManager> pSessionManager = NULL;
  3. hr = pIMMDeivce->Activate(IID_IAudioSessionManager, CLSCTX_INPROC_SERVER, NULL, (void **)(&pSessionManager));
  4. if(FAILED(hr)) return;
  5. hr = pSessionManager->GetSimpleAudioVolume(NULL, FALSE, &m_pRenderSimpleVol);

獲取到ISimpleAudioVolume接口對(duì)象后就可以使用其具有的方法操作具體的功能了,看下這個(gè)接口有的方法:

  1. class ISimpleAudioVolume : public IUnknown
  2. {
  3. public:
  4. virtual HRESULT STDMETHODCALLTYPE SetMasterVolume(float fLevel, LPCGUID EventContext) = 0;
  5. virtual HRESULT STDMETHODCALLTYPE GetMasterVolume(float *pfLevel) = 0;
  6. virtual HRESULT STDMETHODCALLTYPE SetMute(const BOOL bMute, LPCGUID EventContext) = 0;
  7. virtual HRESULT STDMETHODCALLTYPE GetMute(BOOL *pbMute) = 0;
  8. };
所有方法和上面IAudioEndpointVolume接口方法基本一樣,直接貼代碼說(shuō)明
設(shè)置和獲取會(huì)話(huà)音量的大小:
  1. //設(shè)置揚(yáng)聲器會(huì)話(huà)音量大小
  2. float fVol = 0.5f;
  3. hr = m_pRenderSimpleVol->SetMasterVolume(fVol, NULL);
  4. //獲取揚(yáng)聲器會(huì)話(huà)音量大小
  5. float fVol = 0.0f;
  6. hr = m_pRenderSimpleVol->GetMasterVolume(&fVol);
設(shè)置和獲取會(huì)話(huà)音量的靜音狀態(tài):
  1. //設(shè)置揚(yáng)聲器會(huì)話(huà)音量靜音狀態(tài)
  2. BOOL bMute = TRUE;
  3. hr = m_pRenderSimpleVol->SetMute(bMute , NULL);
  4. //獲取揚(yáng)聲器靜音狀態(tài)
  5. hr = m_pRenderSimpleVol->GetMute(&bMute);
        揚(yáng)聲器里面的功能設(shè)置還有很多方法,介紹只是最基本的方法,大家可以根據(jù)自己需要挖掘更深層的設(shè)置方法,這一節(jié)就先介紹到這里吧,下一節(jié)介紹系統(tǒng)麥克風(fēng)方面一些簡(jiǎn)單的設(shè)置。                                      

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀(guān)點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多