I'm trying to record audio data from the microphone and save in files. The problem is that the wavein device only uses half the buffer specified in the wave header. In particular, only first 2000 points in the file from the audio, the rest of the file reads like the following
-12851
-12851
-12851
-12851
.....
Not clear what goes wrong. What I find is that if I change the following line of code from
_header[i].dwBufferLength = bpbuff;
to
_header[i].dwBufferLength = 2*bpbuff;
then all 4000 values are indeed the audio input. But obviously this is not the right way to get the problem fixed. Any thoughts?
Here's the full code:
#include "stdafx.h"
#include <Windows.h>
#pragma comment(lib, "winmm.lib")
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
HANDLE hEvent_BufferReady;
#define Samplerate 2000
#define nSec 3
BOOL BufferReady;
enum { NUM_BUF = 8 };
int _iBuf;
int prevBuf;
void CALLBACK myWaveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
WAVEHDR *pHdr=NULL;
switch(uMsg)
{
case WIM_CLOSE:
cout << "waveInProc()... WIM_CLOSE" << endl;
break;
case WIM_DATA:
{
cout << "waveInProc()... WIM_DATA : " <<endl;
SetEvent(hEvent_BufferReady);
}
break;
case WIM_OPEN:
cout << "waveInProc()... WIM_OPEN" << endl;
break;
default:
break;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
hEvent_BufferReady=CreateEvent(NULL,FALSE, FALSE, NULL);
WAVEFORMATEX pFormat;
pFormat.wFormatTag = WAVE_FORMAT_PCM; // simple, uncompressed format
pFormat.nChannels = 1; // 1=mono, 2=stereo
pFormat.nSamplesPerSec = Samplerate; // 44100
pFormat.wBitsPerSample = 16; // 16 for high quality, 8 for telephone-grade
pFormat.nBlockAlign = pFormat.nChannels*pFormat.wBitsPerSample/8;
pFormat.nAvgBytesPerSec = (pFormat.nSamplesPerSec)*(pFormat.nChannels)*(pFormat.wBitsPerSample)/8;
pFormat.cbSize=0;
HWAVEIN hWaveIn;
unsigned long result;
WAVEHDR _header [NUM_BUF];
short int *_pBuf;
size_t bpbuff = (pFormat.nSamplesPerSec) * (pFormat.nChannels) * (pFormat.wBitsPerSample)/8;
result = waveInOpen(&hWaveIn, WAVE_MAPPER,&pFormat, (DWORD)myWaveInProc, 0L, CALLBACK_FUNCTION);
_pBuf = new short int [bpbuff * NUM_BUF];
// initialize all headers in the queue
for ( int i = 0; i < NUM_BUF; i++ )
{
_header[i].lpData = (LPSTR)&_pBuf [i * bpbuff];
_header[i].dwBufferLength = bpbuff;
_header[i].dwFlags = 0L;
_header[i].dwLoops = 0L;
waveInPrepareHeader(hWaveIn, & _header[i], sizeof(WAVEHDR));
waveInAddBuffer (hWaveIn, & _header[i], sizeof (WAVEHDR));
}
_iBuf = 0;
int _prevBuf = NUM_BUF - 1;
unsigned char* tempchar;
waveInStart(hWaveIn);
for(int iter=0;iter<5;iter++)
{
do {
} while (!(_header[_iBuf].dwFlags & WHDR_DONE));
waveInUnprepareHeader (hWaveIn, &_header[_iBuf], sizeof (WAVEHDR));
std::ostringstream fn;
fn << "file" << iter << ".txt";
ofstream myfile;
myfile.open (fn.str());
for(int i=0;i<bpbuff;i++)
{
myfile<<_pBuf[_iBuf*bpbuff + i]<<"\n";
}
myfile.close();
int prevBuf = _iBuf - 1;
if (prevBuf < 0)
prevBuf = NUM_BUF - 1;
_header [prevBuf].lpData = (LPSTR)&_pBuf [prevBuf * bpbuff];
_header [prevBuf].dwBufferLength = bpbuff;
_header [prevBuf].dwFlags = 0L;
_header [prevBuf].dwLoops = 0L;
waveInPrepareHeader(hWaveIn, & _header[_iBuf], sizeof(WAVEHDR));
waveInAddBuffer (hWaveIn, & _header[_iBuf], sizeof (WAVEHDR));
++_iBuf;
if (_iBuf == NUM_BUF) _iBuf = 0;
}
waveInClose(hWaveIn);
cout<<"hello"<<endl;
getchar();
CloseHandle(hEvent_BufferReady);
return 0;
}