头文件:SoundRecord.h
#ifndef _SOUND_RECORD_H__
#define _SOUND_RECORD_H__
#include
#include
#include
#define MAX_BUFFERS 3
#define m_samplefreq 44100 //采样频率
#define m_channels 2 //通道数
#define m_channelbits 8 //通道字节数
class CSoundRecord
{
public:
CSoundRecord(void);
~CSoundRecord(void);
void startRecording(float time);
void stopRecording();
private:
void printStartInfo(std::string Tip,int time);
void printEndInfo();
static void CALLBACK waveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1,DWORD_PTR dwParam2);
bool initDevice();
void prepareBuffers();
void unPrepareBuffers();
void closeDevice();
void processHeader(WAVEHDR * pHdr);
private:
bool m_bPlay;
HWAVEIN m_hWaveIn;
WAVEFORMATEX m_stWFEX;
WAVEHDR m_stWHDR[MAX_BUFFERS];
HANDLE m_hThread;
HMMIO m_hOPFile;
MMIOINFO m_stmmIF;
MMCKINFO m_stckOut,m_stckOutRIFF;
std::string m_FileName;
int m_Time;
};
#endif // _SOUND_RECORD_H__
#include "SoundRecord.h"
#include
CSoundRecord::CSoundRecord(void):m_bPlay(false),
m_Time(0),
m_hOPFile(nullptr)
{
m_hWaveIn=NULL;
ZeroMemory(&m_stWFEX,sizeof(WAVEFORMATEX));
ZeroMemory(m_stWHDR,MAX_BUFFERS*sizeof(WAVEHDR));
}
CSoundRecord::~CSoundRecord(void)
{
}
bool CSoundRecord::initDevice()
{
MMRESULT mRes=0;
int nT1=0;
m_stWFEX.nSamplesPerSec = m_samplefreq;
m_stWFEX.nAvgBytesPerSec = m_samplefreq * m_channels * m_channelbits / 8;
m_stWFEX.nBlockAlign = m_channels * m_channelbits / 8;
m_stWFEX.nChannels = m_channels;
m_stWFEX.wFormatTag = 0x0001;
m_stWFEX.wBitsPerSample = m_channelbits;
m_stWFEX.cbSize = sizeof(WAVEFORMATEX);
mRes=waveInOpen(&m_hWaveIn,WAVE_MAPPER,&m_stWFEX,(DWORD_PTR)waveInProc,(DWORD_PTR)this,CALLBACK_FUNCTION);
if(mRes!=MMSYSERR_NOERROR)
{
std::cout << "打开音频设备失败...." << std::endl;
return false;
}
SYSTEMTIME sysTime;
GetLocalTime( &sysTime );
char fileName[512];
memset(fileName,0,512);
sprintf_s(fileName,"%d_%d_%d_%d_%d_%d.wav",sysTime.wYear,sysTime.wMonth,sysTime.wDay,sysTime.wHour,sysTime.wMinute,sysTime.wSecond);
ZeroMemory(&m_stmmIF,sizeof(MMIOINFO));
m_FileName = fileName;
std::wstring widstr;
widstr = std::wstring(m_FileName.begin(), m_FileName.end());
LPWSTR ff = (LPWSTR)widstr.c_str();
m_hOPFile=mmioOpen(ff,&m_stmmIF,MMIO_WRITE | MMIO_CREATE);
if(m_hOPFile==NULL)
{
std::cout << "创建文件失败..." << std::endl;
return false;
}
ZeroMemory(&m_stckOutRIFF,sizeof(MMCKINFO));
m_stckOutRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E');
mRes=mmioCreateChunk(m_hOPFile, &m_stckOutRIFF, MMIO_CREATERIFF);
if(mRes!=MMSYSERR_NOERROR)
{
std::cout << "创建RIFF-WAVE数据块失败" << std::endl;
}
ZeroMemory(&m_stckOut,sizeof(MMCKINFO));
m_stckOut.ckid = mmioFOURCC('f', 'm', 't', ' ');
m_stckOut.cksize = sizeof(m_stWFEX);
mRes=mmioCreateChunk(m_hOPFile, &m_stckOut, 0);
if(mRes!=MMSYSERR_NOERROR)
{
std::cout << "创建fmt数据块失败" << std::endl;
}
nT1=mmioWrite(m_hOPFile, (HPSTR) &m_stWFEX, sizeof(m_stWFEX));
if(nT1!=sizeof(m_stWFEX))
{
std::cout << "写音频数据格式失败" << std::endl;
}
mRes=mmioAscend(m_hOPFile, &m_stckOut, 0);
if(mRes!=MMSYSERR_NOERROR)
{
std::cout << "升序排列数据" << std::endl;
}
m_stckOut.ckid = mmioFOURCC('d', 'a', 't', 'a');
mRes=mmioCreateChunk(m_hOPFile, &m_stckOut, 0);
if(mRes!=MMSYSERR_NOERROR)
{
std::cout << "创建data数据块失败" << std::endl;
}
}
void CSoundRecord::closeDevice()
{
MMRESULT mRes=0;
if(m_hWaveIn)
{
unPrepareBuffers();
mRes=waveInClose(m_hWaveIn);
}
if(m_hOPFile)
{
mRes=mmioAscend(m_hOPFile, &m_stckOut, 0);
if(mRes!=MMSYSERR_NOERROR)
{
std::cout << "重定向音频头数据失败" << std::endl;
return ;
}
mRes=mmioAscend(m_hOPFile, &m_stckOutRIFF, 0);
if(mRes!=MMSYSERR_NOERROR)
{
std::cout << "重定向音频数据头失败" << std::endl;
return ;
}
mmioClose(m_hOPFile,0);
m_hOPFile=NULL;
}
m_hWaveIn=NULL;
}
void CSoundRecord::prepareBuffers()
{
MMRESULT mRes=0;
for(int nT1=0;nT18,m_stWFEX.nAvgBytesPerSec);
m_stWHDR[nT1].dwBufferLength=m_stWFEX.nAvgBytesPerSec;
m_stWHDR[nT1].dwUser=nT1;
mRes=waveInPrepareHeader(m_hWaveIn,&m_stWHDR[nT1],sizeof(WAVEHDR));
if(mRes!=0)
{
std::cout << "准备头部数据失败" << std::endl;
return ;
}
mRes=waveInAddBuffer(m_hWaveIn,&m_stWHDR[nT1],sizeof(WAVEHDR));
if(mRes!=0)
{
std::cout << "准备缓存数据失败" << std::endl;
return ;
}
}
}
void CSoundRecord::startRecording(float time)
{
MMRESULT mRes;
m_bPlay = true;
m_Time = time;
try
{
initDevice();
prepareBuffers();
mRes=waveInStart(m_hWaveIn);
if(mRes!=0)
{
std::cout << "无法进行录音" << std::endl;
}
while(m_bPlay)
{
static int i = 0;
printStartInfo("录音开始",i);
SleepEx(100,FALSE);
i++;
}
}
catch(PCHAR pErrorMsg)
{
std::cout << "异常---->"<< pErrorMsg << std::endl;
}
closeDevice();
printEndInfo();
}
void CSoundRecord::stopRecording()
{
m_bPlay = false;
}
void CALLBACK CSoundRecord::waveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1,DWORD_PTR dwParam2)
{
static int count = 0;
CSoundRecord *pSoundRecord = (CSoundRecord*)dwInstance;
if(!pSoundRecord)
return ;
WAVEHDR* hdr = (WAVEHDR*)dwParam1;
if(pSoundRecord->m_Time == count)
{
pSoundRecord->stopRecording();
}
if(uMsg == WIM_DATA)
{
pSoundRecord->processHeader(hdr);
count++;
}
}
void CSoundRecord::processHeader(WAVEHDR * pHdr)
{
MMRESULT mRes=0;
if(WHDR_DONE==(WHDR_DONE &pHdr->dwFlags))
{
mmioWrite(m_hOPFile,pHdr->lpData,pHdr->dwBytesRecorded);
mRes=waveInAddBuffer(m_hWaveIn,pHdr,sizeof(WAVEHDR));
if(mRes!=0)
{
std::cout << "file: " << __FILE__ << "Line Number: " << __LINE__ << std::endl;
}
}
}
void CSoundRecord::unPrepareBuffers()
{
MMRESULT mRes=0;
int nT1=0;
if(m_hWaveIn)
{
mRes=waveInStop(m_hWaveIn);
for(nT1=0;nT1<3;++nT1)
{
if(m_stWHDR[nT1].lpData)
{
mRes=waveInUnprepareHeader(m_hWaveIn,&m_stWHDR[nT1],sizeof(WAVEHDR));
HeapFree(GetProcessHeap(),0,m_stWHDR[nT1].lpData);
ZeroMemory(&m_stWHDR[nT1],sizeof(WAVEHDR));
}
}
}
}
void CSoundRecord::printStartInfo(std::string Tip,int time)
{
static bool bfirst = true;
if(bfirst)
{
std::cout << "************************"<< std::endl;
std::cout << Tip << std::endl;
bfirst = false;
}
COORD coord = { 0, 4 };
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
float per = (float)time / 100;
std::cout<<"录音进度: "<< per << " %";
std::cout << std::endl;
}
void CSoundRecord::printEndInfo()
{
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
std::cout<<"录音结束"<<std::endl;
std::cout << "************************"<< std::endl;
COORD coord1 = { 0, 8} ;
info.dwCursorPosition = coord1;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), info.dwCursorPosition);
}
调用: main
CSoundRecord* pSound = new CSoundRecord;
std::cout << "请输入时间,单位:秒" << std::endl;
int time;
std::cin >> time;
pSound->startRecording(time);
结果图: