Playing Microphone Input.

I'm looking for code to read in the audio input from the Microphone and play it out again throught the soundcard.

I believe it can be done using the waveIn* and waveOut* api calls but I cant suss out the buffer stuff.

Thanks in advance
Gordon
LVL 3
GordonpAsked:
Who is Participating?
 
WynCommented:
Here is some info I quote ,hope helpful.I'm keeping write a array-sort program,thus late here:
Quoted :
Before starting the process of voice recording and playing you have to declare and initialize the above described structures and handles related to wave input/output.

Two important handle types are :
HWAVEIN = This handle identifies the open waveform-audio input device.
HWAVEOUT = This handle identifies the open waveform-audio output device.

Let's define a structure for our convenience to be used in the code as :
typedef struct _LevelStreamData {
LPWAVEHDR alpWave[BUFFERSNO];
WAVEFORMATEX FAR *pwf;
HWAVEIN hwi;
int buffersize;
} LEVELSTREAMDATA, FAR * PLEVELSTREAMDATA;

BUFFERSNO are defined as
#define BUFFERSNO 4

Here you can define the total number of buffers that you want to use.

Now before starting the recording and playing of voice data you have to initialize these voice related structures and prepare the audio input and output device.

Inthe following lines of code we will see how one can open a wave device in the given format, queue up all the buffers and start data streaming.

step 1: Declare a member of PLEVELSTREAMDATA structure defined above.
PLEVELSTREAMDATA pInfo;

step 2: Initialize the above declared structure member with appropriate value like
pInfo->pwf->nChannels = 1;
pInfo->pwf->wBitsPerSample = 8;
pInfo->pwf->nSamplesPerSec = 11025;
pInfo->pwf->wFormatTag = WAVE_FORMAT_PCM;
pInfo->pwf->nBlockAlign = pInfo->pwf->nChannels * pInfo->pwf->wBitsPerSample / 8;
pInfo->pwf->nAvgBytesPerSec = pInfo->pwf->nSamplesPerSec * pInfo->pwf->nBlockAlign;

pInfo->buffersize = pInfo->pwf->nAvgBytesPerSec/UPDATES_PER_SEC;

Where UPDATES_PER_SEC is the part of a second for which you want to record the voice data and is defined as

#define UPDATES_PER_SEC 5
In which case your buffer size will record one fifth second's voice.

step 3: Opening the waveform input device (soundcard) for recording
The function for this goes like this :
waveInOpen(&pInfo->hwi, WAVE_MAPPER, (LPWAVEFORMATEX)pwf, (DWORD) hDlg, 0, CALL_BACK_WINDOW)

where hDlg is the handle to the window receiving messages.

step 4: Setting all the wave headers to NULL for cleanup
for( i=0; i<BUFFERSNO; i++)
pInfo->alpWave[i] = NULL;

step 5: Allocate, prepare and add all the buffers
for(i=0; i<BUFFERSNO; i++)
{
pInfo->alpWave[i] = (LPWAVEHDR) GlobalLock(GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR) + pInfo->buffersize));

if(pInfo->alpWave[i] == NULL) return FALSE;   //Unable to allocate memory

pInfo->alpWave[i]->lpData = (LPSTR)(LPBYTE)(pInfo->alpWave[i] + 1);
pInfo->alpWave[i]->dwBufferLength = pInfo->buffersize;
pInfo->alpWave[i]->dwBytesRecorded = 0;
pInfo->alpWave[i]->dwUser = 0;
pInfo->alpWave[i]->dwFlags = 0;
pInfo->alpWave[i]->dwLoops = 0;

if(waveInPrepareHeader(pInfo->hwi, pInfo->alpWave[i], sizeof(WAVEHDR))) return FALSE;
//Above function prepare these buffers for waveform input finally

if(waveInAddBuffer(pInfo->hwi, pInfo->alpWave[i], sizeof(WAVEHDR)))
return FALSE;
//Above function sends these buffers to the given waveform input device
}

step 7: Finally starting the wave input
With the execution of waveInStart() function the waveform input device starts recording. The function is called like this.
int errorCode = waveInStart( pInfo->hwi);
if(errorCode) {
MessageBox("Error in starting wave recording");
return FALSE;
}



With the above WaveInStart() packets will start arriving. To get those packets process the
MM_WIM_DATA message as shown below:

case MM_WIM_DATA:
wRBuffer=(char*)((LPWAVEHDR)lParam)->lpData;
_beginthread((void (__cdecl *)(void *))sendAThread,0,(void (__cdecl *)(void *))wRBuffer);
waveInUnprepareHeader((HWAVEIN)wParam,(LPWAVEHDR)lParam,sizeof(WAVEHDR));
waveInPrepareHeader((HWAVEIN)wParam,(LPWAVEHDR)lParam,sizeof(WAVEHDR));
waveInAddBuffer((HWAVEIN)wParam,(LPWAVEHDR)lParam,sizeof(WAVEHDR));
return TRUE;
break;

where -
wrBuffer is declared as char *wrBuffer;
_beginThread will start execution of a thread and pass to that the voice packet
which contains the recorded voice.
sendAThread is the thread function to which this data is passed. In this function you can
process this voice packet and do with that whatever u like, (i.e. u can send this packet to
some other machine or play it back)

sendAThread can be written as follows :

void sendAThread(char *sbuffer)
{
//code to process the received buffer
return;
}

So, you can see how easy is it to create a thread and than pass to it the required data.
But before using threads remember to include process.h header file.
================

Hope helpful.
Regards
W.Yinan

0
 
WynCommented:
Hi,Gordon .There are many ways to record input from soundcard.

Qed:
1. MCIWnd Window Class

Recording with MCIWnd Controls
http://msdn.microsoft.com/library/psdk/multimed/mciwnd_0e43.htm 

2. MCI

Recording with a Waveform-Audio Device
http://msdn.microsoft.com/library/psdk/multimed/mci_4wpx.htm 

3. Waveform Audio

Example of Writing Waveform Data
http://msdn.microsoft.com/library/psdk/multimed/wave_8rj5.htm 

Recording and Playing Waveform Audio
http://msdn.microsoft.com/library/techart/msdn_spellit.htm 

4. DirectSound

Tutorial 2: Capturing a Sound
http://msdn.microsoft.com/library/psdk/directx/dstut_9ox0.htm

Regards
0
 
WynCommented:
And here are some info you need:

some samples:
Audio Mixer Functions Demo
http://www.codeguru.com/multimedia/ADMixer.shtml 


http://msdn.microsoft.com/workshop/c-frame.htm?944437056110#/workshop/imedia/windowsmedia/sdk/wmsdk_fmt.asp

And if you want to use waveinxxx waveoutxx .I can write another sample but it will take some time.First check above info.

Regards
W.Yinan
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

 
GordonpAuthor Commented:
Wyn>
All bar one of your links are for recording an audio input, and the other link is broken.

I want to play the audio input straight out again on the speakers, not record it into a file.

GordonP
0
 
WynCommented:
I know what you want and Okay now I will write one for you .But I dont think it's big different to above!

Waiting....
0
 
WynCommented:
One Directions:
Use threads for this application. One for receiving and playing the voice you are receiving and another for recording and sending the voice.

One question:
Is your card duplex?
0
 
GordonpAuthor Commented:
> One question:
> Is your card duplex?
Yes!
0
 
WynCommented:
You will find code how to record in above links.Here is how to play them concurrently

The MM_WIM_DATA message will be sent when the input structure are filled.
Then you create a create in handler code:

case MM_WIM_DATA:
_beginthread(doit,0,buffer);
The doit will the function you want to do with the buffer.

0
 
GordonpAuthor Commented:
can I just use one buffer! do I need to use synchro for buffer access??

GordonP
0
 
GordonpAuthor Commented:
the link "Recording and Playing Waveform Audio" doesnt work.

I assume this would have shown me how to read the data into the buffer, do you have a working link for this!!

GordonP
0
 
WynCommented:

->can I just use one buffer! do I need to use synchro for buffer access??  
================
All above:)
0
 
GordonpAuthor Commented:
Thanks I'll try it and get back to you

Gordon
0
 
GordonpAuthor Commented:
Thanks for your help

Gordon
0
 
gptrevenCommented:
I have a problem in that I have two sound cards in the one machine and I am having troubles selecting the individual device under waveinopen.  It keeps returning error 32 any help
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.