80.4.4 Managing Waveform Recording

Once you open a waveform input device, you can begin recording waveform data. Waveform data is recorded into application-supplied buffers specified by a WAVEHDR data structure. This is the same data structure used for waveform playback described in “Writing Waveform Data,” earlier in this chapter. Memory for the WAVEHDR structure and its accompanying data buffer must be allocated and prepared, as shown in “Allocating and Preparing Audio Data Blocks,” earlier in this chapter.

Windows provides the following functions to manage waveform recording:

Function Description

waveInAddBuffer Sends a buffer to the device driver so it can be filled with recorded waveform data.
waveInReset Stops waveform recording and marks all pending buffers as done.
waveInStart Starts waveform recording.
waveInStop Stops waveform recording.

Use the waveInAddBuffer function to send data buffers to the device driver. As the buffers are filled with recorded waveform data, the application is notified with either a window message or with a callback message, depending on the flag specified when the device was opened.

Use the waveInStart function to begin recording. Before beginning recording, you should send at least one buffer to the driver, or incoming data might be lost. To stop waveform recording, use waveInStop.

Before closing the device using waveOutClose, call waveOutReset to mark any pending data blocks as being done.

80.4.4.1 Using Window Messages to Manage Waveform Recording

The following messages can be sent to a window procedure function for managing waveform recording:

Message Description

MM_WIM_CLOSE Sent when the device is closed using waveInClose.
MM_WIM_DATA Sent when the device driver is finished with a data buffer sent using waveInAddBuffer.
MM_WIM_OPEN Sent when the device is opened using waveInOpen.

There is a wParam and lParam parameter associated with each of these messages. The wParam parameter always specifies a handle to the open waveform device. The lParam parameter is unused for the MM_WIM_CLOSE and MM_WIM_OPEN messages.

For the MM_WIM_DATA message, lParam specifies a far pointer to a WAVEHDR structure that identifies the data buffer. This data buffer might not be completely filled with waveform data—recording can stop before the buffer is filled. Use the dwBytesRecorded field of the WAVEHDR structure to determine the amount of valid data present in the buffer.

The most useful message is MM_WIM_DATA. Unless you need to allocate memory or initialize variables, you probably don't need to use the MM_WIM_OPEN and MM_WIM_CLOSE messages. When the device driver is finished with a data block, you can clean up and free the data block as described in “Allocating and Preparing Audio Data Blocks,” earlier in this chapter.

80.4.4.2 Using a Low-Level Callback to Manage Waveform Recording

This syntax of the low-level callback function for waveform input devices is as follows:

void FAR PASCAL waveInCallback(hWaveIn, wMsg, dwInstance, dwParam1, dwParam2)

The following messages can be sent to the wMsg parameter of waveform input callback functions:

Message Description

WIM_CLOSE Sent when the device is closed using waveInClose.
WIM_OPEN Sent when the device is opened using waveInOpen.
WIM_DONE Sent when the device driver is finished with a data block sent using waveInAddBuffer.

These messages resemble messages sent to window-procedure functions, but their parameters are different. A handle to an open waveform device is passed as a parameter to the callback function, along with the DWORD of instance data that was passed using waveInOpen.

The callback has two message-dependent parameters: dwParam1 and dwParam2. For the WIM_CLOSE and WIM_OPEN messages, these parameters are not used. For the WIM_DONE message, dwParam1 specifies a far pointer to a WAVEHDR structure identifying the completed data block and dwParam2 is not used.

After the driver is finished with a data block, you can clean up and free the data block. Because of the restrictions of low-level audio callback functions, you can't do this within the callback. You must set some semaphores and do this outside of the callback. See “Using a Callback Function to Process Driver Messages,” earlier in this chapter, for details on the restrictions on using callback functions.