简体   繁体   中英

Why the recorded audio data only use half of the buffer (WaveIn)?

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;
}

WAVEHDR::dwBufferLength :

dwBufferLength - Length, in bytes, of the buffer.

Your code:

_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;

Your buffer is bpbuff * sizeof (short int) bytes long. However you route it to the API to get it filled with bpbuff bytes of data only. Hence, the buffer is only filled partially and the rest of it holds uninitialized data (which you see as -12851, see 0xCDCDCDCD ).

You need to make it:

    _header[i].dwBufferLength = bpbuff * sizeof *_pBuf;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM