Topic : Low level Digital Audio API
Author : Unknown
Page : 1 Next >>
Go to page :


Using the Low level Digital Audio API, you need to first call waveOutOpen() or waveInOpen() to open some Digital Audio device for output (use its Digital to Analog Converter to play audio) or input (use its Analog to Digital Converter to record audio) respectively.
In order to write out Digital Audio data to a particular device's DAC, you need to first call waveOutOpen() once, passing it the Device ID of that desired device. Then, you can subsequently call a function to send blocks of Digital Audio data to that device's DAC. One of the other parameters you pass is a pointer to a WAVEFORMATEX structure. You fill in the fields of this structure (prior to calling waveOutOpen) to tell the device such things as the sample rate and bit resolution of the digital audio data you intend to play, as well as whether it is Mono (1 channel) or stereo (2 channels).

In order to read incoming Digital Audio data from a particular device's ADC, you need to first call waveInOpen() once, passing it the Device ID of that desired device. Then, Windows will subsequently pass your program blocks of incoming Digital Audio from that device's ADC. One of the other parameters you pass is a pointer to a WAVEFORMATEX structure. You fill in the fields of this structure (prior to calling waveInOpen) to tell the device such things what sample rate and bit resolution to use when recording the digital audio data, as well as whether to record in Mono (1 channel) or stereo (2 channels).

After you're done recording or playing Digital Audio on a device (and have no further use for it), you must close that device.

Think of a Digital Audio device like a file. You open it, you read or write to it, and then you close it.

Easy way to choose a Digital Audio device for input or output
How does your program choose a Digital Audio device for input or output? There are several different approaches you can take, depending upon how fancy and flexible you want your program to be.
Recall that Windows maintains separate lists of the devices which are capable of recording Digital Audio data, and the devices capable of playing Digital Audio data. Pass the value WAVE_MAPPER as the Device ID to open the "preferred" Digital Audio Input device and Digital Audio Output device respectively. So, if you simply want to open the preferred Digital Audio Output device, then use a Device ID of WAVE_MAPPER with waveOutOpen() as so:

unsigned long result;
HWAVEOUT      outHandle;
WAVEFORMATEX  waveFormat;

/* Initialize the WAVEFORMATEX for 16-bit, 44KHz, stereo */
waveFormat.wFormatTag = WAVE_FORMAT_PCM;
waveFormat.nChannels = 2;
waveFormat.nSamplesPerSec = 44100;
waveFormat.wBitsPerSample = 16;
waveFormat.nBlockAlign = waveFormat.nChannels * (waveFormat.wBitsPerSample/8);
waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
waveFormat.cbSize = 0;

/* Open the preferred Digital Audio Out device. Note: myWindow is a handle to some open window */
result = waveOutOpen(&outHandle, WAVE_MAPPER, &waveFormat, (DWORD)myWindow, 0, CALLBACK_WINDOW);
if (result)
{
   printf("There was an error opening the preferred Digital Audio Out device!\r\n");
}


Note: If the preferred device does not support your desired choice of sample rate and channels, then Windows will instead open some other device that does (assuming that there is such other device available).
Of course, if the user has no device installed capable of outputting or playing Digital Audio data, the above call returns an error, so always check that return value.

Likewise, use a Device ID of WAVE_MAPPER with waveInOpen() to open the preferred Digital Audio Input device. (Note that these two preferred devices may or may not be components of the same card. But that is irrelevant to your purposes. The only caveat is that if they are components upon the same card, the card's driver needs to be full duplex in order to simultaneously open both the Digital Audio input and output. In this way, your program can play back previously recorded waveforms while recording new waveforms. Without a full duplex driver, you have to open for recording, record a waveform, close the device using waveInClose(), and open for playback. Some sound card designs do not allow the card to simultaneously record and play digital audio, so they have only half duplex drivers).

unsigned long result;
HWAVEIN       inHandle;
WAVEFORMATEX  waveFormat;

/* Initialize the WAVEFORMATEX for 16-bit, 44KHz, stereo */
waveFormat.wFormatTag = WAVE_FORMAT_PCM;
waveFormat.nChannels = 2;
waveFormat.nSamplesPerSec = 44100;
waveFormat.wBitsPerSample = 16;
waveFormat.nBlockAlign = waveFormat.nChannels * (waveFormat.wBitsPerSample/8);
waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
waveFormat.cbSize = 0;

/* Open the preferred Digital Audio In device */
result = waveInOpen(&inHandle, WAVE_MAPPER, &waveFormat, (DWORD)myWindow, 0, CALLBACK_WINDOW);
if (result)
{
   printf("There was an error opening the preferred Digital Audio In device!\r\n");
}

So what actually is the preferred Digital Audio Output device? Well, that's whatever device that the user choose from the dropdown list of Digital Audio Output devices under "Playback" of Control Panel's Multimedia utility (ie, on the "Audio" page). The list on this page is Windows actually displaying all of the names that were added to its list of devices capable of outputting or playing Digital Audio data.

The preferred Digital Audio Input device is whatever device that the user chooses from the dropdown list of Digital Audio Input devices under "Recording" of Control Panel's Multimedia utility (ie, on the "Audio" page). The list on this page is Windows actually displaying all of the names that were added to its list of devices capable of inputting or recording Digital Audio data.

The most flexible way to choose a Digital Audio device
The most flexible way would be to present the user with all of the names in the list of Digital Audio Output devices and let him choose which ones he wants (or if your program supports multiple Digital Audio output devices, you may wish to let him pick out several names from the list, and assign each digital audio "track" to one of those Device IDs. This is how professional sequencers implement support for multiple cards/outputs, in addition to perhaps implementing virtual tracks).
Whereas Windows maintains separate lists of Digital Audio Input and Output devices, so too, Windows has separate functions for querying the devices in each list.

Windows has a function that you can call to determine how many device names are in the list of devices that support outputting or playing Digital Audio data. This function is called waveOutGetNumDevs(). This returns the number of devices in the list. Remember that the Device IDs start with 0 and increment. So if Windows says that there are 3 devices in the list, then you know that their Device IDs are 0, 1, and 2 respectively. You then use these Device IDs with other Windows functions. For example, there is a function you can call to get information about one of the devices in the list, for example its name, and what sort of other features it has such as what sample rates it supports. You pass the Device ID of the device which you want to get information about (as well as a pointer to a special structure called a WAVEOUTCAPS into which Windows puts the info about the device), The name of the function to get information about a particular Digital Audio Output device is waveOutGetDevCaps().

Here then is an example of going through the list of Digital Audio Output devices, and printing the name of each one:

WAVEOUTCAPS     woc;
unsigned long   iNumDevs, i;

/* Get the number of Digital Audio Out devices in this computer */
iNumDevs = waveOutGetNumDevs();

/* Go through all of those devices, displaying their names */
for (i = 0; i < iNumDevs; i++)
{
    /* Get info about the next device */
    if (!waveOutGetDevCaps(i, &woc, sizeof(WAVEOUTCAPS)))
    {
        /* Display its Device ID and name */
        printf("Device ID #%u: %s\r\n", i, woc.szPname);
    }
}


Likewise with Digital Audio Input devices, Windows has a function that you can call to determine how many device names are in the list of devices that support inputting or recording Digital Audio data. This function is called waveInGetNumDevs(). This returns the number of devices in the list. Again, the Device IDs start with 0 and increment. There is a function you can call to get information about one of the devices in the list, for example its name, and what sort of other features it has such as what sample rates it supports. You pass the Device ID of the device which you want to get information about (as well as a pointer to a special structure called a WAVEINCAPS into which Windows puts the info about the device), The name of the function to get information about a particular Digital Audio Input device is waveInGetDevCaps().

Here then is an example of going through the list of Digital Audio Input devices, and printing the name of each one:

WAVEINCAPS     wic;
unsigned long  iNumDevs, i;

/* Get the number of Digital Audio In devices in this computer */
iNumDevs = waveInGetNumDevs();

/*


Page : 1 Next >>