对声卡输出进行录音的设置.

本文详细介绍了如何通过编程设置录音设备的输出源,包括stereomix和monomix的选择及音量调节,并讨论了录音前的最佳实践,例如禁用不需要的输入源以提高录音质量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一般正常的录音都是对Line in进行录音,但有些需要对line out进行录音,因为有些音源是没有line in的.

如即时聊天时录取对方的语音.但这些声音都要经过声卡播放,所以它们的音源就是声卡输出.

对于声卡的输出,在录音控制中有两个,就是Mono mix和stereo mix,当然最好是选取stereo mix,效果更好.

编程打开录音设备时,是不能控制打开的设备上的输出还是输入通道的.所在要在打开设备前就设置好.

用Mixer的API可以对输出源进行牧举,不过不同的设备的定义不同,对于SoundMax能够正确区别stereo mix和Mono mix的区别,但AC 97的声卡它都是相似的输出源.所以只能多次地优选列举.代码逻辑不是完美,但只能如此.否则只能让用户手工选择,致少要按6次mouse才行.

以下是自己定义的结构,在第一次没有找到正确的输出源时将所有输出源保的index,swLineID和name保存起来.下面

在结构数组中再优选,而不要再对设备牧举

typedef struct ControlEnumData{
INT index;
CString szName;
DWORD dwLineID;
} CTRL_ENUM_DATA,* LPCTRL_ENUM_DATA;

BOOLXXX::setOutSource()
{
UINTdeviceCount
=::mixerGetNumDevs();
if(deviceCount<1){
MessageBox(
"没有找到混音设备,请手工选择录音设备的混音输出!");
returnTRUE;
}
BOOLfound
=FALSE;

for(UINTdevID=0;devID<deviceCount;devID++){
HMIXERhMixer;
if(mixerOpen(&hMixer,devID,(DWORD)0,0,CALLBACK_WINDOW)!=MMSYSERR_NOERROR)
{
::mixerClose(hMixer);
continue;
}

MIXERLINEline;
line.cbStruct
=sizeof(MIXERLINE);
//注意我们要查找的是录音设备.所以dwComponentType应该是MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
line.dwComponentType=MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
if(::mixerGetLineInfo((HMIXEROBJ)hMixer,&line,
MIXER_OBJECTF_HMIXER
|MIXER_GETLINEINFOF_COMPONENTTYPE)!=MMSYSERR_NOERROR){
::mixerClose(hMixer);
continue;
}
DWORDdwConnections
=line.cConnections;
DWORDselectIndex
=-1;
MIXERLINElinesub;
CTRL_ENUM_DATAenumData[
8];
intenumIndex=0;
//然后看录音设备上共一连结了几个线路
for(DWORDi=0;i<dwConnections;i++){//列举出波形混音输出源的索引并最声音设置最大
linesub.cbStruct=sizeof(MIXERLINE);
linesub.dwSource
=i;
linesub.dwDestination
=line.dwDestination;
if(mixerGetLineInfo((HMIXEROBJ)hMixer,&linesub,
MIXER_OBJECTF_HMIXER
|MIXER_GETLINEINFOF_SOURCE)==MMSYSERR_NOERROR){
if(linesub.dwComponentType==MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT){
//这是stereomix的输出源.如果能明确找到,就直接定位到这个index上.
//并把这个设备选中并把音量调到最大.
MIXERCONTROLmxc;
MIXERLINECONTROLSmxlc;
mxlc.cbStruct
=sizeof(MIXERLINECONTROLS);
mxlc.dwLineID
=linesub.dwLineID;
DWORDdwControlType
=MIXERCONTROL_CONTROLTYPE_VOLUME;
mxlc.dwControlType
=dwControlType;
mxlc.cControls
=1;
mxlc.cbmxctrl
=sizeof(MIXERCONTROL);
mxlc.pamxctrl
=&mxc;
if(::mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc,
MIXER_OBJECTF_HMIXER
|MIXER_GETLINECONTROLSF_ONEBYTYPE)==MMSYSERR_NOERROR)
{
MIXERCONTROLDETAILS_BOOLEANvumVal[
1];
MIXERCONTROLDETAILSmxcd;
mxcd.cbStruct
=sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID
=mxc.dwControlID;//在上面的&mxc得到
mxcd.cChannels=1;
mxcd.cMultipleItems
=mxc.cMultipleItems;
mxcd.cbDetails
=sizeof(MIXERCONTROLDETAILS_BOOLEAN);
mxcd.paDetails
=&vumVal;
vumVal[
0].fValue=65535;
//将设备音量调至最大
::mixerSetControlDetails((HMIXEROBJ)hMixer,&mxcd,
MIXER_OBJECTF_HMIXER
|MIXER_GETCONTROLDETAILSF_VALUE);

}
selectIndex
=i;
break;//如果明确找到MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT,break出去

}
if(linesub.dwComponentType==MIXERLINE_COMPONENTTYPE_SRC_ANALOG){
//否则是MIXERLINE_COMPONENTTYPE_SRC_ANALOG的话,保存起来
enumData[enumIndex].index=i;
enumData[enumIndex].dwLineID
=linesub.dwLineID;
enumData[enumIndex
++].szName=linesub.szName;
}
}

}
if(selectIndex==-1&&enumIndex<1){
::mixerClose(hMixer);
continue;
}
//既没有找到MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT,也没有找到MIXERLINE_COMPONENTTYPE_SRC_ANALOG.

DWORDvumLineID;
//这个ID用于下面对找到的输出源调整音量
if(selectIndex==-1){//第一次优选,找STEREO
for(INTi=0;i<enumIndex;i++){
if(enumData[i].szName.MakeUpper().Find("STEREO")!=-1)
{
selectIndex
=enumData[i].index;
vumLineID
=enumData[i].dwLineID;
break;
}
}
}
if(selectIndex==-1){//第二次优选,找MONO
for(INTi=0;i<enumIndex;i++){
if(enumData[i].szName.MakeUpper().Find("MONO")!=-1)
{
selectIndex
=enumData[i].index;
vumLineID
=enumData[i].dwLineID;
break;
}
}
}
if(selectIndex==-1){//都没有就默认第一个吧.无奈:(
selectIndex=enumData[0].index;
vumLineID
=enumData[0].dwLineID;
}
if(selectIndex!=-1){
//此时肯selectIndex肯定不为-1,加了条件是想在{}内重新定义mxc,mxlc
//来设置音量,不和下面的设置选中的mxc,mxlc冲突.
MIXERCONTROLmxc;
MIXERLINECONTROLSmxlc;
mxlc.cbStruct
=sizeof(MIXERLINECONTROLS);
mxlc.dwLineID
=vumLineID;
DWORDdwControlType
=MIXERCONTROL_CONTROLTYPE_VOLUME;
mxlc.dwControlType
=dwControlType;
mxlc.cControls
=1;
mxlc.cbmxctrl
=sizeof(MIXERCONTROL);
mxlc.pamxctrl
=&mxc;
if(::mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc,
MIXER_OBJECTF_HMIXER
|MIXER_GETLINECONTROLSF_ONEBYTYPE)==MMSYSERR_NOERROR)
{
MIXERCONTROLDETAILS_BOOLEANvumVal[
1];
MIXERCONTROLDETAILSmxcd;
mxcd.cbStruct
=sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID
=mxc.dwControlID;
mxcd.cChannels
=1;
mxcd.cMultipleItems
=mxc.cMultipleItems;
mxcd.cbDetails
=sizeof(MIXERCONTROLDETAILS_BOOLEAN);
mxcd.paDetails
=&vumVal;
vumVal[
0].fValue=65535;
//将设备音量调至最大
::mixerSetControlDetails((HMIXEROBJ)hMixer,&mxcd,
MIXER_OBJECTF_HMIXER
|MIXER_GETCONTROLDETAILSF_VALUE);

}


}
//得到了index就能正确定位该输出源并将其选中,这里调试的时候浪费了很多时间,网上的代码
//都是错误的.录音通道列表和控制面板中录音属性中顺序是一致的,但是对其选中的控件的顺序
//是反的.这一点我调试了好久才发现,没有找到相关文档.KAO,网上可以看到的文章都是错误的.

found
=TRUE;
MIXERCONTROLmxc;
MIXERLINECONTROLSmxlc;
mxlc.cbStruct
=sizeof(MIXERLINECONTROLS);
mxlc.dwLineID
=line.dwLineID;
//注意不能在linesub中查找MIXERCONTROL_CONTROLTYPE_MUX,因为"选中"互斥控件是整个录音控制的
//即MIXERLINE_COMPONENTTYPE_DST_WAVEIN,不是波形混音输出源所独有的.
DWORDdwControlType=MIXERCONTROL_CONTROLTYPE_MUX;
mxlc.dwControlType
=dwControlType;
mxlc.cControls
=1;
mxlc.cbmxctrl
=sizeof(MIXERCONTROL);
mxlc.pamxctrl
=&mxc;
if(::mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc,
MIXER_OBJECTF_HMIXER
|MIXER_GETLINECONTROLSF_ONEBYTYPE)!=MMSYSERR_NOERROR)
{
MessageBox(
"无法选中波形混音输出,请从控制面板中手工设置混音输出为录音设备!");
returnFALSE;
}

MIXERCONTROLDETAILS_BOOLEANvumVal[
8];
MIXERCONTROLDETAILSmxcd;
mxcd.cbStruct
=sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID
=mxc.dwControlID;
mxcd.cChannels
=1;
mxcd.cMultipleItems
=mxc.cMultipleItems;
mxcd.cbDetails
=sizeof(MIXERCONTROLDETAILS_BOOLEAN);
mxcd.paDetails
=&vumVal;

if(::mixerGetControlDetails((HMIXEROBJ)hMixer,&mxcd,
MIXER_OBJECTF_HMIXER
|MIXER_GETCONTROLDETAILSF_VALUE)!=MMSYSERR_NOERROR)
{
MessageBox(
"无法选中波形混音输出,请从控制面板中手工设置混音输出为录音设备!");
returnFALSE;
}
for(DWORDi=0;i<mxc.cMultipleItems;i++){
vumVal[i].fValue
=FALSE;
}
vumVal[mxc.cMultipleItems
-selectIndex-1].fValue=TRUE;
//选中控件顺序和设备顺序相反,TMD
if(::mixerSetControlDetails((HMIXEROBJ)hMixer,&mxcd,
MIXER_OBJECTF_HMIXER
|MIXER_GETCONTROLDETAILSF_VALUE)!=MMSYSERR_NOERROR)
{
MessageBox(
"无法选中波形混音输出,请从控制面板中手工设置混音输出为录音设备!");
returnFALSE;
}
::mixerClose(hMixer);
break;//如果到这里已经正确设置了,break出去.
}
if(!found){
MessageBox(
"没有找到录音设备的混音输出,请手工选择!");
}
returnTRUE;
}

另外,因为混音输出是各种声音的在声卡的输出,所以在录音前最好把所有输入源设为禁音,这样可以保证质量.

并将其它的输出源的音量设为最小(这个是否有影响没有测试)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值