Switching between Mic In and Stereo Mix

Jan 26, 2010 at 5:51 AM

Hi,

thanks for a great library! I've been using it for couple of projects to get Mic input with great success, but now I got stuck with a problem I cannot resolve:

In my app I'd like to capture sound either from microphone input, or from stereo mixer (sound output). When using for example Audacity software, I can choose whether the caputerd sound comes from Mic or from mixer, but using NAudio's WaveIn.DeviceCount I can always get only 1 device, so there is no way to switch between the sources.

Of course, I can switch the sources using audio driver options, or directly in  Audacity or similar apps - the change affects my application as well. But I'd like to do it within my code and I have no idea how.

I don't know If I'm missing something fundamental, or such funcionality is just not supported by NAudio. But then again, if Audacity can do it, there must be some standardized way to do it.... Does anyone came across the same problem? Thanks for advice...

(My audio device is Realtek HD.)

Coordinator
Jan 26, 2010 at 9:36 AM

hi MuHoR,

there is a distinction between physical inputs on your soundcard and WaveIn devices. Often there is just a single WaveIn device for many physical inputs. The mixer API is the way to choose what you actually want to record. NAudio has wrappers for the mixer API, but unfortunately due to changes to the Windows audio subsystem in Vista it is extremely hard to write code that works reliably in both XP and Vista/Win7. I haven't used Audacity recently, so I don't know what mechanism they are using, but I would expect it is the mixer API.

Mark

Jan 27, 2010 at 8:20 AM

Thank's a lot for your reply, Mark!

I was following your advice and studied about the windows mixer api and NAudio's wrapper for it. I think I understand the structure now and I can use the NAudio mixer-related classes to enumerate sources and destinations and their controls, but I can't see any way how to actually change any of those controls using NAudio. Neither can I see how to achieve the main thing I'm attempting to do - switching sources from Microphone to WaveOut. Everythings seems to be ReadOnly in NAudio wrapper classes.

I guess this is quite an infrequent problem I'm trying to solve here, but if someone tried (and achieved) to do the same, please share your experience.

Coordinator
Jan 27, 2010 at 4:57 PM

you can set the value of controls with NAudio. I would imagine that there are some boolean controls you could use to select a mixer input

Mark

Jan 28, 2010 at 3:18 AM
Edited Jan 28, 2010 at 3:24 AM

Thanks for another advice, Mark!

As you said, the settings is in the boolean control called Mux in the MixerLine I get from the WaveIn. I can see it changing to True when I switch to the WaveOut (in Audacity or elsewhere) and False when I set it to MicIn. However, I still didn't manage to change the value of it - if I try, I get the exception "InvalidParameter calling mixerSetControlDetails".

So I had a look into the source of BooleanMixerControl(.cs - 1.3 beta Oct. 10 2009), and it seems that the Set part of Value property actually doesn't pass the new value to the mixerControlDetails - it's commented out:

 

		public bool Value 
		{
			get 
			{
				GetControlDetails(); // make sure we have the latest value
				return (boolDetails.fValue == 1);
			}
			set 
			{
				//GetControlDetails();
				//MixerInterop.MIXERCONTROLDETAILS_BOOLEAN boolDetails = (MixerInterop.MIXERCONTROLDETAILS_BOOLEAN) 
//Marshal.PtrToStructure(mixerControlDetails.paDetails,typeof(MixerInterop.MIXERCONTROLDETAILS_BOOLEAN));
//boolDetails.fValue = (value) ? 1 : 0; // TODO: pin the memory MmException.Try(MixerInterop.mixerSetControlDetails
(mixerHandle, ref mixerControlDetails, MixerFlags.Value | mixerHandleType), "mixerSetControlDetails"); } }

 Anyways, if the value doesn't get passed, where is the invalid paramer exception coming from?
I tried to fix this and marshal the value the same way you do it in the signed mixer control:
set 
			{
                boolDetails.fValue = Convert.ToInt32(value);
                Marshal.StructureToPtr(boolDetails, mixerControlDetails.paDetails, false);
                MmException.Try(MixerInterop.mixerSetControlDetails
(mixerHandle, ref mixerControlDetails, MixerFlags.Value | mixerHandleType), "mixerSetControlDetails"); Marshal.FreeHGlobal(mixerControlDetails.paDetails); }
But I still get the InvalidParameter exception. I think I'll tinker with this a bit more, but I would like to know if there was something which made you comment the code out in the original version before geetting too deep into the problem (I.e. if there were some underlying problems I can't know about at this level).

I added this into the issues section as well. Thanks for the help so far!

 

Coordinator
Jan 28, 2010 at 9:53 AM

oh, I didn't realise I hadn't done the boolean control. I think the signed and unsigned controls work, so you could compare with the set value code for them. I wrote the original code ages ago. It was more or less the first .NET interop code I had ever written. I didn't really know what I was doing back then (still don't if I'm honest!)

Mark

Dec 16, 2010 at 8:06 AM

I read an article on codeproject where someone created an interop for the IMAPI2 library
and they had said the hard thing for them to figure out when they wrote the wrapper was
that they needed to place the Set method before the Get method and for some strange reason that
made the wrapper work correctly.

 

I am posting this here even though it is an old thread so that if someone else is writing a wrapper or having difficulties / issues.

Just thought I would pass it along... cheers.

Feb 11, 2011 at 1:45 PM
Edited Feb 11, 2011 at 1:48 PM

 

 

I make same thing MuHoR did, i don't have any error but Mute value doesn't chnage.

 

Anyone solves this issue?