文章出處

  本文主要介紹如何使用混音器Mixer API函數實現系統音量調節,以及設置靜音。

1.混音器的作用及結構

1.1混音器的作用

  聲卡(音頻卡)是計算機進行聲音處理的適配器,具有三個基本功能:

  (1)音樂合成發音功能

  (2)混音器(Mixer)功能和數字聲音效果處理器(DSP)功能

  (3)模擬聲音信號的輸入和輸出功能

  混音器的作用是將來自音樂合成器、CD-ROM、話筒輸入(MIC)等不同來源的聲音組合在一起再輸出。

1.2混音器的結構

  混音器由多個目的單元(Destination)組成,如回放(Playback)、錄音(Recording)、語音命令(Voice Command)等等。

  目的單元(Destination)又由多個連接設備(Connections)組成,如回放下有CD AudioMIDIWave等等。

  而每條連接設備又聯系著一個或多個控制器(Control)。

  控制器是混音器的關鍵,如音量控制器(Volume Control)、靜音控制器(Mute Control)、儀表控制器(Meter Control)等等。

 

2. Mixer API函數

2.1獲取混合器設備的數量

函數原型:

WINMMAPI UINT WINAPI mixerGetNumDevs(void);

函數說明:該函數用于獲取系統中混合器設備的數量。

2.2打開混合器設備

函數原型:

WINMMAPI MMRESULT WINAPI mixerOpen(LPHMIXER phmx, UINT uMxId, DWORD dwCallback, DWORD dwInstance, DWORD fdwOpen);

函數說明:該函數用于打開混合器設備。

參數說明:

參數phmx是一個指向設備句柄的指針,當該函數調用成功,該指針就指向所打開的混合器設備句柄。

參數uMxId是混合器的標識號,用于指定要打開的混合器設備。

參數dwCallback是在混合器設備發生變化時,接收通知消息的窗口句柄。

參數dwInstance是傳給回調函數的用戶實例數據。

參數fdwOpen表示打開設備的標志。

2.3獲取混合器設備指定音頻線路的信息

函數原型:

WINMMAPI MMRESULT WINAPI mixerGetLineInfo(HMIXEROBJ hmxobj, LPMIXERLINE pmxl, DWORD fdwInfo);

函數說明:該函數用于獲取混合器設備指定音頻線路的信息。

參數說明:

參數hmxobj表示混合器設備對象句柄。

參數pmxl是MIXERLINE結構體對象,用于填充指定音頻線路的相關信息。

參數fdwInfo用于指定得到哪些音頻線路信息。

2.4獲取與音頻線路相關的控制

函數原型:

WINMMAPI MMRESULT WINAPI mixerGetLineControls(HMIXEROBJ hmxobj, LPMIXERLINECONTROLS pmxlc, DWORD fdwControls);

函數說明:該函數用于獲取與音頻線路相關的控制。

參數說明:

參數hmxobj表示混合器設備對象句柄。

參數pmxlc是MIXERLINECONTROLS結構體對象,用于填充控制信息。

參數fdwControls用于指定得到哪些線路的控制。

2.5獲取指定控制器的詳細信息

函數原型:

WINMMAPI MMRESULT WINAPI mixerGetControlDetails(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails);

函數說明:該函數用于獲取指定控制器的詳細信息

參數說明:

參數hmxobj表示混合器設備對象句柄。

參數pmxcd是MIXERCONTROLDETAILS結構體對象,包含具體控制信息。

參數fdwDetails用于指定要獲取的信息。

2.6設置指定控制器的詳細信息

函數原型:

WINMMAPI MMRESULT WINAPI mixerSetControlDetails(HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails);

函數說明:該函數用于設置指定控制器的詳細信息

參數說明:

參數hmxobj表示混合器設備對象句柄。

參數pmxcd是MIXERCONTROLDETAILS結構體對象,包含具體控制信息。

參數fdwDetails用于指定要設置的信息。

2.7關閉混合器設備

函數原型:

WINMMAPI MMRESULT WINAPI mixerClose(HMIXER hmx);

函數說明:該函數用于關閉混合器設備

參數說明:

參數hmx表示混合器設備對象句柄。

 

3.使用實例

  下面通過一個簡單的實例來演示如何使用上述的Mixer API函數實現系統音量調節,以及設置靜音。實例運行效果如圖1所示。

 圖1 FV掃頻軟件_V1.0主界面

  該實例是我正在做的一個掃頻軟件,其中的音量調節部分實現了以下功能:

  (1)通過拖動滑塊,能夠調節系統音量的大小,并實時顯示當前音量值。

  (2)通過勾選/取消勾選“靜音”復選框,能夠設置系統是/否靜音。

  (3)調節系統音量或設置靜音時,程序也能夠同步進行響應。

3.1加載頭文件和動態鏈接庫

  在使用Mixer API函數編程時,我們需要在工程中包含頭文件mmsystem.h,并加載動態鏈接庫Winmm.lib。具體方法如下:

1 #include <mmsystem.h>                        //包含音頻操作頭文件mmsystem.h
2 #pragma comment(lib, "Winmm.lib")            //添加動態鏈接庫Winmm.lib

3.2獲取混合器設備的數量

  通過使用Mixer API函數mixerGetNumDevs(),我們可以獲取系統中混合器設備的數量。具體方法如下:

 1 /*
 2  * 函數功能 : 獲取混合器設備的數量
 3  * 備    注 : 
 4  * 作    者 : 博客園 依舊淡然
 5  */
 6 bool CMixerDAO::GetMixerDevsNumber()
 7 {
 8     m_nMixerDevsNumber = ::mixerGetNumDevs();
 9     if(m_nMixerDevsNumber == 0)
10     {
11         return false;
12     }
13     return true;
14 }

  其中,成員變量m_nMixerDevsNumber用于存儲獲取到的系統中混合器設備的數量,若不存在混合器設備,后續對混合器的操作均不可進行。

3.3打開混合器設備

  通過使用Mixer API函數mixerOpen (),我們可以打開指定的混合器設備。具體方法如下:

 1 /*
 2  * 函數功能 : 打開混合器設備
 3  * 備    注 : 參數hWnd表示窗口句柄
 4  *              參數nMixerID表示混合器標識號(取值范圍0到混合器設備總個數-1)
 5  * 作    者 : 博客園 依舊淡然
 6  */
 7 bool CMixerDAO::OpenMixer(HWND hWnd, UINT nMixerID)
 8 {
 9     ASSERT(nMixerID < m_nMixerDevsNumber-1);
10     MMRESULT mmResult = ::mixerOpen(&m_hMixer, nMixerID, (DWORD)hWnd, NULL,
11         MIXER_OBJECTF_MIXER | CALLBACK_WINDOW);
12     if(mmResult != MMSYSERR_NOERROR)
13     {
14         return false;
15     }
16     return true;
17 }

  其中,成員變量m_hMixer用于存儲混合器設備句柄。

3.4獲取混合器設備指定音頻線路的信息

  通過使用Mixer API函數mixerGetLineInfo (),我們可以獲取混合器設備指定音頻線路的信息。具體方法如下:

 1 /*
 2  * 函數功能 : 獲取混合器音頻線路信息
 3  * 備    注 : 
 4  * 作    者 : 博客園 依舊淡然
 5  */
 6 bool CMixerDAO::GetMixerLineInfo()
 7 {
 8     ASSERT(m_hMixer != NULL);
 9     m_tMixerLine.cbStruct = sizeof(MIXERLINE);
10     m_tMixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
11     MMRESULT mmResult = ::mixerGetLineInfo((HMIXEROBJ)m_hMixer, &m_tMixerLine, 
12         MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE);        //指定線路類型
13     if(mmResult != MMSYSERR_NOERROR)
14     {
15         return false;
16     }
17     return true;
18 }

3.5獲取與音頻線路相關的控制

  通過使用Mixer API函數mixerGetLineControls (),我們可以獲取與音頻線路相關的控制。例如要獲得音量控制器,可以采用如下方法:

 1 /*
 2  * 函數功能 : 獲取混合器音頻線路控件(音量)
 3  * 備    注 : 
 4  * 作    者 : 博客園 依舊淡然
 5  */
 6 bool CMixerDAO::GetMixerLineControlsOfVolume()
 7 {
 8     ASSERT(m_hMixer != NULL);
 9     m_tMixerLineControls.cbStruct = sizeof(MIXERLINECONTROLS);
10     m_tMixerLineControls.dwLineID = m_tMixerLine.dwLineID;
11     m_tMixerLineControls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;        //音量
12     m_tMixerLineControls.cControls = 1;
13     m_tMixerLineControls.cbmxctrl = sizeof(MIXERCONTROL);
14     m_tMixerLineControls.pamxctrl = &m_tMixerControlOfVolume;
15     MMRESULT mmResult = ::mixerGetLineControls((HMIXEROBJ)m_hMixer, &m_tMixerLineControls,
16         MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE);
17     if(mmResult != MMSYSERR_NOERROR)
18     {
19         return false;
20     }
21     return true;
22 }

  其中,m_tMixerLineControls.dwControlType用于指定要獲取哪種控制器,若為MIXERCONTROL_CONTROLTYPE_VOLUME,則表明是音量控制器m_tMixerControlOfVolume;若為MIXERCONTROL_CONTROLTYPE_MUTE,則表明是靜音控制器m_tMixerControlOfMute。

3.6獲取指定控制器的詳細信息

  通過使用Mixer API函數mixerGetControlDetails (),我們可以獲取指定控制器的詳細信息。例如要獲取當前的音量值,可以采用如下方法:

 1 /*
 2  * 函數功能 : 獲取混合器控件詳細信息(音量)
 3  * 備    注 : 參數nCurrentVolume表示當前的音量值
 4  * 作    者 : 博客園 依舊淡然
 5  */
 6 bool CMixerDAO::GetMixerControlDetails(DWORD& nCurrentVolume)
 7 {
 8     ASSERT(m_hMixer != NULL);
 9     MIXERCONTROLDETAILS_UNSIGNED tMixerControlDetailsUnsigned;
10     m_tMixerControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
11     m_tMixerControlDetails.dwControlID = m_tMixerControlOfVolume.dwControlID;
12     m_tMixerControlDetails.cChannels = 1;
13     m_tMixerControlDetails.cMultipleItems = 0;
14     m_tMixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
15     m_tMixerControlDetails.paDetails = &tMixerControlDetailsUnsigned;
16     MMRESULT mmResult = ::mixerGetControlDetails((HMIXEROBJ)m_hMixer, &m_tMixerControlDetails,
17         MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE);
18     if(mmResult != MMSYSERR_NOERROR)
19     {
20         return false;
21     }
22     nCurrentVolume = tMixerControlDetailsUnsigned.dwValue;            //獲取當前的音量值
23     return true;
24 }

  獲取系統靜音狀態的方法與上述獲取當前系統音量值的方法類似,但是需要將m_tMixerControlDetails.dwControlID指定為m_tMixerControlOfMute.dwControlID。

3.7設置指定控制器的詳細信息

  通過使用Mixer API函數mixerSetControlDetails (),我們可以設置指定控制器的詳細信息。例如要設置音量值,可以采用如下方法:

 1 /*
 2  * 函數功能 : 設置混合器控件詳細信息(音量)
 3  * 備    注 : 參數nNewVolume表示新的音量值
 4  * 作    者 : 博客園 依舊淡然
 5  */
 6 bool CMixerDAO::SetMixerControlDetails(DWORD nNewVolume)
 7 {
 8     ASSERT(m_hMixer != NULL);
 9     ASSERT(nNewVolume >= m_tMixerControlOfVolume.Bounds.dwMinimum);            //輸入參數范圍驗證
10     ASSERT(nNewVolume <= m_tMixerControlOfVolume.Bounds.dwMaximum);
11     MIXERCONTROLDETAILS_UNSIGNED tMixerControlDetailsUnsigned = {nNewVolume};
12     m_tMixerControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
13     m_tMixerControlDetails.dwControlID = m_tMixerControlOfVolume.dwControlID;
14     m_tMixerControlDetails.cChannels = 1;
15     m_tMixerControlDetails.cMultipleItems = 0;
16     m_tMixerControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
17     m_tMixerControlDetails.paDetails = &tMixerControlDetailsUnsigned;
18     MMRESULT mmResult = ::mixerSetControlDetails((HMIXEROBJ)m_hMixer, &m_tMixerControlDetails,
19         MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE);
20     if(mmResult != MMSYSERR_NOERROR)
21     {
22         return false;
23     }
24     return true;
25 }

  設置系統靜音狀態的方法與上述設置當前系統音量值的方法類似,但是需要將m_tMixerControlDetails.dwControlID指定為m_tMixerControlOfMute.dwControlID。

3.8關閉混合器設備

  通過使用Mixer API函數mixerClose (),可以關閉混合器設備。具體方法如下:

 1 /*
 2  * 函數功能 : 關閉混合器設備
 3  * 備    注 : 
 4  * 作    者 : 博客園 依舊淡然
 5  */
 6 bool CMixerDAO::CloseMixer()
 7 {
 8     ASSERT(m_hMixer != NULL);
 9     MMRESULT mmResult = ::mixerClose(m_hMixer);
10     if(mmResult != MMSYSERR_NOERROR)
11     {
12         return false;
13     }
14     m_hMixer = NULL;
15     return true;
16 }

  至此,我們已經在CMixerDAO類中封裝好了進行混合器操作的一些常用方法,通過調用這些方法,就可以實現調節音量、設置靜音功能了。但是,要實現在調節系統音量、設置靜音時,我們的程序也能夠同步進行響應,就得在我們的程序中對MM_MIXM_CONTROL_CHANGE消息進行監聽并響應了。

3.9監聽響應MM_MIXM_CONTROL_CHANGE消息

  當混合器控制器改變時會發送MM_MIXM_CONTROL_CHANGE消息,我們對該消息進行監聽,并進行相應的消息事件處理,就可以讓我們的程序在調節系統音量、設置靜音時,進行同步響應了。具體的實現代碼如下:

 1 /*
 2  * 函數功能 : 系統音量(靜音)調節消息MM_MIXM_CONTROL_CHANGE的消息處理函數
 3  * 備    注 : 
 4  * 作    者 : 博客園 依舊淡然
 5  */
 6 LONG CFrequencyVoiceDlg::OnMixerCtrlChange(UINT wParam, LONG lParam)
 7 {
 8     //靜音
 9     if((wParam == (UINT)(HMIXEROBJ)m_MixerDAO.m_hMixer) &&
10         (lParam == m_MixerDAO.m_tMixerControlOfMute.dwControlID))
11     {
12         //獲取混合器控件詳細信息(靜音)
13         if(!m_MixerDAO.GetMixerControlDetails(m_isMixerMute))
14         {
15             MessageBox("獲取混合器控件詳細信息(靜音)失敗!", "提示", MB_OK|MB_ICONWARNING);
16             return 0;
17         }
18     
19         //更新靜音復選框的勾選狀態
20         ((CButton*)GetDlgItem(IDC_CHECK_MUTE))->SetCheck((int)m_isMixerMute);    
21     }
22 
23     //音量
24     if((wParam == (UINT)(HMIXEROBJ)m_MixerDAO.m_hMixer) &&
25         (lParam == m_MixerDAO.m_tMixerControlOfVolume.dwControlID))
26     {
27         //獲取混合器控件詳細信息(音量)
28         if(!m_MixerDAO.GetMixerControlDetails(m_nCurrentVolume))
29         {
30             MessageBox("獲取混合器控件詳細信息(音量)失敗!", "提示", MB_OK|MB_ICONWARNING);
31             return 0;
32         }
33         
34         //更新音量控件信息
35         m_nCurrentVolumePos = 65535 - m_nCurrentVolume;
36         UpdateDataVolumeCtrlInfo();
37     }
38 
39     return 0;
40 }

 

   備注:由于接口函數變更,在Win7以上的系統中,調節音量或設置靜音,需要使用IAudioEndpointVolume,具體請參閱MSDN:

http://msdn.microsoft.com/en-us/library/dd370839(v=VS.85).aspx

 

 

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()