7

首先,请注意,我知道已经发布了一些这样的问题;但是他们似乎没有充分解决这个问题。我有一个 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(out mixer, 0, 0, 0, 0),代码不会返回失败,但麦克风增益不受影响。请注意,正如我上面所说,这适用于 W7(第二次尝试永远不会执行,因为它不会使用 MixerOpen(out Mixer, mxid, 0, 0, MIXER_OBJECTF_WAVEIN) 失败)。

我承认对混音器 API 没有很好的掌握,所以这就是我现在正在研究的;但是,如果有人知道为什么这适用于 W7 而不是 XP,我肯定想听听。同时,如果我在得到回复之前弄清楚了,我会发布我自己的答案......

4

2 回答 2

1

以下代码现在对我来说似乎可以正常工作(更新于 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”。不太明白这一点,所以如果有人想解释一下(或告诉我这不会通用),我欢迎回复!

于 2010-06-11T17:04:09.607 回答
1

不久前,当我使用 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-06-11T13:37:32.447 回答