<!-- Download Links -->
<!-- Image -->
<!-- Add the rest of your HTML here -->
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
CWaveInterface lists all available devices and their names.
CWaveBufferis is a class that encapsulate buffers for
CWaveIn is the base class for recording (record, pause, continue, stop) and making a
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.
static CString GetWaveInName(UINT nIndex);
static UINT GetWaveInCount();
static CString GetWaveOutName(UINT nIndex);
static UINT GetWaveOutCount();
int GetSampleSize() const;
void SetBuffer(void* pBuffer, DWORD dwNumSamples, int nSize);
void SetNumSamples(DWORD dwNumSamples, int nSize = sizeof(short));
void CopyBuffer(void* pBuffer, DWORD dwNumSamples, int nSize = sizeof(short));
DWORD GetNumSamples() const; void* GetBuffer() const;CWaveBuffer();
Class CWave : public CObject
void SetBuffer(void* pBuffer, DWORD dwNumSamples, bool bCopy = false);
void Load(const CString& strFile);
void Load(CFile* f);
void Save(const CString& strFile);
void Save(CFile* f);
DWORD GetBufferLength() const; WORD GetNumSamples() const; void* GetBuffer() const;
WAVEFORMATEX GetFormat() const;
void BuildFormat(WORD nChannels, DWORD nFrequency, WORD nBits);
CWave(const CWave& copy);
CWave& operator=(const CWave& wave);
virtual void Serialize( CArchive& archive );
UINT GetDevice() const;bool IsInputFormat(const CWave& wave); bool IsOutputFormat(const CWave& wave); CWaveDevice(UINT nDevice = WAVE_MAPPER);
CWaveDevice(const CWaveDevice& copy); virtual ~CWaveDevice();
CString GetError() const;DWORD GetPosition(); bool IsPlaying();
bool Close(); bool Continue();
bool FullPlay(int nLoop = -1, DWORD dwStart = -1, DWORD dwEnd = -1);
>bool Play(DWORD dwStart = -1, DWORD dwEnd = -1);
bool Stop(); void ModifyWaveOutBufferLength(DWORD dwLength); void SetDevice(const CWaveDevice& aDevice); void SetWave(const CWave& aWave); CWaveOut();
CWaveOut(const CWave& aWave, const CWaveDevice& aDevice);
CString GetError() const;
bool IsRecording();CWave MakeWave(); bool Close();
bool Record(UINT nTaille = 4096); void SetDevice(const CWaveDevice& aDevice);
void SetWaveFormat(WAVEFORMATEX tagFormat);
CWaveIn(WAVEFORMATEX tagFormat, const CWaveDevice& aDevice);
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
) 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
AddNewHeader don't have to be execute. I introduced
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
As recommended in MSDN, for playing or recording, make a
and then free the
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.
The last update corrected a wave format building error.