Click here to Skip to main content
11,487,401 members (70,568 online)
Click here to Skip to main content

A simple record and playback volume control class

, 27 Oct 2001 227.4K 3.2K 48
Rate this:
Please Sign up or sign in to vote.
A class to make setting the record and playback volume easier
<!-- Download Links --> <!-- Main HTML starts here -->

Introduction

Sometimes we need to control the volume of our soundcard and Microsoft has provided an API waveOutSetVolume() to do this. Unfortunately this can only set the playback volume. When we want to set the volume of other lines such as mic or MIDI or the line-in for recording, there is NO API to help!

At first I thought that DirectMedia may provide an interface to do this, and it does, but after I coded it and tested, the result is not so good. The interface IAMAudioInputMixer can only handle the record, not the playback, and most of all:

"The name of each pin, such as "Line in" or "Microphone", reflects the type of input"

but the name is not the same on different machines!

eg:
I want to set the volume of the microphone, so I find the pin by name "Microphone" and control it, it works on my computer. When I tested it at another machine, it failed because the name of the pin is "Mic Volume"!

I tried many ways and at last I worked out how to do it using MIXER.

There may be some people that have had a headache over the same quetion, so I released my solution. I hope it helps you.

Usage

  1. include the Mixer.h and Mixer.cpp into your project;
  2. add code like this:
      CMixer mixer(MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE, CMixer::Record);
    
      ......
      mixer.GetVolume();
      mixer.SetVolume(...);
    

Remarks

The constructor takes two parameters, the first is ComponentType from MIXERLINE (see MSDN for all possible values), and the second is an enum type, which can be Record or Play. The above controls the record (waveIn) volume, you can also control the playback (waveout) volume using:

CMixer mixer(MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE, CMixer::Play);

Notice that there is no default constructor takes no parameters, so if you use it in a C++ class, you should code it like this:

// MyClass.h
//////////////////////////
class CMixer;
class CMyClass
{
  CMyClass();
private:
  CMixer m_mixer;
....
}

//MyClass.cpp
///////////////////////////
CMyClass::CMyClass():m_mixer(MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE, CMixer::Play)
{
}
....

if you have any suggestion or improvement, plz let me know: whoo@isWhoo.com

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Whoo
Architect
China China
No Biography provided

Comments and Discussions

 
QuestionIs error? Pin
yangzmpang@22-Aug-10 21:54
memberyangzmpang@22-Aug-10 21:54 
GeneralCMixer constructor error Pin
anandveerappan5-Mar-10 0:24
memberanandveerappan5-Mar-10 0:24 
GeneralAnother Code Project article on this topic Pin
daluu5-Sep-07 10:06
memberdaluu5-Sep-07 10:06 
GeneralPlease, I need help Pin
wanhaven27-Feb-07 5:00
memberwanhaven27-Feb-07 5:00 
GeneralConversion error Pin
sraigiuz25-Jan-07 23:44
membersraigiuz25-Jan-07 23:44 
GeneralThe archive file is not avaible ... Pin
jere44trial@yahoo.fr29-Nov-06 6:28
memberjere44trial@yahoo.fr29-Nov-06 6:28 
QuestionHow to choose FrontPanel MIC or BackPanel MIC? Pin
guzeliang9-Oct-06 22:48
memberguzeliang9-Oct-06 22:48 
AnswerRe: How to choose FrontPanel MIC or BackPanel MIC? Pin
knightriderjon31-May-07 0:21
memberknightriderjon31-May-07 0:21 
GeneralRecord Volume Control on Vista OS Pin
varungarg25-Jul-06 20:01
membervarungarg25-Jul-06 20:01 
QuestionAdjusting Record Volume Pin
~Jabeen~22-Jun-06 21:46
member~Jabeen~22-Jun-06 21:46 
AnswerRe: Adjusting Record Volume [modified] Pin
Martin Skibye25-Mar-07 22:14
memberMartin Skibye25-Mar-07 22:14 
GeneralMixer.obj : error LNK2001 Pin
LowFly23-Nov-05 4:21
memberLowFly23-Nov-05 4:21 
GeneralIt was a valiant effort, but... Pin
Prodelos15-Jun-05 6:01
memberProdelos15-Jun-05 6:01 
GeneralRe: It was a valiant effort, but... Pin
koehler10-Feb-06 3:28
memberkoehler10-Feb-06 3:28 
GeneralCMixer class to controll multiple cards in one system Pin
sujudavid2-Mar-05 1:30
membersujudavid2-Mar-05 1:30 
GeneralRe: CMixer class to controll multiple cards in one system Pin
Prodelos15-Jun-05 4:35
memberProdelos15-Jun-05 4:35 
GeneralThank you very much Pin
niukaimin27-Jan-05 17:45
memberniukaimin27-Jan-05 17:45 
GeneralComawhite is right. Pin
Whoo17-Dec-04 2:52
memberWhoo17-Dec-04 2:52 
QuestionHow do you SELECT the Control Pin
ckathrani16-Dec-04 11:17
memberckathrani16-Dec-04 11:17 
AnswerRe: How do you SELECT the Control Pin
daluu5-Sep-07 9:50
memberdaluu5-Sep-07 9:50 
AnswerRe: How do you SELECT the Control Pin
Martin Skibye25-Feb-08 21:37
memberMartin Skibye25-Feb-08 21:37 
One way of selecting a component in "Recording Control" is this:

/// CODE START ///

void setInputSel(long compType)
{
     HMIXER                                       hMixer;
     MMRESULT                                    result;
     MIXERLINE                                 ml               = {0};
     MIXERCONTROL                              mc               = {0};
     MIXERLINECONTROLS                     mlc               = {0};
     MIXERCONTROLDETAILS                  mcd               = {0};

     DWORD dwi;
     DWORD m_dwControlType, m_dwSelectControlID, m_dwMultipleItems;

     result = mixerOpen(&amp;hMixer, MIXER_OBJECTF_MIXER, 0, 0, 0);
     if (result == MMSYSERR_NOERROR)
     {
          // get dwLineID
          ml.cbStruct = sizeof(MIXERLINE);
          ml.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;     //"Recording Control"

          result = mixerGetLineInfo((HMIXEROBJ) hMixer, &amp;ml, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE);
          if (result == MMSYSERR_NOERROR)
          {
               // try MUX
               m_dwControlType = MIXERCONTROL_CONTROLTYPE_MUX;
               mlc.cbStruct = sizeof(MIXERLINECONTROLS);
               mlc.dwLineID = ml.dwLineID;
               mlc.dwControlType = MIXERCONTROL_CONTROLTYPE_MUX;
               mlc.cControls = 1;
               mlc.cbmxctrl = sizeof(MIXERCONTROL);
               mlc.pamxctrl = &amp;mc;

               result = mixerGetLineControls((HMIXEROBJ) hMixer, &amp;mlc, MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE);
               if (result != MMSYSERR_NOERROR)
               {
                    return;
               }

               // store dwControlID, cMultipleItems
               m_dwSelectControlID = mc.dwControlID;
               m_dwMultipleItems = mc.cMultipleItems;

               // get the index of the component type Select control
               MIXERCONTROLDETAILS_LISTTEXT *pmcdSelectText = new MIXERCONTROLDETAILS_LISTTEXT[m_dwMultipleItems];

               if (pmcdSelectText != NULL)
               {
                    MIXERCONTROLDETAILS mcd;
                    mcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
                    mcd.dwControlID = m_dwSelectControlID;
                    mcd.cChannels = 1;
                    mcd.cMultipleItems = m_dwMultipleItems;
                    mcd.cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXT);
                    mcd.paDetails = pmcdSelectText;

                    result = mixerGetControlDetails((HMIXEROBJ) hMixer,     &amp;mcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_LISTTEXT);
                    if (result == MMSYSERR_NOERROR)
                    {
                         // Run through the list of the recording components to find the array element (dwi) for the componentType
                         for (dwi = 0; dwi &lt; m_dwMultipleItems; dwi++)
                         {
                              // get the line information
                              MIXERLINE ml;
                              ml.cbStruct = sizeof(MIXERLINE);
                              ml.dwLineID = pmcdSelectText[dwi].dwParam1;

                              result = mixerGetLineInfo((HMIXEROBJ) hMixer, &amp;ml, MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_LINEID);
                              if (result == MMSYSERR_NOERROR &amp;&amp; ml.dwComponentType == compType)
                              {
                                   // found, dwi is the index.
                                   break;
                              }
                         }
                    }
                    delete []pmcdSelectText;
               }
               // get all the values first
               MIXERCONTROLDETAILS_BOOLEAN *pmcdSelectValue = new MIXERCONTROLDETAILS_BOOLEAN[m_dwMultipleItems];

               if (pmcdSelectValue != NULL)
               {
                    MIXERCONTROLDETAILS mcd;
                    mcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
                    mcd.dwControlID = m_dwSelectControlID;
                    mcd.cChannels = 1;
                    mcd.cMultipleItems = m_dwMultipleItems;
                    mcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
                    mcd.paDetails = pmcdSelectValue;

                    result = mixerGetControlDetails((HMIXEROBJ) hMixer, &amp;mcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE);
                    if (result == MMSYSERR_NOERROR)
                    {
                         // Check if m_dwControlType has a valid value:
                         assert(m_dwControlType == MIXERCONTROL_CONTROLTYPE_MUX);

                         // MUX restricts the line selection to one source line at a time.
                         ZeroMemory(pmcdSelectValue, m_dwMultipleItems * sizeof(MIXERCONTROLDETAILS_BOOLEAN));

                         // set the component type value
                         pmcdSelectValue[dwi].fValue = 1;

                         mcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
                         mcd.dwControlID = m_dwSelectControlID;
                         mcd.cChannels = 1;
                         mcd.cMultipleItems = m_dwMultipleItems;
                         mcd.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
                         mcd.paDetails = pmcdSelectValue;

                         result = mixerSetControlDetails((HMIXEROBJ) hMixer,     &amp;mcd, MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE);
                         int test = 0;
                    }
                    delete []pmcdSelectValue;
               }
          }
          mixerClose(hMixer);
     }
}

/// CODE END ///

This function is to be called with the component to be selected (e.g.   MIXERLINE_COMPONENTTYPE_SRC_LINE ("Line In")).

Greetings,
Martin Skibye

Vivir con miedo es como vivir a medias!
Generalmicrophone record volume Pin
Anonymous15-Dec-04 18:41
sussAnonymous15-Dec-04 18:41 
GeneralLink doesn't work Pin
ramontxu6-Jul-04 3:08
memberramontxu6-Jul-04 3:08 
GeneralRe: Link doesn't work Pin
oyljerry8-Nov-04 3:07
memberoyljerry8-Nov-04 3:07 
GeneralPlayback Pin
whacker30-Jun-04 9:41
memberwhacker30-Jun-04 9:41 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150520.1 | Last Updated 28 Oct 2001
Article Copyright 2001 by Whoo
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid