如何从C#调整麦克风增益(需要在XP和W7上工作)

首先,请注意我知道有一些问题已经发布; 但他们似乎没有充分解决这个问题。 我有一个C#应用程序,所有pInvoke挂钩都与waveXXX API对话,我可以用它来捕获和回放音频。 我还可以使用该API调整扬声器(WaveOut)音量。
问题在于,无论出于何种原因,该API都不允许我调整麦克风(WaveIn)音量。 所以,我设法找到了一些混音器代码,我也已经通过pInvoke进入并允许我调整麦克风音量,但只能在我的W7 PC上调整。 我开始使用的混音器代码来自这里: http : //social.msdn.microsoft.com/Forums/en-US/isvvba/thread/05dc2d35-1d45-4837-8e16-562ee919da85它可以工作,但写的是调整扬声器音量。 我添加了此处显示的SetMicVolume方法…

public static void SetMicVolume(int mxid, int percentage) { bool rc; int mixer, vVolume; MIXERCONTROL volCtrl = new MIXERCONTROL(); int currentVol; mixerOpen(out mixer, mxid, 0, 0, MIXER_OBJECTF_WAVEIN); int type = MIXERCONTROL_CONTROLTYPE_VOLUME; rc = GetVolumeControl(mixer, MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE, type, out volCtrl, out currentVol); if (rc == false) { mixerClose(mixer); mixerOpen(out mixer, 0, 0, 0, 0); rc = GetVolumeControl(mixer, MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE, type, out volCtrl, out currentVol); if (rc == false) throw new Exception("SetMicVolume/GetVolumeControl() failed"); } vVolume = ((int)((float)(volCtrl.lMaximum - volCtrl.lMinimum) / 100.0F) * percentage); rc = SetVolumeControl(mixer, volCtrl, vVolume); if (rc == false) throw new Exception("SetMicVolume/SetVolumeControl() failed"); mixerClose(mixer); } 

注意调用GetVolumeControl()的“第二次尝试”。 这样做是因为在XP上,在第一次调用GetVolumeControl时(参考上面的站点获取该代码),调用mixerGetLineControlsA()失败,XP系统返回MIXERR_INVALCONTROL。 然后,使用mixerOpen(输出混音器,0,0,0,0)的第二次尝试,代码不会返回故障但麦克风增益不受影响。 注意,正如我上面所说,这适用于W7(第二次尝试从未执行,因为它使用mixerOpen(输出混音器,mxid,0,0,MIXER_OBJECTF_WAVEIN)不会失败)。

我承认没有很好地掌握混音器API,所以这就是我现在正在研究的内容; 但是,如果有人知道为什么这可以在W7上运行,而不是XP,我肯定希望听到它。 同时,如果我在得到答复之前搞清楚,我会发布自己的答案……

我刚刚在使用NAudio编写.NET Voice Recorder时尝试过这样做,发现它非常难。 您可能最终需要编写两个代码,一个用于XP,另一个用于Vista / Win 7.我使用NAudio进行混音器互操作。

这就是我最终的结果(到处都不起作用)

  private void TryGetVolumeControl() { int waveInDeviceNumber = waveIn.DeviceNumber; if (Environment.OSVersion.Version.Major >= 6) // Vista and over { var mixerLine = new MixerLine((IntPtr)waveInDeviceNumber, 0, MixerFlags.WaveIn); foreach (var control in mixerLine.Controls) { if (control.ControlType == MixerControlType.Volume) { volumeControl = control as UnsignedMixerControl; MicrophoneLevel = desiredVolume; break; } } } else { var mixer = new Mixer(waveInDeviceNumber); foreach (var destination in mixer.Destinations) { if (destination.ComponentType == MixerLineComponentType.DestinationWaveIn) { foreach (var source in destination.Sources) { if (source.ComponentType == MixerLineComponentType.SourceMicrophone) { foreach (var control in source.Controls) { if (control.ControlType == MixerControlType.Volume) { volumeControl = control as UnsignedMixerControl; MicrophoneLevel = desiredVolume; break; } } } } } } } } 

以下代码现在似乎对我有用 (2010年6月29日更新 )。 请注意,我的测试用例是我的两台PC,一台是W7,另一台是XP,所以它不是决定性的。 我已经证实这不适用于所有机器,但对于那些机器,它似乎没问题。

  public static bool setMicVolume(int mxid, int percentage) { if (mixerdisabled) return(false); bool rc; int mixer, vVolume, ctrltype, comptype; MIXERCONTROL volCtrl = new MIXERCONTROL(); int currentVol; int mr = mixerOpen(out mixer, mxid, 0, 0, MIXER_OBJECTF_WAVEIN); if (mr != MMSYSERR_NOERROR) { Warning("mixerOpen() failed: " + mr.ToString()); mixerdisabled = true; return(false); } ctrltype = MIXERCONTROL_CONTROLTYPE_VOLUME; comptype = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; rc = GetVolumeControl(mixer, comptype, ctrltype, out volCtrl, out currentVol); if (rc == false) { Warning("SetMicVolume/GetVolumeControl() failed"); mixerdisabled = true; mixerClose(mixer); return(false); } vVolume = ((int)((float)(volCtrl.lMaximum - volCtrl.lMinimum) / 100.0F) * percentage); rc = SetVolumeControl(mixer, volCtrl, vVolume); if (rc == false) { Warning("SetMicVolume/SetVolumeControl() failed"); mixerdisabled = true; mixerClose(mixer); return (false); } mixerClose(mixer); return (true); } 

请注意,主要区别在于我使用的是“MIXERLINE_COMPONENTTYPE_DST_WAVEIN”而不是“MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE”的组件类型。 真的不明白这一点,所以如果有人想要解释(或者告诉我这一般不会起作用),我很欢迎回复!