MIXER 混响器编程

得到系统中一共有多少个混音器设备:
(在一般的系统中只有一块声卡,所以返回的值应该为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_CONTROLTYPE_MIXER
  MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT
  MIXERCONTROL_CONTROLTYPE_MUX
  MIXERCONTROL_CONTROLTYPE_SINGLESELECT 

 MIXERCONTROL_CT_CLASS_METER 
  MIXERCONTROL_CONTROLTYPE_BOOLEANMETER
  MIXERCONTROL_CONTROLTYPE_PEAKMETER
  MIXERCONTROL_CONTROLTYPE_SIGNEDMETER
  MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER 

 MIXERCONTROL_CT_CLASS_NUMBER 
  MIXERCONTROL_CONTROLTYPE_DECIBELS
  MIXERCONTROL_CONTROLTYPE_PERCENT
  MIXERCONTROL_CONTROLTYPE_SIGNED
  MIXERCONTROL_CONTROLTYPE_UNSIGNED 

 MIXERCONTROL_CT_CLASS_SLIDER 
  MIXERCONTROL_CONTROLTYPE_PAN
  MIXERCONTROL_CONTROLTYPE_QSOUNDPAN
  MIXERCONTROL_CONTROLTYPE_SLIDER 

 MIXERCONTROL_CT_CLASS_SWITCH 
  MIXERCONTROL_CONTROLTYPE_BOOLEAN
  MIXERCONTROL_CONTROLTYPE_BUTTON
  MIXERCONTROL_CONTROLTYPE_LOUDNESS
  MIXERCONTROL_CONTROLTYPE_MONO
  MIXERCONTROL_CONTROLTYPE_MUTE
  MIXERCONTROL_CONTROLTYPE_ONOFF
  MIXERCONTROL_CONTROLTYPE_STEREOENH 

 MIXERCONTROL_CT_CLASS_TIME 
  MIXERCONTROL_CONTROLTYPE_MICROTIME
  MIXERCONTROL_CONTROLTYPE_MILLITIME 

MIXER_OBJECTF_HMIXER  hmxobj 使用由 mixerOpen 返回的句柄   
MIXER_OBJECTF_MIXER hmxobj 使用由 mixerGetNumDevs 返回的设备总数范围内的数值(0到总数减1)
   
   

mixerSetControlDetails命令充分了解后,相信再理解mixerGetControlDetailsmixerSetControlDetails命令不会困难。下面只给出这两个命令的结构。

--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;i cConnections) || 
     (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));//指定区域清零

你可能感兴趣的:(c++)