//WindowsXP录音模块
//RecordToWavFile.h
#ifndef __RECORD_TO_WAV_FILE_H__
#define __RECORD_TO_WAV_FILE_H__
#define RECORD_TO_WAV_FILE_API __declspec(dllexport)
#pragma warning(disable:4996)
RECORD_TO_WAV_FILE_API int _StartRecord(
const wchar_t* _lpszFileName,unsigned int _nChannels = 1,unsigned int _nSamplesPerSec = 16000,unsigned int _wBitsPerSample = 16);
RECORD_TO_WAV_FILE_API void _EndRecord();
#endif//__RECORD_TO_WAV_FILE_H__
//RecordToWavFile.cpp
#include <windows.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <mmsystem.h>
#include "RecordToWavFile.h"
#pragma comment(lib,"winmm.lib")
#define FRAGMENT_SIZE 1024//缓存区大小
#define FRAGMENT_NUM 4//缓存区个数
#pragma pack(push,1)
typedef struct tagPcmWaveHeader
{
unsigned char riff[4];
unsigned long file_length;
unsigned char wave[4];
unsigned char fmt[4];
unsigned long format_length;
short wFormatTag;
short nChannels;
unsigned long nSamplesPerSec;
unsigned long nAvgBytesPerSec;
short nBlockAlign;
short wBitsPerSample;
unsigned char data[4];
unsigned long data_length;
}PCM_WAVE_HEADER,*PPCM_WAVE_HEADER;
#pragma pack(pop)
static unsigned char s_byteBufferArrayForHdr[FRAGMENT_NUM][FRAGMENT_SIZE] = {0};
static WAVEHDR s_sWaveHdr[FRAGMENT_NUM] = {0};
static HANDLE s_hFile = INVALID_HANDLE_VALUE;
static HWAVEIN s_hWaveIn = NULL;
static long s_lWavDataLength = 0;
static PCM_WAVE_HEADER s_bpfh = {0};
static void CALLBACK waveInProc(HWAVEIN hwi,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2);
void FillAcmWavHeader(PPCM_WAVE_HEADER header,unsigned long length,
unsigned short _nChannelsRes,unsigned long _nSamplesPerSecRes,short _wBitsPerSampleRes);
RECORD_TO_WAV_FILE_API int _StartRecord(
const wchar_t* _lpszFileName,unsigned int _nChannels,unsigned int _nSamplesPerSec,unsigned int _wBitsPerSample)
{
int iCreateFileCount;
MMRESULT rel = MMSYSERR_NOERROR;
WAVEFORMATEX wavform = {0};
DWORD dwNumberOfBytesWritten = 0;
assert (NULL != _lpszFileName && 0 != _lpszFileName[0]);
assert (2 >= _nChannels && 48000 >= _nSamplesPerSec && 16 >= _wBitsPerSample);
if (NULL != _lpszFileName && 0 != _lpszFileName[0] &&
2 >= _nChannels && 48000 >= _nSamplesPerSec && 16 >= _wBitsPerSample &&
INVALID_HANDLE_VALUE == s_hFile)
{
iCreateFileCount = 0;
do
{
if (INVALID_HANDLE_VALUE != s_hFile)
{
CloseHandle(s_hFile);
s_hFile = INVALID_HANDLE_VALUE;
Sleep(5);
}
if (0 < iCreateFileCount)
{
Sleep(10);
}
s_hFile = CreateFile(_lpszFileName,GENERIC_WRITE,FILE_SHARE_READ,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
iCreateFileCount ++;
}while (INVALID_HANDLE_VALUE == s_hFile && iCreateFileCount < 5);
#ifdef _DEBUG
int err = GetLastError();
#endif//_DEBUG
assert (INVALID_HANDLE_VALUE != s_hFile);
if (INVALID_HANDLE_VALUE != s_hFile)
{
wavform.wFormatTag = WAVE_FORMAT_PCM;
wavform.nChannels = _nChannels;
wavform.nSamplesPerSec = _nSamplesPerSec;
wavform.wBitsPerSample = _wBitsPerSample;
wavform.nBlockAlign = wavform.nChannels * wavform.wBitsPerSample / 8;
wavform.nAvgBytesPerSec = wavform.nSamplesPerSec * wavform.nBlockAlign;
wavform.cbSize = 0;
rel = waveInOpen(&s_hWaveIn,WAVE_MAPPER,&wavform,(DWORD_PTR)waveInProc,0,CALLBACK_FUNCTION);
if (MMSYSERR_NOERROR == rel)
{
for (int i=0;i<FRAGMENT_NUM;i++)
{
memset(&(s_sWaveHdr[i]),0,sizeof(WAVEHDR));
s_sWaveHdr[i].lpData = (LPSTR)(s_byteBufferArrayForHdr[i]);
s_sWaveHdr[i].dwBufferLength = FRAGMENT_SIZE;
s_sWaveHdr[i].dwLoops = 1;
waveInPrepareHeader(s_hWaveIn,&(s_sWaveHdr[i]),sizeof(WAVEHDR));
waveInAddBuffer(s_hWaveIn,&(s_sWaveHdr[i]),sizeof(WAVEHDR));
}
if (NULL != s_hFile)
{
s_lWavDataLength = 0;
FillAcmWavHeader(&s_bpfh,s_lWavDataLength,_nChannels,_nSamplesPerSec,_wBitsPerSample);
WriteFile(s_hFile,&s_bpfh,sizeof(s_bpfh),&dwNumberOfBytesWritten,NULL);
}
waveInStart(s_hWaveIn);
return 0;
}
else
{
CloseHandle(s_hFile);
s_hFile = INVALID_HANDLE_VALUE;
return -1;
}
}
else
{
return -2;
}
}
return -3;
}
RECORD_TO_WAV_FILE_API void _EndRecord()
{
int i;
DWORD dwNumberOfBytesWritten = 0;
if (INVALID_HANDLE_VALUE != s_hFile)
{
waveInStop(s_hWaveIn);
for (i=0; i<FRAGMENT_NUM; i++)
{
waveInUnprepareHeader(s_hWaveIn, &s_sWaveHdr[i], sizeof(WAVEHDR));
memset(&(s_sWaveHdr[i]),0,sizeof(WAVEHDR));
}
waveInClose(s_hWaveIn);
if (NULL != s_hFile)
{
SetFilePointer(s_hFile,0,0,FILE_BEGIN);
FillAcmWavHeader(&s_bpfh,s_lWavDataLength,s_bpfh.nChannels,s_bpfh.nSamplesPerSec,s_bpfh.wBitsPerSample);
WriteFile(s_hFile,&s_bpfh,sizeof(s_bpfh),&dwNumberOfBytesWritten,NULL);
s_lWavDataLength = 0;
}
if (NULL != s_hFile)
{
CloseHandle(s_hFile);
s_hFile = INVALID_HANDLE_VALUE;
}
}
}
void CALLBACK waveInProc(HWAVEIN hwi,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2)
{
DWORD dwNumberOfBytesWritten = 0;
LPWAVEHDR lpsHdr = (LPWAVEHDR)dwParam1;
switch (uMsg)
{
case WIM_DATA:
if (INVALID_HANDLE_VALUE != s_hFile)
{
s_lWavDataLength += lpsHdr->dwBytesRecorded;
WriteFile(s_hFile,lpsHdr->lpData,lpsHdr->dwBytesRecorded,&dwNumberOfBytesWritten,NULL);
waveInAddBuffer(hwi,lpsHdr,sizeof(WAVEHDR));
}
break;
default:
break;
}
}
void FillAcmWavHeader(PPCM_WAVE_HEADER header,unsigned long length,
unsigned short _nChannelsRes,unsigned long _nSamplesPerSecRes,short _wBitsPerSampleRes)
{
strncpy((char*)header->riff, "RIFF", 4);
header->file_length = sizeof(PCM_WAVE_HEADER) + length - 8;
strncpy((char*)header->wave, "WAVE", 4);
strncpy((char*)header->fmt, "fmt ", 4);
header->format_length = 16;
header->wFormatTag = 1;
header->nChannels = _nChannelsRes;
header->nSamplesPerSec = _nSamplesPerSecRes;
header->wBitsPerSample = _wBitsPerSampleRes;
header->nBlockAlign = header->nChannels * header->wBitsPerSample / 8;
header->nAvgBytesPerSec = header->nSamplesPerSec * header->nBlockAlign;
strncpy((char*)header->data, "data", 4);
header->data_length = length;
}
//TestRecordToWavFile.cpp
//
#include "stdafx.h"
#include <Windows.h>
#include "../RecordToWavFile/RecordToWavFile.h"
///
int _tmain(int argc, _TCHAR* argv[])
{
int k = 0;
_StartRecord(L".\\Hello1-16000-16.wav");
k = 25;
while (0 < k)
{
printf("Hello1-16000-16 Record...%d\n",k);
Sleep(200);
k --;
}
_EndRecord();
///
_StartRecord(L".\\Hello2-44100-16.wav",2,44100,16);
k = 25;
while (0 < k)
{
printf("Hello2-44100-16 Record...%d\n",k);
Sleep(200);
k --;
}
_EndRecord();
return 0;
}
///