Introduction
Adding a volume control to an application seems like it should be an easy thing to do, enter the Windows Multimedia Audio API that enables a programmer to add audio services to an application. The audio mixer functions of this API are used to set an audio device's volume but there is a steep learning curve penalty waiting for the first time user. Although Vista provides a new and somewhat easier to use set of user-mode audio components, Microsoft has stated that it does not plan to make the Vista core audio APIs available for use with earlier versions of Windows such as XP. Since there is a large population of users still using XP and older Windows operating systems, a solution is needed that applies to all of these older systems as well.
Background
To address this problem, I created an API in the form of a small wrapper library that provides a straightforward way to programmatically interact with standard audio controls such as volume, balance, and mute. Using this API still requires some understanding of the terminology and basic concepts used in the mixer documentation.
Mixer: A Mixer combines (mixes), routes, and changes the levels and other characteristics of audio signal data. A system can have zero to several mixers.
Destination: Each mixer has one or more destinations, and each destination has zero to several controls and one or more connections.
Connection: A connection supplies audio data to a destination and has zero to several controls. There are also one or more channels per connection, if a connection has two channels, the volume of each channel may be controlled independently (balance).
Control: A control effects a change in the characteristics of audio signal data such as volume. Each control associated with a mixer has a system assigned unique ID, 0...N. A mixer with one destination that has two connections will have nine control IDs assigned to it numbered zero to eight assuming each connection and destination has three controls each. If there are three mixers, there will be three sets of control ID numbers, each set starting at zero.
The concept of a destination is somewhat confusing, but I find it useful to think of a destination as a receiver or consumer of data coming from the connections associated with it. The confusing part of this is that a destination may be an output device, such as a speaker, or an input device, such as a wave input device. A speaker is clearly an output device but a wave input device is clearly not an output device. The introductory part of the SDK documentation uses the term "audio line" to refer to both destinations and connections but the usage of this term is not consistent throughout the remainder of the documentation so I have avoided using it here.
The wrapper library mixer class, CMixer
, enumerates all destinations, connections, and controls associated with a mixer. It provides access to control labels and bounds data and read and write access to state data for each control. The following chart provides a clearer view of the relationships between mixer class components:
Mixer | A Mixer has a collection of Destinations |
Destination | A Destination has a collection of Connections and Controls |
Connection | A Connection has a collection of Controls |
Control | A Control has a collection of channels, typically two |
The CMixer
class draws on the support of two other classes, CMixerDestination
and CMixerControl
. The CMixerDestination
class manages data associated with a destination while the CMixerControl
class provides access to the state and metrics data of a control.
Using the Code
To fully use the CMixer
class, you will need to familiarize yourself with three SDK defined structures used by the class to provide information about mixer components:
- The
MIXERCAPS
structure describes the capabilities of a mixer device. - The
MIXERLINE
structure describes the state and metrics of a connection or destination. - The
MIXERCONTROL
structure describes the state and metrics of a single control for a connection or destination.
If you are interested in associating a Windows control with a mixer control, you will only need to refer to the MIXERCONTROL
structure definition in the SDK documentation as this structure contains the ID number, type, name, and bounds data for a control. The included VolumeControl
sample application is a simple MFC dialog application with a single volume control that is synchronized with the first volume control of the first mixer found in the system. In the case where a specific audio device, such as a wave in/out, MIDI in/out, or auxiliary device has already been opened, the CMixer
instance may be initialized using the device’s ID index value or opened handle.
The AudioDialog
sample MFC dialog application has been included to address the situation where more extensive mixer information is required. It enumerates all mixers in the system and allows the user to display data associated with any of the mixers, destinations, connections, and controls found. It also presents a collection of volume, balance, and mute check box control groups based on the user selected mixer and destination similar to the system provided Volume Control utility.
Build Notes
Both of the sample applications were built with Visual Studio 2005 as I felt that most people would at least have this version and that updating a project to a newer version of VS is much simpler than converting one to a previous version. Both applications were tested with Vista, XP, and 2K. The AudioDialog
application should be built first as it creates the mixer API library file used by the VolumeControl
application.
History