实现录音和播放 使用wave系列函数

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;//文件保存路径
};

cpp
//---------------------------------------------------------------------------


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


你可能感兴趣的:(c++,builder学习)