本文主要介紹如何使用混音器Mixer API函數實現系統音量調節,以及設置靜音。
1.混音器的作用及結構
1.1混音器的作用
聲卡(音頻卡)是計算機進行聲音處理的適配器,具有三個基本功能:
(1)音樂合成發音功能
(2)混音器(Mixer)功能和數字聲音效果處理器(DSP)功能
(3)模擬聲音信號的輸入和輸出功能
混音器的作用是將來自音樂合成器、CD-ROM、話筒輸入(MIC)等不同來源的聲音組合在一起再輸出。
1.2混音器的結構
混音器由多個目的單元(Destination)組成,如回放(Playback)、錄音(Recording)、語音命令(Voice Command)等等。
目的單元(Destination)又由多個連接設備(Connections)組成,如回放下有CD Audio、MIDI、Wave等等。
而每條連接設備又聯系著一個或多個控制器(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
文章列表