Solved

Playing Microphone Input.

Posted on 2000-03-13
14
321 Views
Last Modified: 2013-12-03
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
0
Comment
Question by:Gordonp
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 6
14 Comments
 
LVL 5

Expert Comment

by:Wyn
ID: 2611421
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
 
LVL 5

Expert Comment

by:Wyn
ID: 2611450
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
 
LVL 3

Author Comment

by:Gordonp
ID: 2611491
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
Instantly Create Instructional Tutorials

Contextual Guidance at the moment of need helps your employees adopt to new software or processes instantly. Boost knowledge retention and employee engagement step-by-step with one easy solution.

 
LVL 5

Expert Comment

by:Wyn
ID: 2611528
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
 
LVL 5

Expert Comment

by:Wyn
ID: 2611619
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
 
LVL 3

Author Comment

by:Gordonp
ID: 2611625
> One question:
> Is your card duplex?
Yes!
0
 
LVL 5

Expert Comment

by:Wyn
ID: 2611651
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
 
LVL 3

Author Comment

by:Gordonp
ID: 2611710
can I just use one buffer! do I need to use synchro for buffer access??

GordonP
0
 
LVL 3

Author Comment

by:Gordonp
ID: 2611726
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
 
LVL 5

Accepted Solution

by:
Wyn earned 300 total points
ID: 2612590
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
 
LVL 5

Expert Comment

by:Wyn
ID: 2612594

->can I just use one buffer! do I need to use synchro for buffer access??  
================
All above:)
0
 
LVL 3

Author Comment

by:Gordonp
ID: 2614994
Thanks I'll try it and get back to you

Gordon
0
 
LVL 3

Author Comment

by:Gordonp
ID: 2640221
Thanks for your help

Gordon
0
 

Expert Comment

by:gptreven
ID: 8583296
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

Featured Post

Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
How to update List item Managed Metadata Column with JSOM 2 287
WPF issue with Trigger 2 143
reboot server with scheduled time and week base 4 88
Error in Visual Project 10 45
For a while now I'v been searching for a circular progress control, much like the one you get when first starting your Silverlight application. I found a couple that were written in WPF and there were a few written in Silverlight, but all appeared o…
Entering time in Microsoft Access can be difficult. An input mask often bothers users more than helping them and won't catch all typing errors. This article shows how to create a textbox for 24-hour time input with full validation politely catching …
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

738 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question