Querying Waveform Output Devices

Before playing a waveform, you should call the waveOutGetDevCaps function to determine the waveform output capabilities of the playback device, as described earlier in this chapter. This function takes a pointer to a WAVEOUTCAPS structure, which it fills with information about the capabilities of a given device. This information includes the manufacturer and product IDs, a product name for the device, and the version number of the device driver.

In addition, the WAVEOUTCAPS structure provides information on the standard waveform formats and features supported by the device driver. The MMSYSTEM.H header file defines WAVEOUTCAPS as follows:

typedef struct waveoutcaps_tag {
  WORD  wMid;                                                /* manufacturer ID */
  WORD  wPid;                                                /* product ID */
  VERSION vDriverVersion;                        /* driver version */
  char  szPname[MAXPNAMELEN];                /* product name */
  DWORD  dwFormats;                                        /* supported standard formats */
  WORD  wChannels;                                        /* number of channels */
  DWORD  dwSupport;                                        /* supported features */
} WAVEOUTCAPS;

Determining Standard Format Support

The dwFormats field of the WAVEOUTCAPS structure specifies the standard waveform formats supported by a device. The MMSYSTEM.H header file defines the following standard waveform format identifiers for the dwFormats field:

Format Identifier Waveform Format

WAVE_FORMAT_1M08 8-bit mono at 11.025 kHz
WAVE_FORMAT_1S08 8-bit stereo at 11.025 kHz
WAVE_FORMAT_1M16 16-bit mono at 11.025 kHz
WAVE_FORMAT_1S16 16-bit stereo at 11.025 kHz
WAVE_FORMAT_2M08 8-bit mono at 22.05 kHz
WAVE_FORMAT_2S08 8-bit stereo at 22.05 kHz
WAVE_FORMAT_2M16 16-bit mono at 22.05 kHz
WAVE_FORMAT_2S16 16-bit stereo at 22.05 kHz
WAVE_FORMAT_4M08 8-bit mono at 44.1 kHz
WAVE_FORMAT_4S08 8-bit stereo at 44.1 kHz
WAVE_FORMAT_4M16 16-bit mono at 44.1 kHz
WAVE_FORMAT_4S16 16-bit stereo at 44.1 kHz

The dwFormats field is a logical OR of the flags listed above. For example, to determine if a device supports a waveform format of 16-bit stereo at 44.1 kHz, use this technique:

if(waveOutCaps.dwFormats & WAVE_FORMAT_4S16)
        /* Format is supported */
else
        /* Format is not supported */

This information on standard-format support also applies to the WAVEINCAPS structure used with waveform input devices. For information on the WAVEINCAPS structure, see “Querying Waveform Input Devices,” later in this chapter.

To determine if a specific format is supported by a device (as opposed to all standard formats supported by a device), use the waveOutOpen function with the WAVE_FORMAT_QUERY flag as shown in the next section.

Determining Non-Standard Format Support

Waveform devices can support non-standard formats not listed in the preceding table. To see if a particular format (standard or non-standard) is supported by a device, you can call waveOutOpen with the WAVE_FORMAT_QUERY flag. The WAVE_FORMAT_QUERY flag tells waveOutOpen to check if the requested format is supported. The wave device is not actually opened. The requested format is specified by the structure pointed to by the lpFormat parameter passed to waveOutOpen. For information about setting up this structure, see “Specifying Waveform Data Formats,” later in this chapter. The following code fragment uses this technique to determine if a given waveform device supports a given format:

/* Determines if the given waveform output device supports a given wave-
 * form format. Returns 0 if the format is supported, WAVEERR_BADFORMAT
 * if the format is not supported, and one of the MMSYSERR_ error codes if
 * there are other errors encountered in opening the given waveform device.
 */
WORD IsFormatSupported(LPPCMWAVEFORMAT lpPCMWaveFormat, WORD wDeviceID)
{
    return (waveOutOpen(
            NULL,                           // ptr can be NULL for query
            wDeviceID,                      // the device ID
            (LPWAVEFORMAT)lpPCMWaveFormat,  // defines requested format
            NULL,                           // no callback
            NULL,                           // no instance data
            WAVE_FORMAT_QUERY));            // query only, don't open device
}

This technique to determine non-standard format support also applies to waveform input devices. The only difference is that the waveInOpen function is used in place of waveOutOpen to query for format support.

Note:

To determine if a particular waveform-data format is supported by any of the waveform devices in a system, use the technique illustrated in the previous example, but specify the WAVE_MAPPER constant for the wDeviceID parameter. See “Selecting a Waveform Output Device,” later in this chapter, for more information on using the WAVE_MAPPER constant.

Determining Capabilities of Waveform Output Devices

Waveform output devices vary in the capabilities they support. The dwSupport field of the WAVEOUTCAPS structure indicates whether a given device supports capabilities such as volume and pitch changes. MMSYSTEM.H defines the following flags for the dwSupport field:

Flag Description

WAVECAPS_PITCH Pitch-change support
WAVECAPS_PLAYBACKRATE Playback-rate-change support
WAVECAPS_VOLUME Volume-control support
WAVECAPS_LRVOLUME Individual volume-control support for both left and right channels

The dwSupport field is a logical OR of the flags listed in the preceding table. For example, to determine if a device supports volume changes, use this technique:

if(waveOutCaps.dwSupport & WAVECAPS_VOLUME)
        /* Volume changes are supported */
else
        /* Volume changes are not supported */

For more information on playback volume levels, see “Changing Waveform Playback Volume,” later in this chapter. For more information on pitch and playback rates, see “Changing Pitch and Playback Rates,” also later in this chapter.