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.
CWaveBuffer
is 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
static CString GetWaveInName(UINT nIndex);
static UINT GetWaveInCount();
static CString GetWaveOutName(UINT nIndex);
static UINT GetWaveOutCount();
Class CWaveBuffer
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();
virtual ~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();
CWave(const CWave& copy);
CWave& operator=(const CWave& wave);
virtual ~CWave();
virtual void Serialize( CArchive& archive );
Class CWaveDevice
UINT GetDevice() const;
bool IsInputFormat(const CWave& wave);
bool IsOutputFormat(const CWave& wave);
CWaveDevice(UINT nDevice = WAVE_MAPPER);
CWaveDevice(const CWaveDevice& copy); virtual ~CWaveDevice();
Class CWaveOut
CString GetError() const;
DWORD GetPosition();
bool IsPlaying();
bool Close();
bool Continue();
bool FullPlay(int nLoop = -1, DWORD dwStart = -1, DWORD dwEnd = -1);
bool Open();
bool Pause();
>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(); <BR>CWaveOut(const CWave& aWave, const CWaveDevice& aDevice);
virtual ~CWaveOut();
Class CWaveIn
CString GetError() const;
DWORD GetPosition();
bool IsRecording();
CWave MakeWave();
bool Close();
bool Continue();
bool Open();
bool Pause();
bool Stop();
bool Record(UINT nTaille = 4096);
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.
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++