Solved

Sound Recording

Posted on 1998-07-15
3
348 Views
Last Modified: 2013-11-20
I am working with Visual C++ 4.2 and  WindowsNT 4.0 on a P233.
I want to implement an MFC application which record and play sounds. I would like to be able to :
- record a sound
- to play it and stop it
- to be able to reach any particular time in the audio file
The sound I want to record comes from a microphone plugged into the PC.
 Could anyone tell me what are the available functions and how to integrate it in my application?
Thanks.
0
Comment
Question by:Nicolas060297
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
3 Comments
 
LVL 2

Expert Comment

by:lucidity
ID: 1319217
Check out the DirectX SDK, it has lots of examples for using Direct Input (which is handy for this kind of thing).
0
 
LVL 23

Accepted Solution

by:
chensu earned 200 total points
ID: 1319218
There are several methods.
1. The easiest way is to use MCI commands or MCIWnd Window Class. Here is an example for recording copied from the Platform SDK documentation. There are some samples for MCI playing in Visual C++ samples.

Recording with a Waveform-Audio Device
The following example opens a waveform-audio device with a new file, records for the specified time, plays the recording, and prompts the user to save the recording if desired.

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

    // Open a waveform-audio 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);
    }

    // The 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-audio 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);
}


2. Use low-level audio functions waveIn* and waveOut* functions.
Sample: "Reverse: Play a Waveform in Reverse" for playing. Here is an example for recording copied from the Platform SDK documentation.

Example of Writing Waveform Data
The following example illustrates the steps required to allocate and set up a WAVEHDR structure and write a block of data to a waveform output device.

// Global variables.

HANDLE hData  = NULL;  // handle of waveform data memory
HPSTR  lpData = NULL;  // pointer to waveform data memory
 
void WriteWaveData(void)
{
    HWAVEOUT    hWaveOut;
    HGLOBAL     hWaveHdr;
    LPWAVEHDR   lpWaveHdr;
    HMMIO       hmmio;
    UINT        wResult;
    HANDLE      hFormat;
    WAVEFORMAT  *pFormat;
    DWORD       dwDataSize;

    // Open a waveform device for output using window callback.

    if (waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER,
                    (LPWAVEFORMAT)pFormat,
                    (LONG)hwndApp, 0L, CALLBACK_WINDOW))
    {
        MessageBox(hwndApp,
                   "Failed to open waveform output device.",
                   NULL, MB_OK | MB_ICONEXCLAMATION);
        LocalUnlock(hFormat);
        LocalFree(hFormat);
        mmioClose(hmmio, 0);
        return;
    }
 
    // Allocate and lock memory for the waveform data.
 
    hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, dwDataSize );
    if (!hData)
    {
        MessageBox(hwndApp, "Out of memory.",
                   NULL, MB_OK | MB_ICONEXCLAMATION);
        mmioClose(hmmio, 0);
        return;
    }
    if ((lpData = GlobalLock(hData)) == NULL)
    {
        MessageBox(hwndApp, "Failed to lock memory for data chunk.",
                   NULL, MB_OK | MB_ICONEXCLAMATION);
        GlobalFree(hData);
        mmioClose(hmmio, 0);
        return;
    }
 
    // Read the waveform data subchunk.
 
    if(mmioRead(hmmio, (HPSTR) lpData, dwDataSize) != (LRESULT)dwDataSize)
    {
        MessageBox(hwndApp, "Failed to read data chunk.",
                   NULL, MB_OK | MB_ICONEXCLAMATION);
        GlobalUnlock(hData);
        GlobalFree(hData);
        mmioClose(hmmio, 0);
        return;
    }
 
    // Allocate and lock memory for the header.

    hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
        (DWORD) sizeof(WAVEHDR));
    if (hWaveHdr == NULL)
    {
        GlobalUnlock(hData);
        GlobalFree(hData);
        MessageBox(hwndApp, "Not enough memory for header.",
            NULL, MB_OK | MB_ICONEXCLAMATION);
        return;
    }
 
    lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr);
    if (lpWaveHdr == NULL)
    {
        GlobalUnlock(hData);
        GlobalFree(hData);
        MessageBox(hwndApp,
            "Failed to lock memory for header.",
            NULL, MB_OK | MB_ICONEXCLAMATION);
        return;
    }
 
    // After allocation, set up and prepare header.
 
    lpWaveHdr->lpData = lpData;
    lpWaveHdr->dwBufferLength = dwDataSize;
    lpWaveHdr->dwFlags = 0L;
    lpWaveHdr->dwLoops = 0L;
    waveOutPrepareHeader(hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
 
    // Now the data block can be sent to the output device. The
    // waveOutWrite function returns immediately and waveform
    // data is sent to the output device in the background.
 
    wResult = waveOutWrite(hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
    if (wResult != 0)
    {
        waveOutUnprepareHeader(hWaveOut, lpWaveHdr,
                               sizeof(WAVEHDR));
        GlobalUnlock( hData);
        GlobalFree(hData);
        MessageBox(hwndApp, "Failed to write block to device",
                   NULL, MB_OK | MB_ICONEXCLAMATION);
        return;
    }
}

Processing the MM_WOM_DONE Message
The following example shows how to process the MM_WOM_DONE message. This example assumes the application does not play multiple data blocks, so it can close the output device after playing a single data block.

// WndProc--Main window procedure.
LRESULT FAR PASCAL WndProc(HWND hWnd, UINT msg, WPARAM wParam,
    LPARAM lParam)
{
switch (msg)
{
    case MM_WOM_DONE:
 
    // A waveform-audio data block has been played and
    // can now be freed.
    waveOutUnprepareHeader((HWAVEOUT) wParam,
        (LPWAVEHDR) lParam, sizeof(WAVEHDR) );
   
    // Free hData memory.
   
    waveOutClose((HWAVEOUT) wParam);
    break;
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}


3. Use DirectX 5 or later which come with IDirectSound and IDirectSoundCapture interfaces. There are a lot of samples in the SDK.

By the way, DirectInput provides support for input devices including the mouse, keyboard, and joystick, as well as for force-feedback (input/output) devices, but not sound devices.
0
 

Author Comment

by:Nicolas060297
ID: 1319219
Thanks for your answer.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
There are cases when e.g. an IT administrator wants to have full access and view into selected mailboxes on Exchange server, directly from his own email account in Outlook or Outlook Web Access. This proves useful when for example administrator want…

691 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question