Solved

Playing Microphone Input.

Posted on 2000-03-13
14
312 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
  • 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
 
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
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
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

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

What my article will show is if you ever had to do processing to a listbox without being able to just select all the items in it. My software Visual Studio 2008 crystal report v11 My issue was I wanted to add crystal report to a form and show…
For most people, the WrapPanel seems like a magic when they switch from WinForms to WPF. Most of us will think that the code that is used to write a control like that would be difficult. However, most of the work is done by the WPF engine, and the W…
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…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

707 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now