MFC Multithreaded Classes for Recording, Playing, and Saving (WAV Files) Sound

The following classes, CRecordSound and CPlaySound, record sound and play PCM sound simultaneously. An example dialog-based program is provided that records, saves to disk, and then echos sound. This example also contains two more classes, CWriteSoundFile and CPlayMMSound. CWriteSoundFile receives sound buffers from CRecordSound and writes them to a WAV disk file. CPlayMMSound opens these WAV files and plays them to the sound device. All sound files are currently PCM samples. Be careful with the sample application because it records a PCM WAV file. The PCM WAV file can grow at 16 kilobytes a second, so keep the recorded samples short.

With these classes, sound can be both recorded and played at the same time. Continuous sound can be monitored and upon appropriate queues, sound can be played back. Simple sound recognition could also, for instance, be put into CRecordSound. The multithreading allows other actions to take place while sound recording and playback go on. As well, recorded sound can be saved to WAV files and played back.

CRecordSound can be invoked by the following code:

m_pRecordSound = new CRecordSound();
m_pRecordSound->CreateThread();

CPlaySound can be invoked by the following code:

m_pPlaySound = new CPlaySound();
m_pPlaySound->CreateThread();

To initiate sound recording from CRecordSound, do the following:

m_RecordThread->
PostThreadMessage(WM_RECORDSOUND_STARTRECORDING, 0, 0L);

To stop recording sound:

m_RecordThread->
PostThreadMessage(WM_RECORDSOUND_STOPRECORDING,0,0);

Similar calls begin the playing and stopping of sound:

m_PlayThread->
PostThreadMessage(WM_PLAYSOUND_STARTPLAYING,0,0);

m_PlayThread->
PostThreadMessage(WM_PLAYSOUND_STOPPLAYING,0,0);

The CRecordSound class ferries sound blocks that have been recorded over to the CPlaySound class. The CRecordSound class is notified of the CPlaySound thread via the following:

m_RecordSound->PostThreadMessage(WM_RECORDSOUND_SOUNDPLAYER,
                                 0,(LPARAM)m_PlaySound);

For both CRecordSound and CPlaySound, the virtual member,

ProcessSoundData(short int* sound, DWORD dwSamples);

can be overridden to get access to the actual sound data.

CWriteSoundFile has the following messages associated with it:

m_WriteSoundThread->PostThreadMessage(WM_WRITESOUNDFILE_FILENAME,
                                      0,(LPARAM)
(PWRITESOUNDFILE)&structWriteSoundFile);

m_WriteSoundThread->PostThreadMessage(WM_WRITESOUNDFILE_WRITEBLOCK,
                                      0,(LPARAM)(WAVEHDR)pWaveHdr);

m_WriteSoundThread->PostThreadMessage(WM_WRITESOUNDFILE_CLOSEFILE,0,0);

To write a WAV file, you must provide a WRITESOUNDFILE structure. The WRITESOUNDFILE structure has the following definition:

typedef struct writesoundfile_tag {
   char lpszFileName[MAX_PATH];
   WAVEFORMATEX waveFormatEx;
   TCHAR buffer[100];
} WRITESOUNDFILE, *PWRITESOUNDFILE;

You must provide the filename, and then the WAVEFORMATEX structure that defines the file to be written. With nonPCM formats, there is extra style-specific information at the end of the structure, hence the 100 bytes of buffer space.

This class receives WAVEHDR blocks created by CRecordSound. In the example application, pushing the "Start Recording" button will echo sound and save it to a "sound.wav" file at the same time.

CPlayMMSound will read a WAV file and play it to the sound device. It uses a pointer to a CPlaySound thread to acheive this. Its messages are:

m_pPlayMMSound->PostThreadMessage(WM_PLAYMMSOUND_PLAYFILE,
                                  0,(LPARAM)"sound.wav")

m_pPlayMMSound->PostThreadMessage(WM_PLAYMMSOUND_CLOSEFILE,0,0);

m_pPlayMMSound->PostThreadMessage(WM_PLAYMMSOUND_PLAYSOUNDPTR,0,
                                  (LPARAM)(CPlaySound*)m_pPlaySound);

The WM_PLAYMMSOUND_PLAYFILE messages open a WAV file for processing. It automatically sends off a worker thread to play the file.

You must provide a CPlaySound thread for this to work. That is the job of the WM_PLAYMMSOUND_PLAYSOUNDPTR message. You can stop the play at any time by the WM_PLAYMMSOUND_CLOSEFILE message. Currently, CPlaySound is set to play around 1.5 seconds ahead of any sound actually heard.



Downloads

Comments

  • network application

    Posted by sruthi on 10/25/2012 10:27pm

    here in the above example..how to send recording data over a network using UDP sockets in mfc

    Reply
  • duration of a wav file

    Posted by HaroonSiddiqi on 07/14/2004 05:02am

    how can I know abt the duration of a wav file in my application ?

    Reply
  • How to convert wav format file to midi format file?

    Posted by evy_ooi on 03/23/2004 03:16am

    Can someone who know about how a wav format file is convert to midi format file, please let me know. Thank you. Please send to evy_ooi@hotmail.com.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • With JRebel, developers get to see their code changes immediately, fine-tune their code with incremental changes, debug, explore and deploy their code with ease (both locally and remotely), and ultimately spend more time coding instead of waiting for the dreaded application redeploy to finish. Every time a developer tests a code change it takes minutes to build and deploy the application. JRebel keeps the app server running at all times, so testing is instantaneous and interactive.

  • The latest release of SugarCRM's flagship product gives users new tools to build extraordinary customer relationships. Read an in-depth analysis of SugarCRM's enhanced ability to help companies execute their customer-facing initiatives from Ovum, a leading technology research firm.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds