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.

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:

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.

About the Author

Comments and Discussions

Hi,
Your MasterVolume control works well. But microphone control doesn't work on Win-XP.
It shows following lines of error while debugging:

MasterOutputVolume: Initializing for Source MasterOut Line ..
.MasterOutputVolume: "Master Volume" Volume control for the Speakers Source Line adopted.
.MasterOutputVolume: Enabling Line: Speakers Line control "Master Mute"(0x20010002) has been set to 0.

Hi everybody. I discovered a problem selecting the desired input line under XP(for example, you want to select microphone, but the software selects another input line). I found that Windows XP enumerates the different input lines in inverse order. So, in XP you have to invert the order of input lines, and your new code will work!
Good luck !
FJLama.