得到系统中一共有多少个混音器设备:
(在一般的系统中只有一块声卡,所以返回的值应该为1;我的系统中装有一块PIC创新声卡,一块主板载C-media声卡,还安装了Totalrecorder软件,所以返回值是3)
int devnum=::mixerGetNumDevs();
--mixerOpen
明确的打开混响器设备(保证该混响器在Close前一直存在)
MMRESULT mixerOpen( LPHMIXER phmx, UINT uMxId, DWORD dwCallback, DWORD dwInstance, DWORD fdwOpen );
phmx: 是一个指向设备句柄的指针。当mixeropen成功调用后,该指针所指的就是所打开的混响器设备的句柄。该句柄唯一的表示该混响器设备,为其他的函数所引用。该参数不能为NULL.
uMxId: 为混响器的标识号,用于指定要打开的混响器设备。
当你的系统中只有一个混响器设备时(如:一块声卡),可设其值为0(表示将要打开标识号为0的混响器)。取值范围:0 到 混音器设备总数-1.
系统中混响器设备的数量用 UNIT mixerGetNumDevs() 可以得到,这是一个无参数的函数。
可以通过mixerGetID得到混响器的标识号。
dwCallback,dwInstance:这两个参数不能同时使用。
dwCallback 是在混音器设备发生变化时,接收通知消息的窗口的句柄;
dwInstance 是传给回调函数的用户实例数据。
fdwOpen:打开设备的标志
【注】要明确 设备标识号 和 设备句柄 的真正含义。
[例]
UINT CMixer::GetID()
{
if (MMSYSERR_NOERROR ==
mixerGetID((HMIXEROBJ)m_hMixer, &m_uMxId, MIXER_OBJECTF_HMIXER))
//(HMIXEROBJ)m_hMixer实际值是一个最小为0的整数,设备的标识符
{
return m_uMxId;
}
m_uMxId = -1;
return m_uMxId;
}
BOOL CMixer::Open(HWND hWnd)
{
m_hWnd = hWnd;
if (MMSYSERR_NOERROR !=
mixerOpen(&m_hMixer, m_uMxId,(DWORD)m_hWnd, 0, CALLBACK_WINDOW))//使用dwCallback参数
{
return FALSE;
}
GetID();
if (m_uMxId == -1)//没有可用混音器设备
return FALSE;
return TRUE;
}
--mixerGetLineInfo
得到混音器设备的指定音频线路的信息。
MMRESULT mixerGetLineInfo( HMIXEROBJ hmxobj, LPMIXERLINE pmxl, DWORD fdwInfo );
参数:
hmxobj
混响器设备对象句柄,控制指定音频线路。
pmxl
MIXERLINE 结构地址。填充查询的指定音频线路的相关信息。cbStruct成员必须被初始化。
typedef struct { DWORD cbStruct; //结构大小 DWORD dwDestination; //目标单元编号 //普通的声卡设备所支持的目标单元为: //输出单元 DST_Speakers音量控制 //(类型:MIXERLINE_COMPONENTTYPE_DST_SPEAKERS) //和 输入单元 DST_Wave Input录音控制 //(类型:MIXERLINE_COMPONENTTYPE_DST_WAVEIN) DWORD dwSource; //各目标单元中所能控制的音源(source audio line)线路编号 /* 如输出单元 DST_Speakers音量所能控制的: MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER "Synthesizer" MIDI控制 MIXERLINE_COMPONENTTYPE_SRC_LINE "Line Level" line In 控制 MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE "Microphone" Mic vloume 控制 MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC "Compact Disc" CD Audio MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE "Telephone" 调制解调器 MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT "Wave Out" wave MIXERLINE_COMPONENTTYPE_SRC_ANALOG "Analog" AUX Volume */ DWORD dwLineID; //Mixer设备(或是某一线路)的唯一标识符 DWORD fdwLine; //Status and support flags for the audio line /* MIXERLINE_LINEF_ACTIVE MIXERLINE_LINEF_DISCONNECTED MIXERLINE_LINEF_SOURCE */ DWORD dwUser; //实例数据(Instance data) defined //by the audio device for the line DWORD dwComponentType; //线路类型,如:MIXERLINE_COMPONENTTYPE_DST_SPEAKERS DWORD cChannels; //独立声道数,最小为1 DWORD cConnections; //关联的音频线路总数 //如:检索 类型为:MIXERLINE_COMPONENTTYPE_DST_SPEAKERS //可能返回的数量是7 //(既系统控制面板所能看到的可以混音到DST_SPEAKERS的volume中的所有音频线路) //如:检索 类型为:MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC //返回的数量是0 //(既系统控制面板中的CD音频线路,表示其下没有关联的线路,当然不会再有啦,嘿嘿) DWORD cControls; //Number of controls associated with the audio line. //该值可能是0,表示此线路没有相关控制 CHAR szShortName[MIXER_SHORT_NAME_CHARS]; //dwLineID 对应的设备名 CHAR szName[MIXER_LONG_NAME_CHARS]; struct { //Target media information DWORD dwType; //如:MIXERLINE_TARGETTYPE_WAVEIN DWORD dwDeviceID; //标识符 WORD wMid; //厂家 WORD wPid; //产品 MMVERSION vDriverVersion; CHAR szPname[MAXPNAMELEN]; } Target; } MIXERLINE;
[例1] MIXERLINE mxl; mxl.cbStruct = sizeof(MIXERLINE); mxl.dwComponentType = 线路类型; if (::mixerGetLineInfo((HMIXEROBJ)m_hMixer, &mxl, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE) != MMSYSERR_NOERROR) return ;
fdwInfo:
Flags for retrieving information about an audio line. The following values are defined:
MIXER_GETLINEINFOF_COMPONENTTYPE | 使用MIXERLINE 结构成员dwComponentType 指定 线路类型; |
MIXER_GETLINEINFOF_DESTINATION | 使用MIXERLINE 结构成员dwDestination 范围:0到 MIXERCAPS结构成员cDestinations的值 -1 命令:MIXERCAPS() typedef struct { WORD wMid; //厂家编号 WORD wPid; //产品编号 MMVERSION vDriverVersion; //驱动版本 CHAR szPname[MAXPNAMELEN]; //设备名称 DWORD fdwSupport; //支持信息 DWORD cDestinations;// 可用的Destination(目标单元)数量,如:支持输入输出该值为2 } MIXERCAPS; |
MIXER_GETLINEINFOF_LINEID | 使用MIXERLINE 结构成员dwLineID 这是该设备指定线路的唯一ID,通常用来再次刷新得到新的信息 |
MIXER_GETLINEINFOF_SOURCE | 使用MIXERLINE 结构成员 dwDestination和 dwSource 来共同指定一个线路 dwDestination: 所支持的目标单元编号(如:我们普通的声卡设备所支持的目标单元为输出单元DST_Speakers音量控制 和 输入单元DST_Wave Input录音控制 ) 由命令 MIXERCAPS()可以得到该设备具体的dwDestination编号(从0开始编号)。 dwSource:(范围:0 到MIXERLINE 成员 cConnections值减 1 ) 真对某路具体的dwDestination单元(如:输出单元DST_Speakers音量控制),指定其中某一路音源(source audio line)线路编号;其值可以在上一次的mixerGetLineInfo操作中得到;也可以由MIXERCAPS结构成员cDestinations 返回该dwDestination单元音源线路总数; 【例】 |
MIXER_GETLINEINFOF_TARGETTYPE | 使用dwType member of the Target structure 指定线路 |
MIXER_OBJECTF_AUX | 使用由 UINT auxGetNumDevs(VOID) 命令返回的辅助输出设备的编号 |
MIXER_OBJECTF_HMIXER | 说明 hmxobj 参数使用的是一个由mixerOpen返回的句柄; |
MIXER_OBJECTF_MIXER | 说明 hmxobj 参数使用的是一个由UINT mixerGetNumDevs(VOID)返回的Mixer设备编号 |
--mixerGetLineControls
得到一个或多个与某个音源线路相关的控制
MMRESULT mixerGetLineControls( HMIXEROBJ hmxobj, LPMIXERLINECONTROLS pmxlc, DWORD fdwControls );
参数:
hmxobj
设备对象的句柄
pmxlc
MIXERLINECONTROLS 结构的地址。 这个涉及到多个用来填充 各种控制信息 的MIXERCONTROL结构。
typedef struct { DWORD cbStruct; //结构大小 DWORD dwLineID; //指定的音源线路标识符 union { DWORD dwControlID; //一般首先用mixerGetLineInfo命令得到相关线路的dwLineID //然后利用上面得到的dwLineID,使用一次mixerGetLineControls //在返回的成员 LPMIXERCONTROL pamxctrl 中得到该线路的dwControlID DWORD dwControlType; //参看下面表格 }; DWORD cControls; //控制数量 DWORD cbmxctrl; //必须初始化大小,这是一个单独的MIXERCONTROL结构 LPMIXERCONTROL pamxctrl; //参看下面:MIXERCONTROL 结构 及后面的表格说明 } MIXERLINECONTROLS;
MIXERCONTROL 结构: 描述一路音源的单个控制的 state 和 metrics typedef struct { DWORD cbStruct; DWORD dwControlID; DWORD dwControlType; DWORD fdwControl; //线路状态和支持flags /* MIXERCONTROL_CONTROLF_DISABLED (由于某种原因,The control is disabled,此时只能读该线路设置) MIXERCONTROL_CONTROLF_MULTIPLE (The control has two or more settings per channel) MIXERCONTROL_CONTROLF_UNIFORM (统一控制一个多channel的所有通道) 如:stereo volume线路的禁音控制 许多情况下MIXERCONTROL_CONTROLTYPE_MUX 和 MIXERCONTROL_CONTROLTYPE_MIXER 控制也使用该flag DWORD cMultipleItems; //Number of items per channel //至少为2 of items per channel,为0表示不是 multiple-item 控制 CHAR szShortName[MIXER_SHORT_NAME_CHARS]; CHAR szName[MIXER_LONG_NAME_CHARS]; union { struct { LONG lMinimum; //带符号数,最小值 LONG lMaximum; }; struct { DWORD dwMinimum; //无符号数,最小值 DWORD dwMaximum; }; DWORD dwReserved[6]; } Bounds; //边界 union { DWORD cSteps; DWORD cbCustomData; DWORD dwReserved[6]; } Metrics; } MIXERCONTROL, *PMIXERCONTROL, FAR *LPMIXERCONTROL;
mixerGetLineControls命令参数三 fdwControls :
Flags for retrieving information about one or more controls associated with an audio line. The following values are defined:
MIXER_GETLINECONTROLSF_ALL | pmxlc参数 根据 MIXERLINECONTROLS 结构成员 dwLineID 所指定的音源线路标识符,得到所有和其相关的控制信息。 在 MIXERLINECONTROLS 结构中: cControls (控制数量)必须先行被初始化,可以从上述的mixerGetLineInfo 命令中得到; cbmxctrl 成员比要初始化大小,这是一个单独的MIXERCONTROL结构; pamxctrl 成员必须指向第一个被填充的MIXERCONTROL结构; dwControlID 和 dwControlType成员可以在此次被忽略; |
MIXER_GETLINECONTROLSF_ONEBYID | pmxlc参数 根据dwControlID 控制标识符接收信息。 cControls必须是1; cbmxctrl 成员必须初始化大小,这是一个单独的MIXERCONTROL结构; pamxctrl 成员必须指向第一个被填充的MIXERCONTROL结构; dwLineID 和 dwControlType成员可以在此次被忽略; (先前已通过dwLineID检索线路得到了其对应的d wControlID,参考MIXER_GETLINECONTROLSF_ONEBYTYPE) 常用在程序中 刷新再次得到一个控制的改变信息(响应系统消息:MM_MIXM_CONTROL_CHANGE) |
MIXER_GETLINECONTROLSF_ONEBYTYPE | 得到相关音源线路(由 dwLineID 确定)的一个指定类型(由dwControlType确定)的首个控制, pmxlc参数 根据 一个独立的MIXERCONTROL 结构来收到有关这个指定类型的相关信息; dwControlID忽略不用(一般情况是:先使用dwLineID检索线路,得到dwControlID,再做线路其他的控制) 该查询可以被用来得与某个线路关联的单一控制,如:想得到a waveform-audio output线路的峰值。 dwControlType : MIXERCONTROL_CT_CLASS_CUSTOM MIXERCONTROL_CONTROLTYPE_CUSTOM MIXERCONTROL_CT_CLASS_FADER MIXERCONTROL_CONTROLTYPE_BASS MIXERCONTROL_CONTROLTYPE_EQUALIZER MIXERCONTROL_CONTROLTYPE_FADER MIXERCONTROL_CONTROLTYPE_TREBLE MIXERCONTROL_CONTROLTYPE_VOLUME MIXERCONTROL_CT_CLASS_LIST MIXERCONTROL_CT_CLASS_METER MIXERCONTROL_CT_CLASS_NUMBER MIXERCONTROL_CT_CLASS_SLIDER MIXERCONTROL_CT_CLASS_SWITCH MIXERCONTROL_CT_CLASS_TIME |
MIXER_OBJECTF_HMIXER | hmxobj 使用由 mixerOpen 返回的句柄 |
MIXER_OBJECTF_MIXER | hmxobj 使用由 mixerGetNumDevs 返回的设备总数范围内的数值(0到总数减1) |
对mixerSetControlDetails命令充分了解后,相信再理解mixerGetControlDetails和mixerSetControlDetails命令不会困难。下面只给出这两个命令的结构。
--mixerGetControlDetails
得到指定音源线路的单一控制
MMRESULT mixerGetControlDetails( HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails );
参数:
hmxobj :
mixer设备对象的句柄。
pmxcd :
一个MIXERCONTROLDETAILS结构的地址,该结构包含要得到的具体控制信息。
typedef struct { DWORD cbStruct; DWORD dwControlID; DWORD cChannels; union { HWND hwndOwner; DWORD cMultipleItems; }; DWORD cbDetails; LPVOID paDetails; } MIXERCONTROLDETAILS; cbDetails : Size, in bytes, of one of the following details structures being used: MIXERCONTROLDETAILS_BOOLEAN Boolean value for an audio line control. MIXERCONTROLDETAILS_LISTTEXT List text buffer for an audio line control. For information about the appropriate details structure for a specific control, see Control Types. MIXERCONTROLDETAILS_SIGNED Signed value for an audio line control. MIXERCONTROLDETAILS_UNSIGNED Unsigned value for an audio line control. If the control is a MIXERCONTROL_CONTROLTYPE_CUSTOM control, this member must be equal to the cbCustomData member of the MIXERCONTROL structure. paDetails : Address of an array of one or more structures in which properties for the specified control are retrieved or set.
fdwDetails :
Flags --几个常用到的:
MIXER_GETCONTROLDETAILSF_LISTTEXT
MIXER_GETCONTROLDETAILSF_VALUE
MIXER_OBJECTF_HMIXER
MIXER_OBJECTF_MIXER
--mixerSetControlDetails
设置一个音源线路单一控制的属性。
MMRESULT mixerSetControlDetails( HMIXEROBJ hmxobj, LPMIXERCONTROLDETAILS pmxcd, DWORD fdwDetails ); 参数: hmxobj mixer设备对象的句柄。 pmxcd 一个MIXERCONTROLDETAILS结构的地址,该结构包含要刷新的控制信息。 fdwDetails Flags
【一个完整的含盖基本命令的例子】
实际上我就是为了实现这个控制,开始了利用低级音频函数对MIXER 混响器的编程。
BOOL CMixer::GetRecordradio() { UINT m_uMxId2; // HWND m_hWnd;//回调句柄 HMIXER m_hmx2; MIXERCAPS mxcaps; //返回系统中混音器数量(如:一块普通声卡提供一个混音器设备) int devnum=mixerGetNumDevs(); int i=0; for(i;icConnections) || (mxl_v.dwComponentType !=MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE)) return FALSE; dwSource_v--;//得到编号 //下面这段文字说明在本例中已经没有什么实际意义,是以前调试时留下的,也不删除了, //可以知道如何控制主音(Volume)线路的禁音状态: //--可以利用得到的主音(Volume)线路的mxl.dwLineID, //来查询Volume的禁音状态 //要想查询(或设置)可以混音到DST_SPEAKERS主音(Volume)中的 //相关音源线路(如:wave、micphone等)的禁音状态,还必须再使用 //一次 mixerGetLineInfo 进一步指定其dwLineID //注意:不要简单的直接修改上面的: //mxl.dwComponentType = 类型; //虽然可能有时不会报错,但这成了我们程序中的隐患, //因为有的线路在DST_SPEAKERS和DST_WAVEIN中均有,如: //MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC //下面实现了"强制"单选麦克风线路为录音源输入 MIXERCONTROL mxc; MIXERLINECONTROLS mxlc; mxlc.cbStruct = sizeof(MIXERLINECONTROLS); mxlc.dwLineID = mxl.dwLineID; mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_MUX; //MIXERCONTROL_CONTROLTYPE_MUTE; mxlc.cControls = 1; mxlc.cbmxctrl = sizeof(MIXERCONTROL); mxlc.pamxctrl = &mxc; //为了得到相应的mxc.dwControlID, //锁定mxlc.dwLineID和mxlc.dwControlType指定的线路控制 //目前将对录音目标单元的录音音源线路做单选(多路复用) if (::mixerGetLineControls((HMIXEROBJ)m_hmx2, &mxlc, MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE) != MMSYSERR_NOERROR) return -1; //根据mxc.dwControlID检索线路, MIXERCONTROLDETAILS_BOOLEAN mxcdMute[8]; MIXERCONTROLDETAILS mxcd; mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS); mxcd.dwControlID = mxc.dwControlID;//在上面的&mxc得到 mxcd.cChannels = 1; mxcd.cMultipleItems =mxc.cMultipleItems;//多路因子数目 mxcd.cbDetails = sizeof(*mxcdMute); mxcd.paDetails =&mxcdMute;//存放检索结果 if (::mixerGetControlDetails((HMIXEROBJ)m_hmx2, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR) return -1; //做相应单选改变 int j; for(j=0;j<(int)mxc.cMultipleItems;j++) mxcdMute[j].fValue=false; mxcdMute[dwSource_v].fValue=true; //重新设置dwControlID锁定的线路控制 if (::mixerSetControlDetails((HMIXEROBJ)m_hmx2, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE) != MMSYSERR_NOERROR) return -1; }//for(i;i ::ZeroMemory(&m_mxcaps, sizeof(MIXERCAPS));//指定区域清零