Click here to Skip to main content
15,867,771 members
Articles / Desktop Programming / MFC
Article

How to play and record sounds

Rate me:
Please Sign up or sign in to vote.
4.64/5 (53 votes)
12 Mar 2001 516.8K   14.7K   142   90
A simple application that shows how to play and record sounds under Windows

Image 1

Introduction

This is a simple application that shows you how to play and record sound under windows.
It uses the old multimedia API. A better solution may be to use DirectSound.

Image 2

Quick Guide to the Code

Start with the two functions in CFisterDlg called OnPlay and OnRecord. Follow them down to the depth you need to use the classes.

Short description

CSoundIn is a wrapper class that will let you retreive sound from the soundcard. The main functions are Start() and Stop()

CSoundOut is a wrapper class that will let you play sound on the soundcard. The main functions are Start() and Stop()

CSoundFile is a wrapper class of a single wave file, it can either be a file reader or a file writer object. See the constructor.

CSoundBase is a very small class that encapsulates the wave format.

CBuffer is a very small class that encapsulates a simple one dimentional buffer.

The project has a number of different callback functions:

  • One callback function makes the Play button change it's label to stop when it has finished playing the file. CDialogDlg enherits
    CPipe 
    and overloads a function that CPipe can call when it has finished playing the wave file.
  • Another callback function make it possible for CSoundIn to callback to CPipe when it has filled the input buffer. Thus CPipe can give CSoundIn a new buffer to fill.
  • A clone of the above principle is also used in CSoundOut, which enables it to callback to the owner when it is finished playing the sound in a given buffer.

Problems that I encountered

I have spent almost 2 days debugging the following stupid problem. When CSoundIn and CSoundOut inherit from CSoundBase and CWinThread the order in which they are listed must be as shown below. If not, the callback functions, which are started by the WinThread message handler, will not be able to access the member variables of the CSoundIn object.

class CSoundIn : public CWinThread, public CSoundBase

During these two days of fustration I also tried to implement the callback as regular callback functions called by the device driver. This is possible using ::waveInOpen(...). But since this callback function is not allowed to call any of the ::waveInXXX(...) functions it is not of much use.

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


Written By
Web Developer
Denmark Denmark
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generalhelp me,plz Pin
chaitanya123215-Jul-04 22:14
susschaitanya123215-Jul-04 22:14 
GeneralA simple way to play sound... Pin
Member 1021685924-May-04 18:42
Member 1021685924-May-04 18:42 
GeneralRe: A simple way to play sound... Pin
David Crow8-Jun-04 3:21
David Crow8-Jun-04 3:21 
GeneralRe: A simple way to play sound... ? Pin
mohsen nourian3-Jul-04 22:05
mohsen nourian3-Jul-04 22:05 
GeneralRe: A simple way to play sound... ? Pin
mohsen nourian3-Jul-04 23:33
mohsen nourian3-Jul-04 23:33 
General::PostQuitMessage(0)!!! Pin
Andrew Altham31-Jan-04 2:58
Andrew Altham31-Jan-04 2:58 
Generalplay more than one file at a moment Pin
Anonymous19-Jan-04 22:54
Anonymous19-Jan-04 22:54 
GeneralCSoundIn::Stop() change to avoid "still %d buffers in waveIn queue" Pin
Member 7506721-Jan-04 1:55
Member 7506721-Jan-04 1:55 
situation: in the Close() function, 3 things are done:
1. waveInReset
2. m_brecording = False
3. waveInClose

order of events: waveInReset succeeds, then m_brecording is set. between these 2 actions, MM_WIM_DATA events are likely to still arrive and trigger OnMM_WIM_DATA.

OnMM_WIM_DATA will prepare the header again if m_brecording is still true, while waveInReset() is already processed.
result: assigned buffers even though we have performed reset (the assigned buffers will cause waveInClose() to fail).

solution: 2 options
1. set m_brecording = False before waveInReset(). (which is the quick solution)
or
2. put some checking in as follows (uncomment the ErrorMsg lines to see what is happening). See comments in the code.
void CSoundIn::Stop()
{
MMRESULT mmReturn = MMSYSERR_NOERROR;
if(!m_bRecording)
{
//ErrorMsg("CSoundIn::Stop() - m_bRecording == False");
return;
}
else
{
//ErrorMsg("CSoundIn::Stop() - m_bRecording == True");
for(int j=0;(m_QueuedBuffers > 0) && (j < 3);j++)
{
//m_bRecording = FALSE;
mmReturn = ::waveInReset(m_hRecord);
if(mmReturn)
{
waveInErrorMsg(mmReturn, "CSoundIn::Stop() - waveInReset != 0");
//ErrorMsg("CSoundIn::Stop() - waveInReset; Resets = %d", j);
return;
}
else
{
//ErrorMsg("CSoundIn::Stop() - waveInReset == 0; Resets = %d", j);
m_bRecording = FALSE;
/*
between the waveInReset and the m_bRecording = FALSE, onMM_WIM_DATA
may (probably will) have fired and reprepared header and assigned to the
queue. These re-assigned buffers will not be freed by the waveInReset
To make sure that all buffers are free, we need to redo the
waveInReset now, while the m_bRecording has been set to false to free any
possible buffers that were assigned between reset and m_bRecording = false.
We need to give the process some time to receive any onMM_WIM_DATA
messages to free the associated buffers.
In case any buffers are still not unprepared, the outer for() will
redo the reset and test again.
once all buffers are out of the queue, then it is safe to close the
the Wave device.
*/
//Sleep(1000);
for(int i=0;(m_QueuedBuffers > 0) && (i < 3);i++)
{
Sleep(100);
//ErrorMsg("CSoundIn::Stop() - ; Resets = %d;waiting %d", j, i);
}
}
}
mmReturn = ::waveInClose(m_hRecord);
if(mmReturn)
{
waveInErrorMsg(mmReturn, "CSoundIn::Stop() - waveInClose != 0");
}
else
{
//ErrorMsg("CSoundIn::Stop() - waveInClose == 0");
}
if(m_QueuedBuffers != 0)
{
ErrorMsg("CSoundIn::Stop() - Still %d buffers in waveIn queue!", m_QueuedBuffers);
}
else
{
//ErrorMsg("CSoundIn::Stop() - m_QueuedBuffers == 0");
}
}
}
GeneralRe: CSoundIn::Stop() change to avoid &quot;still %d buffers in waveIn queue&quot; Pin
ze_seb25-Mar-05 6:39
ze_seb25-Mar-05 6:39 
Generalplease help me to solve the link errors in the program of how to play and record Pin
2-Dec-03 5:17
suss2-Dec-03 5:17 
QuestionHow to support a sound input device in C# Pin
CNWORM22-Aug-03 20:39
CNWORM22-Aug-03 20:39 
AnswerRe: How to support a sound input device in C# Pin
Anonymous29-Oct-03 17:13
Anonymous29-Oct-03 17:13 
QuestionHow to record sound played by other program Pin
nacasa30-Jul-03 23:19
nacasa30-Jul-03 23:19 
AnswerRe: How to record sound played by other program Pin
Anonymous29-Oct-03 17:15
Anonymous29-Oct-03 17:15 
GeneralRe: How to record sound played by other program Pin
sanpee9-Dec-03 3:26
sanpee9-Dec-03 3:26 
QuestionHow to avoid popuping error dialog instantly? Pin
_sailinsky28-May-03 16:48
_sailinsky28-May-03 16:48 
AnswerRe: How to avoid popuping error dialog instantly? Pin
Anonymous29-Oct-03 17:16
Anonymous29-Oct-03 17:16 
Questionhow can I download it? Pin
lidoo18-May-03 18:22
lidoo18-May-03 18:22 
GeneralWinCE Pin
henrytaihk22-Mar-03 0:52
henrytaihk22-Mar-03 0:52 
GeneralMemory leak! Pin
WaHaha20-Mar-03 3:29
WaHaha20-Mar-03 3:29 
GeneralRe: Memory leak! Pin
burchtimp10-Jun-04 11:31
burchtimp10-Jun-04 11:31 
QuestionHow can I record from line-in not from microphone? Pin
soichi27-Feb-03 13:38
soichi27-Feb-03 13:38 
AnswerRe: How can I record from line-in not from microphone? Pin
Member 27489214-Mar-03 11:14
Member 27489214-Mar-03 11:14 
GeneralRe: How can I record from line-in not from microphone? Pin
mircokramer10-Apr-03 21:46
mircokramer10-Apr-03 21:46 
GeneralRe: How can I record from line-in not from microphone? Pin
edlogic3-Feb-07 19:54
edlogic3-Feb-07 19:54 

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

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