Click here to Skip to main content
15,887,313 members
Articles / Programming Languages / Visual Basic
Article

Audio Library Part I - (Windows Mixer Control)

Rate me:
Please Sign up or sign in to vote.
4.52/5 (79 votes)
1 Oct 2006CPOL3 min read 607.3K   15.4K   163   165
Library to control Windows Mixer from C#
Sample Image - AudioLib.jpg

Introduction

In this article, I'll show you how to use Windows Mixer from C#.

For some time, I was trying to get information about how to program the mixer from C#. I didn't have too much luck, and the few examples found were in C++, so… I took the hard and fun way... doing it myself.

This library is part of my Audio library to control Wave Audio (Playback/Recording), Mixer, Playback/Recording compressed files using ACM, basic speech recognition and some other stuff that I'll be releasing in future articles.

AudioMixer Namespace

Hierarchical Objects View

Sample screenshot

The hierarchical view shows how the classes are organized.

The main object Mixers contains two Mixer objects, Playback and Recording; those will work with default devices, but can be changed by setting the property Mixers.Playback.DeviceId or Mixers.Recording.DeviceId.

I made it as simple as possible by hiding all the flat Win32 API implementation from the developer and creating a hierarchical set of objects.

Every mixer is autonomous, meaning you can have Playback mixer set to one soundcard and Recording mixer to another one. Also each one contains two arrays or MixerLines (Lines, UserLines).

Lines object will contain all lines inside the mixer, for example all the lines that don't have controls associated with it or lines that are not source lines.

UserLines will contains all lines that the developer can interact with, having controls like Volume, Mute, Fadder, Bass, etc. (basically it is the same as Lines object but a filter was applied to it).

Every Line will contain a collection of controls, like Mute, Volume, Bass, Fader, etc.

If you are interested in knowing more about how Windows Mixer works, here is an excellent link with all the information about it.

Let's See Some Code

To Get the Audio Devices in the Computer

C#
foreach(MixerDetail mixerDetail in mMixers.Devices)
{
    ...
    ...
}

To Get the Input Devices

C#
foreach(MixerDetail mixerDetail in mMixers.Recording.Devices)
{
    ...
    ...
}

Change Output Mixer Device

C#
Mixers mixers = new Mixers();
foreach(MixerDetail mixerDetail in mixers.Playback.Devices)
{
    if (mixerDetail.MixerName == "Sound Blaster Live")
        mixers.Playback.DeviceId = mixerDetail.DeviceId;
}

Change Output Mixer Device to the Default Device

C#
Mixers mixers = new Mixers();
mixers.Playback.DeviceId = -1;

or

C#
mixers.Playback.DeviceId = mixers.Playback.DeviceIdDefault;

Getting Playback Speaker Master Volume

C#
mixers.Playback.Lines.GetMixerFirstLineByComponentType(
    MIXERLINE_COMPONENTTYPE.DST_SPEAKERS).Volume;

Setting Playback Speaker Master Volume for the Left Channel Only

C#
MixerLine line = mixers.Playback.Lines.GetMixerFirstLineByComponentType(
    MIXERLINE_COMPONENTTYPE.DST_SPEAKERS);
line.Channel = Channel.Left;
line.Volume = 32000;

Selecting Microphone as Default Input

C#
mixers.Recording.Lines.GetMixerFirstLineByComponentType(
    MIXERLINE_COMPONENTTYPE.SRC_MICROPHONE).Selected = true; 

Getting Callback Notifications When a Line has Changed

C#
/* Initialization */
mMixers = new Mixers();
mMixers.Playback.MixerLineChanged +=
    new WaveLib.AudioMixer.Mixer.MixerLineChangeHandler(mMixer_MixerLineChanged);
mMixers.Recording.MixerLineChanged +=
    new WaveLib.AudioMixer.Mixer.MixerLineChangeHandler(mMixer_MixerLineChanged);
/* Events */
private void mMixer_MixerLineChanged(Mixer mixer, MixerLine line)
{
    Console.WriteLine("Mixer: " + mixer.DeviceDetail.MixerName);
    Console.WriteLine("Mixer Type: " + mixer.MixerType);
    Console.WriteLine("Mixer Line: " + line.Name);
}

Getting and Setting Rare Controls

Specific controls like Fadder, Microphone Boost, bass, treble, etc. can be accessed via the MixerControl object using ValueAsSigned, ValueAsUnsigned and ValueAsBoolean properties, but they are not implemented as standard properties because they don't belong to all controls.

x86 vs x64

Finally I got a core 2 duo and now I could compile the library under x86 and x64. At first I thought there won't be too much difference, but the big problem is that the IntPtr pointers are platform specific, so whereas a x86 takes 4 bytes, a x64 takes 8 bytes, that makes things really messy and there is no simple fix in some cases, for example in the following struct I could not find a way to make it work for x86 and x64 in C#. Looks like the .NET Framework is missing something to work with unions inside structs... I had to declare two structs and work with them separately.

Before

C#
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Auto)]
public struct MIXERCONTROLDETAILS
{
 [FieldOffset(0)] public UInt32  cbStruct;
 [FieldOffset(4)] public UInt32  dwControlID;
 [FieldOffset(8)] public UInt32  cChannels;
 /* Union start */
 [FieldOffset(12)] public IntPtr hwndOwner;
 [FieldOffset(12)] public UInt32 cMultipleItems;
 /* Union end */
 [FieldOffset(16)] public UInt32 cbDetails;
 [FieldOffset(20)] public IntPtr paDetails;
}

After

C#
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 2)]
public struct MIXERCONTROLDETAILS
{
 [FieldOffset(0)]  public UInt32 cbStruct;
 [FieldOffset(4)]  public UInt32 dwControlID;
 [FieldOffset(8)]  public UInt32 cChannels;
 /* Union start */
 [FieldOffset(12)] public IntPtr hwndOwner;
 [FieldOffset(12)] public UInt32 cMultipleItems;
 /* Union end */
 [FieldOffset(16)] public UInt32 cbDetails;
 [FieldOffset(20)] public IntPtr paDetails;
}
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 2)]
public struct MIXERCONTROLDETAILS64
{
 [FieldOffset(0)] public UInt32  cbStruct;
 [FieldOffset(4)] public UInt32  dwControlID;
 [FieldOffset(8)] public UInt32  cChannels;
 /* Union start */
 [FieldOffset(12)] public IntPtr hwndOwner;
 [FieldOffset(12)] public UInt32 cMultipleItems;
 /* Union end */
 [FieldOffset(20)] public UInt32 cbDetails;
 [FieldOffset(24)] public IntPtr paDetails;
}

I was hoping to declare a dynamic size for the FieldOffset and then I could have fixed the problem but it doesn't compile on .NET.

C#
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 2)]
public struct MIXERCONTROLDETAILS
{
 [FieldOffset(0)] public UInt32  cbStruct;
 [FieldOffset(4)] public UInt32  dwControlID;
 [FieldOffset(8)] public UInt32  cChannels;
 /* Union start */
 [FieldOffset(12)] public IntPtr hwndOwner;
 [FieldOffset(12)] public UInt32 cMultipleItems;
 /* Union end */
 [FieldOffset(12 + IntPtr.Size)] public UInt32 cbDetails;
 [FieldOffset(12 + IntPtr.Size + 4)] public IntPtr paDetails;
}

Notes

All the current functionality is tested and working, I tried not to include bugs, but they are there and I find them every once in a while. If you find bugs, I'll be grateful to get feedback to update the article.

For now I don't need anything else from the library, but if you think of something that is not included in it which could make it better, just let me know and I'll try to include it.

If you have a problem with it, feel free to write me an email.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Microsoft
United States United States
I started with programming about 19 years ago as a teenager, from my old Commodore moving to PC/Server environment Windows/UNIX SQLServer/Oracle doing gwBasic, QBasic, Turbo Pascal, Assembler, Turbo C, BC, Summer87, Clipper, Fox, SQL, C/C++, Pro*C, VB3/5/6, Java, and today loving C#.

Currently working as SDE on Failover Clustering team for Microsoft.

Passion for most programming languages and my kids Aidan&Nadia.

Comments and Discussions

 
QuestionCould you just produce a dll file with a API document, like mute the microphone? Pin
Member 1217217430-Nov-15 20:35
Member 1217217430-Nov-15 20:35 
AnswerRe: Could you just produce a dll file with a API document, like mute the microphone? Pin
Member 1353272821-Nov-17 19:24
Member 1353272821-Nov-17 19:24 
QuestionAccessing Win XP Information Pin
CliffRat14-May-14 6:47
CliffRat14-May-14 6:47 
QuestionReg : Microphone Boost Pin
Arun Prasath Kundaru3-Feb-14 17:36
Arun Prasath Kundaru3-Feb-14 17:36 
Questionmixer control Pin
David Altman10-Dec-13 6:10
David Altman10-Dec-13 6:10 
QuestionDouts About Record audio and Listen back microfone Pin
Rodrigo Torres Leme5-Aug-13 5:46
Rodrigo Torres Leme5-Aug-13 5:46 
QuestionMixer Exception Pin
mysofttest4-Jun-12 3:18
mysofttest4-Jun-12 3:18 
GeneralRe: Mixer Exception Pin
Member 96487185-Jul-12 20:59
Member 96487185-Jul-12 20:59 
GeneralRe: Mixer Exception Pin
Tylor Pater21-Nov-13 8:43
Tylor Pater21-Nov-13 8:43 
Question(windows mixer control) Pin
lokesh719010-May-12 23:34
lokesh719010-May-12 23:34 
AnswerRe: (windows mixer control) Pin
mysofttest4-Jun-12 19:54
mysofttest4-Jun-12 19:54 
GeneralMy vote of 5 Pin
Sergio Andrés Gutiérrez Rojas14-Mar-12 18:17
Sergio Andrés Gutiérrez Rojas14-Mar-12 18:17 
GeneralMy vote of 5 Pin
kostickaa5-Jan-12 23:01
kostickaa5-Jan-12 23:01 
QuestionWaveLib.AudioMixer.MixerException Pin
amolpbhavsar10-Sep-11 2:20
amolpbhavsar10-Sep-11 2:20 
AnswerRe: WaveLib.AudioMixer.MixerException Pin
Member 96487185-Jul-12 20:49
Member 96487185-Jul-12 20:49 
GeneralWindows7/Vista version Pin
Member 779661522-Apr-11 19:50
Member 779661522-Apr-11 19:50 
GeneralRe: Windows7/Vista version Pin
loheL17-Sep-11 10:05
loheL17-Sep-11 10:05 
Generaladding wav/mp3 Pin
tzachip10-Dec-10 7:10
tzachip10-Dec-10 7:10 
QuestionRe: adding wav/mp3 Pin
HY1232-Mar-11 1:19
HY1232-Mar-11 1:19 
QuestionHow to impliment Audio Microphone Boost on Windows-7 and Windows-Vista Pin
gawadepd31-Oct-10 21:40
gawadepd31-Oct-10 21:40 
GeneralHiding mixer line Pin
ACNZdev27-Sep-10 14:05
ACNZdev27-Sep-10 14:05 
GeneralRe: Hiding mixer line Pin
RAND 45586617-Mar-11 21:41
RAND 45586617-Mar-11 21:41 
Generalwin 7 mixer Pin
Pdaus10-Aug-10 0:02
Pdaus10-Aug-10 0:02 
GeneralC# Mixer Project needs massive update. [modified] Pin
Member 724777618-Jul-10 17:19
Member 724777618-Jul-10 17:19 
July 17th 2010
~p
This project makes me want to cry.

Somehow back in the day when it came out.. I was hacking on it and ended up with some volume meters. http://img835.imageshack.us/img835/6181/pm1.jpg sweet.

But being how it is with all things Microsoft, apparently the .NET has been updated (scheduled security?) and messed with so many times. Everything I have previously compiled will no longer work. This hurts.

It's worse than a fragmented drive. It "feels" like an encrypted fragmented drive to me on a personal level... Guess the password to decrypt. I digress again.

I am going to show a series of Images and explain each.

CURRENT SCREENSHOT OF EXECUTING AND BYPASSING FIRST POP-UP ERROR.
http://img835.imageshack.us/img835/6181/pm1.jpg
This was my first success, you have to imaging how it originally looked by

Imagining this photo
http://www.codeproject.com/KB/audio-video/AudioLib/AudioLib.jpg

EXCEPT . . . it had the meter working on which ever audio source you've selected last. It remembered settings when you quit and faithfully restored them on start/restart.

Today when I try to start my "already compiled" application from several years back I get this garbage http://img834.imageshack.us/img834/9631/pm2.jpg

I can however click continue, and it does start.
Again: http://img835.imageshack.us/img835/6181/pm1.jpg

But then when I choose a mixer from either my Audigy2 ZS or my MBOX we arrive at the following hair puller.
http://img843.imageshack.us/img843/6492/pm3.jpg

Clicking continue. Makes me want to go get drunk...and use the computer for target practice...Can I borrow a rocket launcher please?
http://img841.imageshack.us/img841/3938/pm4.jpg

Yes your very perceptive, the volume is indeed still working/operating in the meter..,. But everything else is gone. Blagh... argh..

Now sadly, I got hit by a virus back in 2009, after searching for 6+ months, I finally came to the conclusion, I've lost my original modified source code. I had however backed up the install package I was rolling it out on workstations with. So I can at least install it. But clearly since this project started Microsoft has changed .NET so many times over, everything is laid to waste. No matter if you install it or not, it's not working properly.

I almost wish there was a side by side, but this is beyond comprehension for me.

Call me angry, call me sick, call me stupid, I admit it. I ain't the best coder, I am more like the worst, and so I really hate it when my time was wasted, so close but out of reach...

I do a lot of video and audio production, I am constantly messing with audio controls, I loved this project/solution because I had ALL settings REC/Play on one menu, the windows mixer is very annoying. It seems to me this project is way past time to be updated to MS VS 2010!! (In my opinion which this is) Looking at VS 2010 api examples for audio and mixers makes me want to start hating Microsoft with a real passion.

I've actually been trying to fix this now for about two years... The old website I found on archive.org for where he talks about mixers.

I BEG of you, please update this project/solution to VS 2010, and current versions of .NET

I don't care about WIN 7 and 64 bit. let them burn in hell..... okay just kidding.
First thing first, restore this project for XP 32 bit. Then, and only then Port it.

Boy I hate the lack of classic menu on that win 7 anyway.... But I digress..

I was trying to dump some SVideo + audio L and R to disk /AVI/Uncompressed and I occasionally run into a video that has been normalized or something funky by the factory, where every time I record it's too loud, and just needs a careful bump on the levels to correct it. Well, back when I had this application compiled and actually working when it executed, it made quick work of testing 5 second samples after making 1 change at a time to the recording levels. Windows Volume is garbage in comparison.

NOTE: when I run this application now, there are NO RECORDING levels at all !! Ack!! The opposite of my intent. I have the exe that you see in the screenshot, if you want it we can work something out, where I can get it to ya. But I rather see it fixed so I can try to re-hack the meters in again. My end goal was to have a meter for each thing...a group meter? ;o)

Okay, like I said, I guess I am ranting now. I ain't a good coder, I am real bad and by the time I "start" to learn one API, and roll out some tricks of my own, it's suddenly no good anymore because of security updates or whatever update cycle nonsense. I hate wasting my time, as I am sure YOU do as well, back when I was young, I might put 72 hours straight on something like this, but I can barely pay attention for 2 hours at a time now. I'm old and burned out.

Please help or redo this thing to today's standards. I have some half scripted VB6 stuff but man.. come on.. I ain't knocking the author. It something Microsoft did and we haven't called them to carpet on it.



-- Modified Sunday, July 18, 2010 11:43 PM
GeneralRe: C# Mixer Project needs massive update. Pin
CastorTiu19-Jul-10 11:57
CastorTiu19-Jul-10 11:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.