Audio Volume Manipulation classes

-->

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 controling 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() - Retrieve the current volume
void SetCurrentVolume( DWORD dwValue ) - Set 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, 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.

Download demo project - 15 KB



Comments

  • How to use it on network

    Posted by Legacy on 10/07/2003 12:00am

    Originally posted by: Kanatbek Zaiitov

    Hi, greate work,
    but if you could, please,
    how to use this class to manipulate the sound on another computer?
    that is, how to set the volume on domain client computer to 0, upper?

    Reply
  • Yikes! BSOD!!

    Posted by Legacy on 08/27/2002 12:00am

    Originally posted by: MJPetro

    In attempting to implement, I receive a Blue Screen of Death (NT) within the CVolumeOutMaster::EnableLine() method, specifically on the call to mixerSetControlDetails() from, I believe, the MIXERCONTROL_CONTROLTYPE_MUX branch. Any ideas?

    Reply
  • nice work, but...

    Posted by Legacy on 08/20/2002 12:00am

    Originally posted by: josephliu48

    nice work, but with this program, i can't adjust microphone's volume to zero, Can anyone here tell me that 
    
    how to accomplish it.

    Reply
  • Thanks a lot

    Posted by Legacy on 07/17/2002 12:00am

    Originally posted by: Ruslan

    Great job, thank you very very much.

    Reply
  • Any ideas about the auxiliary?

    Posted by Legacy on 02/20/2002 12:00am

    Originally posted by: david

    Hi,
    I need to control both the Line in and the auxiliary in.
    The line in works fine, but the auxiliary- i cannot get it to work.

    Any ideas??

    David.

    Reply
  • Correction

    Posted by Legacy on 10/19/2001 12:00am

    Originally posted by: Greg James

    The class IVolume needs a virtual destructor:
    
    

    virtual ~IVolume(){};

    This is so ~CVolumeInXXX() will be called when you delete a pointer to the base class IVolume* as you have in the sample code.

    Reply
  • Not Work for some computer

    Posted by Legacy on 09/11/2001 12:00am

    Originally posted by: Oliver Leung


    I've used the code in my program to automatically enable the mic for recording and adjust the input volume of it. I've carried out test on different computer. The program works fine in 7 out of 10 computers, but for the remaining 3, the volume of mic can be set while the device next to mic is enabled (instead of the mic itself).

    It seems that the problem is not related to OS version, or types of computer (notebook or desktop)........ I am running out of ideas..... anyone got the same problem?

    Thank you.

    Oliver

    Reply
  • why mute volume in invalid in win2000?

    Posted by Legacy on 09/03/2001 12:00am

    Originally posted by: jadeking

    I use your class, Thank you very much.

    this class is normal in winnt, but mute microphone is invalid in win2000?

    why?

    Reply
  • Thanks a lot! Alex

    Posted by Legacy on 07/30/2001 12:00am

    Originally posted by: SangJin KIM

    Your classes really helped me.
    They work on Win95/98/NT40/2000 well with SB64, SB-LiveValue, Yamaha DS-XG, ESS Maestro, ESS 1868. However, don't work with ESS 1869 PCI. I don't know why.
    Anyway, Thanks a lot for your classes.

    SangJin KIM

    Reply
  • Awesome! You are the man!

    Posted by Legacy on 11/04/2000 12:00am

    Originally posted by: BRIAN V SHIFRIN

    Thank!

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • On-demand Event Event Date: September 17, 2014 Another day, another end-of-support deadline. You've heard enough about the hazards of not migrating to Windows Server 2008 or 2012. What you may not know is that there's plenty in it for you and your business, like increased automation and performance, time-saving technical features, and a lower total cost of ownership. Check out this webcast and join Rich Holmes, Pomeroy's practice director of virtualization, as he discusses the future state of your servers, …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds