Click here to Skip to main content
Click here to Skip to main content

Wave Class for Playing and Recording Wave Files

, 5 Dec 2001
Rate this:
Please Sign up or sign in to vote.
This class allows you to record and play wave files
<!-- Download Links --> <!-- Image --> Sample Image <!-- Add the rest of your HTML here -->

Introduction

This is a simple class to record various sounds from sound cards and to play sound buffers recorded or loaded from a file.

How it works

CWave is the base class for loading or saving wave files. You can also build your own wave format for recording.

CWaveDevice take care of sound devices for the CWave class.

CWaveInterface lists all available devices and their names.

CWaveBufferis is a class that encapsulate buffers for CWave and CWaveIn/CWaveOut.

CWaveIn is the base class for recording (record, pause, continue, stop) and making a new CWave from the recording. In future development, we will add a virtual function to allow some work on new buffers during recording.

CWaveOut allows you to play the CWave in various ways.

Functions

Class CWaveInterface

//Return the device name for input device at index nIndex.
static CString GetWaveInName(UINT nIndex); 

//Return number of input devices detected.
static UINT GetWaveInCount(); 

// Return the device name for output device at index nIndex.
static CString GetWaveOutName(UINT nIndex); 

static UINT GetWaveOutCount(); //Return number of output devices detected. 

Class CWaveBuffer

int GetSampleSize() const; // Return the 'sizeof' a sample (short or long).

// Link pBuffer to the waveBuffer internal buffer, assuming there is 
// dwNumSamples samples of size nSize.
void SetBuffer(void* pBuffer, DWORD dwNumSamples, int nSize); 

// Create a new buffer for dwNumSamples samples of size nSize.
void SetNumSamples(DWORD dwNumSamples, int nSize = sizeof(short)); 

// Copy the buffer pBuffer of dwNumSamples samples.
void CopyBuffer(void* pBuffer, DWORD dwNumSamples, int nSize = sizeof(short)); 

DWORD GetNumSamples() const; // Return the number of samples. 
void* GetBuffer() const;// Return a pointer to the internal buffer.
CWaveBuffer();
virtual ~CWaveBuffer();

Class CWave : public CObject

// Copy or link the data buffer pBuffer of dwNumSamples samples to the 
// internal wave data buffer.
void SetBuffer(void* pBuffer, DWORD dwNumSamples, bool bCopy = false); 

void Load(const CString& strFile);
void Load(CFile* f); // Load a wave file.

void Save(const CString& strFile);
void Save(CFile* f); // Save the current instance to a wave file.

DWORD GetBufferLength() const; // Return the internal buffer length in bytes.
WORD GetNumSamples() const; // Return the internal buffer length in samples.
void* GetBuffer() const; // Return a link to the internal data buffer.

// Return the MS Windows wave format needed for some other functions.
WAVEFORMATEX GetFormat() const; 

// Build a MS Windows wave format from parameters (channels, sample 
// rate, 8 or 16 bits).
void BuildFormat(WORD nChannels, DWORD nFrequency, WORD nBits); 

CWave();
CWave(const CWave& copy);
CWave& operator=(const CWave& wave);
virtual ~CWave();
virtual void Serialize( CArchive& archive );

Class CWaveDevice

UINT GetDevice() const;// Return the MS Windows device number.
bool IsInputFormat(const CWave& wave); // Return true if the wave can be record.
bool IsOutputFormat(const CWave& wave); // Return true if the wave can be played.
CWaveDevice(UINT nDevice = WAVE_MAPPER);
CWaveDevice(const CWaveDevice& copy); virtual ~CWaveDevice();

Class CWaveOut

CString GetError() const;// Return the last string audio error.
DWORD GetPosition(); // Return the current position in the sample scale.
bool IsPlaying(); // Return true if the the instance is playing a buffer.

bool Close(); // Return true if the instance have closed the device for output. 
              // If false, use GetError() to get an explanation.
bool Continue(); // Return true if the instance has restarted playing the buffer. 
                 // If false, use GetError() to get an explanation.

// Play the whole buffer and allow to loop (INFINITE_LOOP allow to loop 
// for a long time…). Buffer can also be played from start to end (in sample scale).
bool FullPlay(int nLoop = -1, DWORD dwStart = -1, DWORD dwEnd = -1); 

bool Open(); // Return true if the instance has correctly been opened. If false, 
             // use GetError() to have an explanation. 
             
bool Pause(); // Return true if the instance has put the playing buffer in pause 
              // state. If false, use GetError() to have an explanation.

// Play the buffer. Buffer can also be played from start to end (in sample scale). 
>bool Play(DWORD dwStart = -1, DWORD dwEnd = -1); 
bool Stop(); // Return true if the instance has stopped playing the buffer. If false, 
             // use GetError() to get an explanation.
void ModifyWaveOutBufferLength(DWORD dwLength); // Set the read buffer length to this 
                                                // value (this mean the instance read dwLength 
                                                // bytes at a time in the Play function). 
void SetDevice(const CWaveDevice& aDevice); // Set the internal device to this one. 
void SetWave(const CWave& aWave); // Set the wave to be managed to this one. 
CWaveOut(); <BR>CWaveOut(const CWave& aWave, const CWaveDevice& aDevice); 
virtual ~CWaveOut();

Class CWaveIn

CString GetError() const;
DWORD GetPosition();
bool IsRecording();// Return true if current instance is recording. 
CWave MakeWave(); // Build a wave from instance buffer and MS Windows wave format.
bool Close(); 
bool Continue();
bool Open();
bool Pause(); 
bool Stop();
bool Record(UINT nTaille = 4096); // Start recording. Return true if no problem occur.
void SetDevice(const CWaveDevice& aDevice);
void SetWaveFormat(WAVEFORMATEX tagFormat); 
CWaveIn();
CWaveIn(WAVEFORMATEX tagFormat, const CWaveDevice& aDevice);
virtual ~CWaveIn(); 

Problems I encountered

I got some samples code for recording and playing wave buffers, but they almost all had  memory leaks. They also all use messages, threads or events. So, as it was not as easy as I expected for my own use, I decide to make my own classes, using the callback method.

The first problem was for playing buffers: there were noises and  interruptions, so I tried to use double buffering, and finally triple buffering (NUMWAVEOUTHDR  parameter). So I prepare 3 WAVEHDR structure from a class member buffer (see AddNewHeader() and Play() ) and the callback function takes care of adding a new one (function of the index to be prepared) and un-prepare the completed one.

Another bug arose as I worked on recording: I could not reset the device. As waveOutReset sends a MM_WOM_DONE message to the callback function, the AddNewHeader don't have to be execute. I introduced the ResetRequired() function to test if the reset has been requested.

Recording is almost the same process as playing, but you have to store recorded buffers. So I use a PtrList (see AddNewBuffer()).

As recommended in MSDN, for playing or recording, make a waveXUnprepareHeader, and then free the waveheader.lpData buffer.

An MFC app is included in the source to test these classes.

Have fun, and feel free to send any information concerning bugs, questions or improvements.

Updates

The last update corrected a wave format building error.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Pierre Canthelou
Web Developer
United States United States
Software engineer since 1998, I worked on a medical software as designer and developper for e-med innovations inc.
Now out of job, but working on PHP and still VC++

Comments and Discussions

 
QuestionA little problem in CWaveOut::FullPlay(124) line [modified] PinmemberOhjjang.Daishin3-Jul-14 22:14 
QuestionCan I use this code in my commercial project? PinmemberMember 87468193-Apr-12 17:26 
GeneralCallback Problem PinmemberRedFraggle22-May-10 3:02 
GeneralMemory owerflow problems when recording PinmemberAnders Gustafsson7-Mar-09 23:48 
Generalabout Concurrency PinmemberMahdi Monhi9-Jan-09 9:35 
QuestionNeed to append a recording to existing wave file Pinmemberbha_code8-Jan-09 19:04 
AnswerRe: Need to append a recording to existing wave file Pinmemberlozan4727-Jan-09 16:43 
QuestionLegal ? Pinmembertechking29-Jun-08 3:47 
GeneralA bug may cause crash Pinmemberwilliamfang13-May-08 12:51 
QuestionHow do i open up the setup PinmemberCanetoad19-Mar-08 19:56 
QuestionRecord audio and display audio level meter... Pinmemberceloftis18-Jul-07 10:51 
GeneralProblem in Recording - WinCE Pinmemberlakshmanakumar_varada1-Apr-07 20:21 
Generalencode audio after record by GSM 6.10 Pinmembertaolacha11323-Nov-06 20:03 
Generalnot working correctly Pinmemberrecoil25-Oct-06 4:59 
QuestionWhere is the device Selected??? Pinmember~Jabeen~13-Oct-06 22:39 
QuestionRecord &#8211; play streaming directly from input to output (no files) Pinmembermadfitz21-Sep-06 6:49 
GeneralHelp me with default recording device!!! PinmemberHung In26-Jul-06 17:00 
GeneralYour program and .Net question PinmemberParik Advani19-Jun-06 1:04 
Questionconverter Pinmemberhafz12-Apr-06 23:29 
GeneralOverload + Oerator PinmemberAmbrish Dwivedi23-Jan-06 22:24 
Generalget buffer Pinmemberwhatsmyid22-Jan-06 7:18 
Questioncan it play/record on Windows 2000? PinmemberSeven Pham9-Nov-05 17:49 
Questionis it possible in C# PinmemberKumar Muthu29-Oct-05 1:20 
GeneralUpdate Pinmember[ Pierre ]20-May-05 0:51 
GeneralRe: Update Pinmemberyoontet19-Nov-05 22:47 
Questioncan u help me PinmemberMuralish23-Apr-05 0:20 
AnswerRe: can u help me Pinmembergooshbob31-Aug-05 10:23 
Generalwav header PinmemberMuralish23-Apr-05 0:14 
GeneralSir! can you help me! Pinmembermssu6-Apr-05 21:55 
GeneralMulti-channel recording PinmemberCosmoNova14-Mar-05 15:41 
GeneralCouldn't PLAY in _UNICODE Pinmemberalan9328-Feb-05 15:21 
GeneralControlling the recorded Sound Pinmembernabilelia27-Jan-05 3:59 
Generaldevice problem PinmemberRafatTariq10-Dec-04 7:06 
Questionhow it works ,need help Pinmemberatul123456789027-Oct-04 17:46 
GeneralGreat but... Pinmemberbengreen53-Oct-04 12:42 
GeneralWave Format Transforming Question PinmemberDick.leeSolucky19-Jan-05 20:42 
GeneralTo ALL YOU intrested in playing or recording wave Pinmembermohsen nourian7-Jul-04 22:49 
Generalproblem with wave files &gt;1MB !!! Pinmembermohsen nourian4-Jul-04 1:52 
Questionthere is no size func ??? Pinsusswavefan3-Jul-04 22:47 
Questionproblem with wave device ? Pinmemberramtinbahal3-Jul-04 18:24 
Generalmore details on wav Pinmembermohsen nourian3-Jul-04 2:44 
Generalrecording in c# Pinmemberali_iac26-Apr-04 22:10 
QuestionCan I record the 5.1 channel wave to the wave file by MME. PinmemberWhite Lie16-Mar-04 16:58 
GeneralRecord &amp; Play simultanously Pinmemberned-ned17-Feb-04 1:29 
GeneralWin98 Problems PinmemberEd Dixon8-Jan-04 2:43 
GeneralRe: Win98 Problems Pinmember[ Pierre ]6-Feb-04 10:58 
GeneralBug in IsRecording and IsPlaying Pinmemberpegasusplus17-Nov-03 17:50 
GeneralOhh, resource leaks much! Pinmemberpegasusplus28-Oct-03 19:47 
GeneralRe: Ohh, resource leaks much! Pinmemberbengreen53-Oct-04 12:45 
GeneralDont do this! PinmemberPatrick Hoffmann25-Oct-03 15:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141223.1 | Last Updated 6 Dec 2001
Article Copyright 2001 by Pierre Canthelou
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid