Playing Waveform-Audio Files

It's easy to play sounds in your application by using the functions, macros, and messages discussed in this overview. The techniques and elements documented here operate only on waveform audio; that is, digitized representations of a sound's physical shape. If you want to add music to your application, and you do not care about other kinds of sounds, you might want to use MIDI. For a discussion of a simple playback MIDI implementation, see the MCIWnd Window Class. For a discussion of the MIDI interface, see Musical Instrument Digital Interface (MIDI).

You can use the following functions to play waveform audio in your application in a single function call:

Plays the sound that corresponds to a specified system-alert level.
Plays the sound that corresponds to the system sound entered in the registry or the contents of the specified filename.
Provides all the functionality of sndPlaySound and can directly access resources.

The MessageBeep function is a standard part of the Win32 API; because its capabilities are very limited and it is documented elsewhere, it is not discussed here.

The functions listed provide the following methods of playing waveform audio:

  • Playing waveform-audio files associated with system-alert levels

  • Playing waveform-audio files specified by entries in the registry

  • Playing in-memory WAVE resources

  • Playing waveform-audio files stored on a hard disk or compact disc pics/MMEDIA00090000.gif read-only memory (CD-ROM)

The sndPlaySound and PlaySound functions load an entire waveform-audio file into memory and, in effect, limit the size of file they can play. Use sndPlaySound and PlaySound to play waveform-audio files that are relatively small pics/MMEDIA00090001.gif up to about 100K. These two functions also require the sound data to be in a format that is playable by one of the installed waveform-audio drivers, including the wave mapper.

For larger sound files, use the Media Control Interface (MCI) services. For more information, see MCI.

Using Window Messages to Manage Waveform-Audio Playback

The following messages can be sent to a window procedure function for managing waveform-audio playback.

Sent when the device is closed by using the waveOutClose function.
Sent when the device driver is finished with a data block sent by using the waveOutWrite function.
Sent when the device is opened by using the waveOutOpen function.

A wParam and lParam parameter is associated with each of these messages. The wParam parameter always specifies a handle of the open waveform-audio device. For the MM_WOM_DONE message, lParam specifies a pointer to a WAVEHDR structure that identifies the completed data block. The lParam parameter is unused for the MM_WOM_CLOSE and MM_WOM_OPEN messages.

The most useful message is probably MM_WOM_DONE. When this message signals that playback of a data block is complete, you can clean up and free the data block. Unless you need to allocate memory or initialize variables, you probably do not need to process the MM_WOM_OPEN and MM_WOM_CLOSE messages.

The callback function for waveform-audio output devices is supplied by the application. For information about this callback function, see the waveOutProc function.

Retrieving the Current Playback Position

You can monitor the current playback position within the file while waveform audio is playing by using the waveOutGetPosition function.

For waveform-audio devices, samples are the preferred time format in which to represent the current position. Thus, the current position of a waveform-audio device is specified as the number of samples for one channel from the beginning of the waveform-audio file. To query the current position of a waveform-audio device, set the wType member of the MMTIME structure to TIME_SAMPLES and pass this structure to waveOutGetPosition.

The MMTIME structure can represent time in one or more different formats, including milliseconds, samples, SMPTE (Society of Motion Picture and Television Engineers), and MIDI song pointer formats. The wType member specifies the format used to represent time. Before calling a function that uses the MMTIME structure, you must set wType to indicate your requested time format. Be sure to check wType after the call to see whether the requested time format is supported. If the requested time format is not supported, the device driver specifies the time in an alternate time format and changes the wType member to the selected time format.

For more information about the MMTIME structure, see Multimedia Timers.

Stopping, Pausing, and Restarting Playback

You can stop or pause playback while waveform audio is playing. After playback has been paused, you can restart it. Windows provides the following functions for controlling waveform-audio playback.

Pauses playback on a waveform-audio output device.
Stops playback on a waveform-audio output device and marks all pending data blocks as done.
Resumes playback on a paused waveform-audio output device.

Pausing a waveform-audio device by using waveOutPause might not be instantaneous; the driver may finish playing the current block before pausing playback.

Generally, as soon as the first waveform-audio data block is sent by using the waveOutWrite function, the waveform-audio device begins playing. If you do not want the sound to start playing immediately, call waveOutPause before calling waveOutWrite. Then, when you want to begin playing waveform-audio data, call waveOutRestart.

You cannot use waveOutRestart to restart a device that has been stopped with waveOutReset; you must use waveOutWrite to send the first data block to resume playback on the device.

Looping Playback

Looping a sound is controlled by the dwLoops and dwFlags members in the WAVEHDR structures passed to the device with the waveOutWrite function. Use the WHDR_BEGINLOOP and WHDR_ENDLOOP flags in the dwFlags member to specify the beginning and ending data blocks for looping.

To loop a single data block, specify both flags for the same block. To specify the number of loops, use the dwLoops member in the WAVEHDR structure for the first block in the loop.

You can call the waveOutBreakLoop function to stop a looping sound.

Changing the Volume of Waveform-Audio Playback

Windows provides the following functions to query and set the volume level of waveform-audio output devices.

Retrieves the current volume level of the specified waveform-audio output device.
Sets the volume level of the specified waveform-audio output device.

Not all waveform-audio devices support volume changes. Some devices support individual volume control on both the left and right channels. For information about how to determine the volume-control capabilities of waveform-audio devices, see Devices and Data Types.

Some applications allow the user to control the volume for all audio devices in a system. (Many applications of this type use the audio mixer services; for more information, see Audio Mixers.) Unless your application is capable of this kind of master volume control, you should open an audio device before changing its volume. You should also query the volume level before changing it and restore the volume level to its previous level as soon as possible.

Volume is specified in a doubleword value. When the audio format is stereo, the upper 16 bits specify the relative volume of the right channel and the lower 16 bits specify the relative volume of the left channel. For devices that do not support left- and right-channel volume control, the lower 16 bits specify the volume level, and the upper 16 bits are ignored.

Volume-level values range from 0x0 (silence) to 0xFFFF (maximum volume) and are interpreted logarithmically. The perceived volume increase is the same when increasing the volume level from 0x5000 to 0x6000 as it is from 0x4000 to 0x5000.

Changing Pitch and Playback Rate

Some waveform-audio output devices can vary the pitch and the playback rate of waveform-audio data. Not all waveform-audio devices support pitch and playback-rate changes. For information about how to determine whether a particular waveform-audio device supports pitch and playback rate changes, see Devices and Data Types.

The differences between changing pitch and playback rate are as follows:

  • Changing the playback rate is performed by the device driver and does not require specialized hardware. The sample rate is not changed, but the driver interpolates by skipping or synthesizing samples. For example, if the playback rate is changed by a factor of two, the driver skips every other sample.

  • Changing the pitch requires specialized hardware. The playback rate and sample rate are not changed.

Windows provides the following functions to query and set waveform-audio pitch and playback rates.

Retrieves the pitch for the specified waveform-audio output device.
Retrieves the playback rate for the specified waveform-audio output device.
Sets the pitch for the specified waveform-audio output device.
Sets the playback rate for the specified waveform-audio output device.

The pitch and playback rates are changed by a factor specified with a fixed-point number packed into a doubleword value. The upper 16 bits specify the integer part of the number; the lower 16 bits specify the fractional part. For example, the value 1.5 is represented as 0x00018000L. The value 0.75 is represented as 0x0000C000L. A value of 1.0 (0x00010000) means the pitch or playback rate is unchanged.

Software for developers
Delphi Components
.Net Components
Software for Android Developers
More information resources
Unix Manual Pages
Delphi Examples