Click here to Skip to main content
15,860,861 members
Articles / Desktop Programming / MFC
Article

Volume Manipulation Classes

Rate me:
Please Sign up or sign in to vote.
4.78/5 (26 votes)
16 Nov 19992 min read 512K   4.9K   84   78
Volume manipulation classes.

Introduction

Many times my applications required audio volume manipulation. To make the volume-enabled application development easier, I decided to create a few C++ classes that would allow me to easily regulate and track the changes of such volume controls as Output Master Volume, WaveOut Volume and Input (WaveIn) Volume. Here I provide such classes that share a common interface (defined in IVolume.h):

  • bool IsAvailable() - Says whether the volume controlling is possible.
  • void Enable() - Enables the line of the volume control.
  • void Disable() - Disables the line of the volume control.
  • DWORD GetVolumeMetric() - Retrieves the granularity of volume.
  • DWORD GetMinimalVolume() - Retrieves the minimal volume that can be set.
  • DWORD GetMaximalVolume() - Retrieves the maximal volume that can be set.
  • DWORD GetCurrentVolume() - Retrieves the current volume.
  • void SetCurrentVolume( DWORD dwValue ) - Sets the volume.

And the last function allows to register a user-implemented callback that will be called as a notification of volume changes:

void RegisterNotificationSink( PONMICVOULUMECHANGE, DWORD )

This interface is implemented by CVolumeOutMaster (VolumeOutMaster.h/cpp), CVolumeOutWave (VolumeOutWave.h/cpp) and CVolumeInXXX (VolumeInXXX.h/cpp) classes. The usage of the classes is very simple:

In your StdAfx.h, include "mmSystem.h" and make sure you link to the "winmm.lib" (#pragma comment(lib, "winmm.lib")). Then, if you are going to use Output Mater volume control, include "VolumeOutMaster.h", say, to the StdAfx.h.

The IVolume.h, VolumeInXXX.h, VolumeInXXX.cpp are to be inserted as your project files.

...
void CALLBACK MasterVolumeChanged( DWORD dwCurrentVolume, DWORD dwUserValue );
...
// Volume control Initialization
IVolume* pMasterVolume = (IVolume*)new CVolumeOutMaster();
if ( !pMasterVolume || !pMasterVolume->IsAvailable() )
{
    // handle error
}
pMasterVolume->Enable();
pMasterVolume->RegisterNotificationSink( MasterVolumeChanged, dwAnyUserValue );
...
pMasterVolume->SetCurrentVolume( dwVolumeToSet );
...
DWORD dwCurrentVolume = pMasterVolume->SetCurrentVolume();
...
void CALLBACK MasterVolumeChanged( DWORD dwCurrentVolume, DWORD dwUserValue )
{
   // handle the volume change
}
...

Very simple, isn't it? Yet, the CVolumeInXXX class requires more explanation. In order to manipulate the Input volume, the source line index is to be passed to the constructor. Confused? Please, be not. CVolumeInXXX class provides a static function to enumerate those lines:

bool EnumerateInputLines( PINPUTLINEPROC, DWORD dwUserValue );

This allows you to manipulate the volume of any WaveIn-based lines. Say, you want to manipulate the microphone volume:

...
bool CALLBACK EnumInputLineProc( UINT uLineIndex, 
              MIXERLINE* pLineInfo, DWORD dwUserValue );
...
// Initialization
UINT uMicrophoneLineIndex = (UINT)-1;
if ( !CVolumeInXXX::EnumerateInputLines( EnumInputLineProc, 
                           (DWORD)&uMicrophoneLineIndex ) )
{
   // handle error
}
if ( uMicrophoneLineIndex == (UINT)-1 )
{
        // Error: mic volume'ing is not available.
}
IVolume* pMicrophoneVolume = 
         (IVolume*)new CVolumeInXXX( uMicrophoneLineIndex );
if ( !pMicrophoneVolume || !pMicrophoneVolume->IsAvailable() )
{
   // handle error
}
// Go on and use pMicrophoneVolume to manipulate the volume
...
bool CALLBACK EnumInputLineProc( UINT uLineIndex, 
              MIXERLINE* pLineInfo, DWORD dwUserValue )
{
    if ( pLineInfo->dwComponentType == 
             MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE )
    {
        *((UINT*)dwUserValue) = uLineIndex;
        return false;
    }
    return true;
}
...

Be aware, that for performance reasons it is better to have a single instance of a given class per application. So don't rush to create lots of CVolumeInXXX objects, better share the only one through your code.

Conclusion

The proposed classes do not encapsulate all the abilities exposed by the mixers. However, working with a mixer just to add a pretty simple functionality is quite boring. That's why, as I think, the proposed classes might be of some help to you.

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


Written By
Web Developer
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
SuggestionWindows 7 volume control sample Pin
Artem Moroz15-Dec-12 1:05
Artem Moroz15-Dec-12 1:05 
QuestionLicense? Pin
LuisVilla16-Feb-12 4:48
LuisVilla16-Feb-12 4:48 
AnswerRe: License? Pin
Alex Chmut16-Feb-12 10:15
Alex Chmut16-Feb-12 10:15 
GeneralControlling master volume in Win7 - IAudioEndpointVolume - Working sample code in MSDN Pin
Peter Heckler15-Jan-12 5:39
Peter Heckler15-Jan-12 5:39 
GeneralVolume Control in Windows7 Pin
Member 264083617-Aug-10 20:41
Member 264083617-Aug-10 20:41 
GeneralMaking compatible Pin
Sami Jadoon18-Jan-09 22:49
Sami Jadoon18-Jan-09 22:49 
QuestionWindows Vista Anyone??? Pin
{bill}1-Sep-08 9:41
{bill}1-Sep-08 9:41 
AnswerRe: Windows Vista Anyone??? Pin
Steven Dong9-Nov-08 4:37
Steven Dong9-Nov-08 4:37 
QuestionCallback Function Pin
peene9-Aug-07 5:46
peene9-Aug-07 5:46 
Questionhow can i control the sound of left and right speaker Pin
rajneshmalik1-Aug-07 21:49
rajneshmalik1-Aug-07 21:49 
GeneralProblem in 2000 Pin
lilesh26-Feb-07 22:56
lilesh26-Feb-07 22:56 
Your class work excellent with windows xp but there is some problem in 2000,
when i run program it give following messages which u have included.

error: CVolumeInXXX::EnumerateInputLines

error: uMicrophoneLineIndex = -1

error: !ob_MicroPhoneVolume || !ob_MicroPhoneVolume->IsAvailable()

plz tell me wht shall i do for this

QuestionBegginer's question Pin
lnenad12-Nov-06 8:12
lnenad12-Nov-06 8:12 
QuestionHigh Definition Audio Pin
Saber00119-Jul-06 0:09
Saber00119-Jul-06 0:09 
QuestionHow to use Volume Manipulation Classes Pin
castlezhen28-Apr-06 3:04
castlezhen28-Apr-06 3:04 
GeneralDiable Microphone Pin
anakia18-Apr-06 17:05
anakia18-Apr-06 17:05 
General[Q] Love your article and more... Pin
ysyoon17-Aug-05 5:52
ysyoon17-Aug-05 5:52 
GeneralRe: [Q] Love your article and more... Pin
ysyoon17-Aug-05 6:23
ysyoon17-Aug-05 6:23 
GeneralProblems with Microphone control Pin
Virendra Sharma25-May-05 23:29
Virendra Sharma25-May-05 23:29 
GeneralRe: Problems with Microphone control Pin
Fco Javier Lama3-May-06 23:24
Fco Javier Lama3-May-06 23:24 
Generaldoesn t work with a USB headset Pin
bartouze22-Apr-05 3:09
bartouze22-Apr-05 3:09 
GeneralProblem passing callback function in... Pin
el davo4-Mar-04 13:48
el davo4-Mar-04 13:48 
GeneralRe: Problem passing callback function in... Pin
laduran27-Aug-04 12:55
laduran27-Aug-04 12:55 
GeneralRe: Problem passing callback function in... Pin
Vinod Vijayan29-Jan-05 0:06
Vinod Vijayan29-Jan-05 0:06 
QuestionHow to determine whether volume is enabled? Pin
Artem Moroz22-Feb-04 9:54
Artem Moroz22-Feb-04 9:54 
GeneralMany Compile Errors - microphone implementation Pin
Bobboots12-Feb-04 19:19
Bobboots12-Feb-04 19:19 

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.