First, note that I know there are a few questions like this already posted; however they
don't seem to address the problem adequately. I have a C# application, with all the pInvoke hooks to talk to the waveXXX API, and I'm able to do capture and play back of
audio with that. I'm also able to adjust speaker (WaveOut) volume with that API.
The problem is that for whatever reason, that API does not allow me to adjust microphone
(WaveIn) volume. So, I managed to find some mixer code that I've also pulled in and
access through pInvoke and that allows me to adjust microphone volume, but only on my W7 PC. The mixer code I started with comes from here:
http://social.msdn.microsoft.com/Forums/en-US/isvvba/thread/05dc2d35-1d45-4837-8e16-562ee919da85
and it works, but is written to adjust speaker volume. I added the SetMicVolume method
shown here...
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);
}
Note the "second attempt" to call GetVolumeControl(). This is done because on XP, in the first call to GetVolumeControl (refer to site above for that code), the call to mixerGetLineControlsA() fails with XP systems returning MIXERR_INVALCONTROL. Then, with this second attempt using mixerOpen(out mixer, 0, 0, 0, 0), the code doesn't return a failure but the mic gain is unaffected. Note, as I said above, this works on W7 (the second attempt is never executed because it doesn't fail using mixerOpen(out mixer, mxid, 0, 0, MIXER_OBJECTF_WAVEIN)).
I admit to not having a good grasp on the mixer API, so that's what I'm looking into now; however if anyone has a clue why this would work on W7, but not XP, I'd sure like to hear it. Meanwhile, if I figure it out before I get a response, I'll post my own answer...
The following code seems to work ok for me now (updated 6/29/2010). Note that my test cases are my two PCs, one being W7 the other being XP, so it's not conclusive. I've verified that this does not work for all machines, but for those on which they do, it seems to be fine.
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);
}
Notice that the main difference is that I'm using a component type of 'MIXERLINE_COMPONENTTYPE_DST_WAVEIN' instead of 'MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE'. Don't really understand this, so if anyone wants to chime in with an explanation (or to tell me that this isn't going to work generically), I'm welcoming the replies!