1 头文件
class TVoiceRecord
{
public:
TVoiceRecord(AnsiString path);
~TVoiceRecord();
int RecordOpen();//打开录音设备
int RecordStart();//开始录音
void RecordStop();//停止录音
bool RecordPlay();//播放声音
bool RecordSave(DWORD dwParam2);//保存
void STopPlay();
BOOL bEnding;
HANDLE Handle;
private:
HWAVEIN hWaveIn;
HWAVEOUT hWaveOut;
PBYTE pBuffer1,pBuffer2,pSaveBuffer,pNewBuffer;
PWAVEHDR pWaveHdr1,pWaveHdr2; //音频数据块缓存结构体
WAVEFORMATEX waveform;
DWORD dwDataLength;
AnsiString FilePath;//文件保存路径
};
//---------------------------------------------------------------------------
#pragma hdrstop
#include
#include
#include "uVoiceRecord.h"
//---------------------------------------------------------------------------
short g_RecordvoiceVal;
#pragma package(smart_init)
#define INP_BUFFER_SIZE 2048
//MM_WIM_OPEN:打开设备时消息,在此期间我们可以进行一些初始化工作
//MM_WIM_DATA:当缓存已满或者停止录音时的消息,处理这个消息可以对缓存进行重新分配,实现不限长度录音
//MM_WIM_CLOSE:关闭录音设备时的消息
//MM_WIM_DONE 一个缓冲区播放完毕后调用
//(MM_WIM_OPEN,MM_WIM_DATA,MM_WIM_CLOSE,MM_WIM_DONE) 对应窗体事件,若选择CALLBACk_FUNCTION,则消息为wim_
bool CALLBACK VoiceWaveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);
TVoiceRecord::TVoiceRecord(AnsiString path)
{
dwDataLength=0;
pWaveHdr1=reinterpret_cast(malloc(sizeof(WAVEHDR)));
pWaveHdr2=reinterpret_cast(malloc(sizeof(WAVEHDR)));
//allocate memory for save buffer
pSaveBuffer = reinterpret_cast(malloc(1));
bEnding = FALSE;
FilePath = path;
}
TVoiceRecord::~TVoiceRecord()
{
if(pBuffer1 != NULL)
free(pBuffer1);
if(pBuffer2 != NULL)
free(pBuffer2);
if(pWaveHdr1 != NULL)
free(pWaveHdr1);
if(pWaveHdr2 != NULL)
free(pWaveHdr2);
if(pSaveBuffer != NULL)
free(pSaveBuffer);
}
int TVoiceRecord::RecordOpen() //打开录音设备开始录音
{
pBuffer1 = (PBYTE)malloc(INP_BUFFER_SIZE);
pBuffer2 = (PBYTE)malloc(INP_BUFFER_SIZE);
if(!pBuffer1 || !pBuffer2)
{
if(pBuffer1 != NULL)
{
free(pBuffer1);
pBuffer1 = NULL;
}
if(pBuffer2 != NULL)
{
free(pBuffer2);
pBuffer2 = NULL;
}
return 0;
}
waveform.wFormatTag=WAVE_FORMAT_PCM;
waveform.nChannels=1; //声道数
waveform.nSamplesPerSec=8000;//速率 采样率
waveform.nAvgBytesPerSec=16000;//
waveform.nBlockAlign=2; // 数据块调整度(块对其,字节),其值为通道数*样本的数据位值/8,
waveform.wBitsPerSample=16;//每秒样本位数
waveform.cbSize=0; //结构体大小
if(waveInOpen(&hWaveIn,WAVE_MAPPER,&waveform,(DWORD)VoiceWaveInProc,(DWORD)this,CALLBACK_FUNCTION))
{
free(pBuffer1);
free(pBuffer2);
return 0;
}
pWaveHdr1->lpData=(LPTSTR)pBuffer1; //数据缓存区指针
pWaveHdr1->dwBufferLength=INP_BUFFER_SIZE;//数据缓存区大小
pWaveHdr1->dwBytesRecorded=0;//缓存区的数据量
pWaveHdr1->dwUser=0; //用户数据
pWaveHdr1->dwFlags=0;//缓存区信息标志
pWaveHdr1->dwLoops=1;//循环播放次数
pWaveHdr1->lpNext=NULL;
pWaveHdr1->reserved=0;
waveInPrepareHeader(hWaveIn,pWaveHdr1,sizeof(WAVEHDR)); //音频格式头初始化
pWaveHdr2->lpData =(LPTSTR)pBuffer2;
pWaveHdr2->dwBufferLength = INP_BUFFER_SIZE;
pWaveHdr2->dwBytesRecorded = 0;
pWaveHdr2->dwUser = 0;
pWaveHdr2->dwFlags = 0;
pWaveHdr2->dwLoops = 1;
pWaveHdr2->lpNext = NULL;
pWaveHdr2->reserved = 0;
waveInPrepareHeader(hWaveIn,pWaveHdr2,sizeof(WAVEHDR));
pSaveBuffer = (PBYTE)realloc(pSaveBuffer, 1) ;
waveInAddBuffer (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ; //音频格式头加入录音队列
waveInAddBuffer (hWaveIn, pWaveHdr2, sizeof (WAVEHDR)) ;
dwDataLength = 0;
bEnding = FALSE;
return 1;
}
int TVoiceRecord::RecordStart()//开始录音
{
return waveInStart(hWaveIn);
}
void TVoiceRecord::RecordStop() //停止录音
{
bEnding = TRUE;
waveInReset(hWaveIn);
waveInUnprepareHeader (hWaveIn, pWaveHdr1, sizeof (WAVEHDR)) ;
waveInUnprepareHeader(hWaveIn,pWaveHdr2,sizeof(WAVEHDR));
waveInClose(hWaveIn);
}
bool TVoiceRecord::RecordPlay() // 播放声音
{
waveform.wFormatTag =WAVE_FORMAT_PCM;
waveform.nChannels =1;
waveform.nSamplesPerSec =8000;
waveform.nAvgBytesPerSec=8000*2;
waveform.nBlockAlign =2;
waveform.wBitsPerSample =16;
waveform.cbSize =0;
if (waveOutOpen(&hWaveOut,WAVE_MAPPER,&waveform,NULL,NULL,CALLBACK_FUNCTION))
{
return 0;
}
pWaveHdr1->lpData = (LPTSTR)pSaveBuffer ;
pWaveHdr1->dwBufferLength = dwDataLength ;
pWaveHdr1->dwBytesRecorded = 0 ;
pWaveHdr1->dwUser = 0 ;
pWaveHdr1->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP ;
pWaveHdr1->dwLoops = 1;
pWaveHdr1->lpNext = NULL ;
pWaveHdr1->reserved = 0 ;
waveOutPrepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
waveOutWrite (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
return 1;
}
bool CALLBACK VoiceWaveInProc(HWAVEIN hwi, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
if (uMsg == WIM_DATA)
{
LPWAVEHDR pHdr = (LPWAVEHDR) dwParam1;
g_RecordvoiceVal = *(short *) pHdr->lpData;
g_RecordvoiceVal *= 0.6;
TVoiceRecord *pVoice=(TVoiceRecord*) dwInstance;
if(pVoice->bEnding == TRUE)
{
return 0;
}
::PostMessage(pVoice->Handle,WM_MY_DRAW,dwParam1,NULL);
pVoice->RecordSave(dwParam1);
}
return true;
}
bool TVoiceRecord::RecordSave(DWORD dwParam2)
{
pNewBuffer = (PBYTE)realloc (pSaveBuffer, dwDataLength +((PWAVEHDR) dwParam2)->dwBytesRecorded) ;
if (pNewBuffer == NULL)
{
waveInClose (hWaveIn) ;
return 0;
}
pSaveBuffer = pNewBuffer;
CopyMemory (pSaveBuffer + dwDataLength, ((PWAVEHDR) dwParam2)->lpData,((PWAVEHDR) dwParam2)->dwBytesRecorded) ;
dwDataLength += ((PWAVEHDR) dwParam2)->dwBytesRecorded ;
TFileStream *stream = new TFileStream(FilePath,fmCreate);
DWORD m_WaveHeaderSize = 40;
DWORD m_WaveFormatSize = 20;
unsigned int Sec=(dwDataLength + m_WaveHeaderSize);
stream->Seek(0,soFromBeginning);
stream->Write("RIFF",4);
stream->Write(&Sec,sizeof(Sec));
stream->Write("WAVE",4);
stream->Write("fmt ",4);
stream->Write(&m_WaveFormatSize,sizeof(m_WaveFormatSize));
stream->Write(&waveform.wFormatTag,sizeof(waveform.wFormatTag));
stream->Write(&waveform.nChannels,sizeof(waveform.nChannels));
stream->Write(&waveform.nSamplesPerSec,sizeof(waveform.nSamplesPerSec));
stream->Write(&waveform.nAvgBytesPerSec,sizeof(waveform.nAvgBytesPerSec));
stream->Write(&waveform.nBlockAlign,sizeof(waveform.nBlockAlign));
stream->Write(&waveform.wBitsPerSample,sizeof(waveform.wBitsPerSample));
stream->Write(&waveform.cbSize,sizeof(waveform.cbSize));
int tt = 0;
stream->Write(&tt,2);
stream->Write("data",4);
stream->Write(&dwDataLength,sizeof(dwDataLength));
stream->Write(pSaveBuffer,dwDataLength);
stream->Seek(dwDataLength,soFromBeginning);
delete stream;
waveInAddBuffer (hWaveIn, (PWAVEHDR)dwParam2, sizeof(WAVEHDR));
return 1;
}
void TVoiceRecord::STopPlay()
{
waveOutUnprepareHeader (hWaveOut, pWaveHdr1, sizeof (WAVEHDR)) ;
waveOutReset(hWaveOut);
waveOutClose(hWaveOut);
}