Recording with Waveform Audio Devices

MCI supports recording with waveform audio devices. You can insert recorded information into an existing file or record into a new file. To record to an existing file, open a waveform device and device element as you would normally. To record into a new file, specify a zero-length filename for the device element when you open the device.

When MCI creates a new file for recording, the waveform data format is set to a default format specified by the device driver. To use a format other than the default format, you can use MCI_SET to change the format.

To begin recording, use the MCI_RECORD command along with the MCI_RECORD_PARMS parameter block. MMSYSTEM.H defines the MCI_RECORD_PARMS parameter block as follows:

typedef struct {
        DWORD        dwCallback;                        /* callback for MCI_NOTIFY flag */
        DWORD        dwFrom;                                /* record begin position */
        DWORD        dwTo;                                /* record end position */
} MCI_RECORD_PARMS;

If you record to an existing file, you can use the MCI_TO and MCI_FROM flags to specify beginning and ending insertion points for recording. For example, if you record to an existing file 20 seconds long, and you begin recording at 5 seconds and end recording at 10 seconds, you will have a recording 25 seconds long, as shown in the following illustration:

If you don't specify an ending position, recording continues until you send an MCI_STOP command, or until the driver runs out of free disk space. If you record to a new file, you can't use the MCI_FROM flag to specify a beginning position—recording always starts at the beginning of a new file. However, you can specify an end position to terminate recording when recording to a new file.

Note:

MCI does not support deleting or recording over portions of a recorded waveform. Applications such as waveform editors should be implemented using low-level audio functions.

Saving a Recorded File

When recording is complete, use the MCI_SAVE command along with the MCI_SAVE_PARMS parameter block to save the recording before closing the device. MMSYSTEM.H defines the MCI_SAVE_PARMS parameter block as follows:

typedef struct {
    DWORD   dwCallback;     /* callback for MCI_NOTIFY flag */
    LPSTR   lpfilename;     /* filename for saved file */
} MCI_SAVE_PARMS;

If you close the device without saving, the recorded data is lost.

Checking Input Levels

To get the level of the input signal before recording on a waveform input device, use the MCI_STATUS command. Specify the MCI_STATUS_ITEM flag and set dwItem in MCI_STATUS_PARMS to MCI_WAVE_STATUS_LEVEL. The average input signal level is returned in the dwReturn field of the MCI_STATUS_PARMS parameter block. The left-channel value is in the high-order word and the right- or mono-channel value is in the low-order word, as shown in the following illustration:

The input level is represented as an unsigned value. For 8-bit samples, this value ranges from 0 through 127 (0x7F). For 16-bit samples, it ranges from 0 through 32,767 (0x7FFF).

Example of Recording with a Waveform Audio Device

The following function opens a waveform audio device with a new file, records for the specified time, plays the recording, and prompts the user to see if the recording should be saved as a file:

/* Uses the MCI_OPEN, MCI_RECORD, MCI_SAVE commands to record and
 * save a waveform audio file. Returns 0L on success; otherwise,
 * it returns an MCI error code.
 */ 
DWORD recordWAVEFile(DWORD dwMilliSeconds)
{
    WORD wDeviceID;
    DWORD dwReturn;
    MCI_OPEN_PARMS mciOpenParms;
    MCI_RECORD_PARMS mciRecordParms;
    MCI_SAVE_PARMS mciSaveParms;
    MCI_PLAY_PARMS mciPlayParms;

    /* Open a waveform device with a new file for recording.
     */
    mciOpenParms.lpstrDeviceType = "waveaudio";
    mciOpenParms.lpstrElementName = "";
    if (dwReturn = mciSendCommand(0, MCI_OPEN,
                                  MCI_OPEN_ELEMENT | MCI_OPEN_TYPE,
                                  (DWORD)(LPVOID) &mciOpenParms))
    {
        /* Failed to open device; don't close it, just return error.
         */
        return (dwReturn);
    }

    /* Device opened successfully, get the device ID.
     */
    wDeviceID = mciOpenParms.wDeviceID;

    /* Begin recording and record for the specified number of milliseconds.
     * Wait for recording to complete before continuing. Assume the 
     * default time format for the waveform device (milliseconds).
     */
    mciRecordParms.dwTo = dwMilliSeconds;
    if (dwReturn = mciSendCommand(wDeviceID, MCI_RECORD, MCI_TO | MCI_WAIT,
                                  (DWORD)(LPVOID) &mciRecordParms))
    {
        mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
        return (dwReturn);
    }

    /* Play the recording and query user to save the file.
     */
    mciPlayParms.dwFrom = 0L;
    if (dwReturn = mciSendCommand(wDeviceID, MCI_PLAY,
                                  MCI_FROM | MCI_WAIT,
                                  (DWORD)(LPVOID) &mciPlayParms))
    {
        mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
        return (dwReturn);
    }
    if (MessageBox(hMainWnd, "Do you want to save this recording?",
                   "", MB_YESNO) == IDNO)
    {
        mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
        return (0L);
    }

    /* Save the recording to a file named "tempfile.wav". Wait for
     * the operation to complete before continuing.
     */
    mciSaveParms.lpfilename = "tempfile.wav";
    if (dwReturn = mciSendCommand(wDeviceID, MCI_SAVE,
                                  MCI_SAVE_FILE | MCI_WAIT,
                                  (DWORD)(LPVOID) &mciSaveParms))
    {
        mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
        return (dwReturn);
    }

    return (0L);
}