本文属spanzhang原创,其blog地址为:http://blog.csdn.net/spanzhang。引用或转贴请注明出处,谢谢!!
/*/////////////////////////////////////////////////////////////////////
文件:waveRecorder.cpp
描述:录音类实现文件
作者:张友邦
时间:2004-09-10
声明:本文件系作者辛苦熬夜的产物,任何人使用本文件请保留本描述文本。
历史:
/*/////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////// #include "stdAfx.h" #include "waveRecorder.h" #include "graphSeed.h"
////////////////////////////////////////////////////////////////////// // Constructions/Destruction namespace wa { //////////////////////////////////////////////////////////////////////
#define MAXINPUTBUFFERS 25 #define BUFFERSIZE 1024 * 1
float waveRecorder::sampleCoef = 1.0;
waveRecorder::waveRecorder() { memset(&waveFormat, 0x00, sizeof(WAVEFORMATEX)); waveFormat.wFormatTag = WAVE_FORMAT_PCM; waveFormat.nChannels = 1; waveFormat.wBitsPerSample = 8; waveFormat.cbSize = 0; waveFormat.nSamplesPerSec = 44100; waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec *(waveFormat.wBitsPerSample>>3); waveFormat.nBlockAlign = (waveFormat.wBitsPerSample>>3)* waveFormat.nChannels;
status = E_STATUS_STOPED; sampleCoef = 1.0; }
waveRecorder::waveRecorder(const WAVEFORMATEX& waveFormatConfig) { waveFormat = waveFormatConfig;
status = E_STATUS_STOPED; sampleCoef = 1.0; }
waveRecorder::waveRecorder(const int& frequency, const int& channels) { memset(&waveFormat, 0x00, sizeof(WAVEFORMATEX)); waveFormat.wFormatTag = WAVE_FORMAT_PCM; waveFormat.nChannels = channels; waveFormat.wBitsPerSample = 16; waveFormat.cbSize = 0; waveFormat.nSamplesPerSec = frequency; waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec *(waveFormat.wBitsPerSample>>3); waveFormat.nBlockAlign = (waveFormat.wBitsPerSample>>3)* waveFormat.nChannels;
status = E_STATUS_STOPED; sampleCoef = 1.0; }
waveRecorder::~waveRecorder() { try { stop(); } catch (...) { } }
float waveRecorder::constraint(char v) { if (v == -128) return 127.0 * sampleCoef;
return float(v) * sampleCoef; }
void waveRecorder::smooth(char* input, int* output, int length, double smoothness/* = 0.8*/, int scale /*= 100*/) { double a = 1.0 - (2.4 / scale); double b = smoothness; double acoef = a; double bcoef = a * b; double ccoef = a * b * b; double mastergain = 1.0 / (-1.0 / (log(a) + 2.0 * log(b)) + 2.0 / (log(a) + log(b)) - 1.0 / log(a)); double again = mastergain; double bgain = mastergain * (log(a * b * b) * (log(a) - log(a * b)) / ((log(a * b * b) - log(a * b)) * log(a * b)) - log(a) / log(a * b)); double cgain = mastergain * (-(log(a) - log(a * b)) / (log(a * b * b) - log(a * b)));
double areg = 0; double breg = 0; double creg = 0;
//第一次循环,取得reg的平均值 for (int j = 0; j < length; ++j) { float v = constraint(input[j]);
areg = acoef * areg + v; breg = bcoef * breg + v; creg = ccoef * creg + v; }
//得到基音 float base = again * areg + bgain * breg + cgain * creg; output[0] = base;
//用基音作为其始作循环得到其他数据 for (int i = 1; i < length; ++i) { int v = constraint(input[i - 1]);
areg = acoef * areg + v; breg = bcoef * breg + v; creg = ccoef * creg + v;
output[i] = again * areg + bgain * breg + cgain * creg - base; } }
void CALLBACK waveRecorder::waveInProc ( HWAVEIN hwi, //音频设备句柄 UINT uMsg, //消息标识 DWORD dwInstance, //用户定义数据 DWORD dwParam1, //消息参数 DWORD dwParam2 //消息参数 ) { //过滤消息(只处理数据消息) if (uMsg != WIM_DATA) return;
//取得参数值 waveRecorder* me = (waveRecorder*)(dwInstance); LPWAVEHDR lpHdr = (LPWAVEHDR)(dwParam1);
//对数据作低通滤波 if (lpHdr->dwBufferLength >= WAVE_BUFFER_LENGTH && ::WaitForSingleObject(pb::eventMutex, INFINITE) == WAIT_OBJECT_0) { smooth(lpHdr->lpData, gs::graphSeed::lowpassWave, WAVE_BUFFER_LENGTH, 0.9999, 100);
::ReleaseMutex(pb::eventMutex); }
//准备新缓冲 if (me->status == E_STATUS_STARTED) { HWAVEIN& hRecord = me->hRecord; ::waveInUnprepareHeader(hRecord, lpHdr, sizeof(WAVEHDR)); ::waveInPrepareHeader(hRecord, lpHdr, sizeof(WAVEHDR)); ::waveInAddBuffer(hRecord, lpHdr, sizeof(WAVEHDR)); } else { safeDelete(lpHdr->lpData); safeDelete(lpHdr); } }
//开始 void waveRecorder::start() throw (std::exception) { if(status == E_STATUS_STARTED) return;
//打开音频设备 MMRESULT mmReturn = ::waveInOpen ( &hRecord, WAVE_MAPPER, &waveFormat, (DWORD)(waveRecorder::waveInProc), (DWORD)(this), CALLBACK_FUNCTION ); switch(mmReturn) { case MMSYSERR_NOERROR: //成功 break;
case MMSYSERR_ALLOCATED: throw std::exception("Specified resource is already allocated.");
case MMSYSERR_BADDEVICEID: throw std::exception("Specified device identifier is out of range.");
case MMSYSERR_NODRIVER: throw std::exception("No device driver is present.");
case MMSYSERR_NOMEM: throw std::exception("Unable to allocate or lock memory.");
case WAVERR_BADFORMAT: throw std::exception("Attempted to open with an unsupported waveform-audio format."); default: throw std::exception("Unknown error occured."); } //加入缓冲 for (int i = 0; i < MAXINPUTBUFFERS; ++i) { LPWAVEHDR lpHdr = new WAVEHDR; memset(lpHdr, 0x00, sizeof(WAVEHDR)); lpHdr->lpData = new char[BUFFERSIZE]; lpHdr->dwBufferLength = BUFFERSIZE; MMRESULT mmReturn = ::waveInPrepareHeader(hRecord, lpHdr, sizeof(WAVEHDR)); if (mmReturn != MMSYSERR_NOERROR) //Memory leaks throw std::exception("waveInPrepareHeader error in startRedording."); mmReturn = ::waveInAddBuffer(hRecord, lpHdr, sizeof(WAVEHDR)); if (mmReturn != MMSYSERR_NOERROR) //Memory leaks throw std::exception("waveInAddBuffer error in startRedording."); }
//开始录音 mmReturn = ::waveInStart(hRecord); if (mmReturn != MMSYSERR_NOERROR) { throw std::exception("waveInStart error."); }
status = E_STATUS_STARTED; }
//停止录音 void waveRecorder::stop() throw (std::exception) { if(status != E_STATUS_STARTED) return; //停止录音 MMRESULT mmReturn = ::waveInStop(hRecord); switch(mmReturn) { case MMSYSERR_NOERROR: //成功 break; case MMSYSERR_INVALHANDLE: throw std::exception("Specified device handle is invalid."); break;
case MMSYSERR_NODRIVER: throw std::exception("No device driver is present."); break;
case MMSYSERR_NOMEM: throw std::exception("Unable to allocate or lock memory."); break; default: throw std::exception("Unknown error occured."); }
status = E_STATUS_STOPED;
//重置设备 //DEL_CODE //(<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< mmReturn = ::waveInReset(hRecord); switch(mmReturn) { case MMSYSERR_NOERROR: //成功 break; case MMSYSERR_INVALHANDLE: throw std::exception("Specified device handle is invalid."); case MMSYSERR_NODRIVER: throw std::exception("No device driver is present."); case MMSYSERR_NOMEM: throw std::exception("Unable to allocate or lock memory."); default: throw std::exception("Unknown error occured."); } //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>)
//关闭设备 mmReturn = ::waveInClose(hRecord); switch(mmReturn) { case MMSYSERR_NOERROR: //成功 break; case MMSYSERR_INVALHANDLE: throw std::exception("Specified device handle is invalid."); break; case MMSYSERR_NODRIVER: throw std::exception("No device driver is present."); break; case MMSYSERR_NOMEM: throw std::exception("Unable to allocate or lock memory."); break; case WAVERR_STILLPLAYING: throw std::exception("There are still buffers in the queue."); break;
default: throw std::exception("Unknown error occured."); }
status = E_STATUS_STOPED; }
////////////////////////////////////////////////////////////////////// }; //namespace wa ////////////////////////////////////////////////////////////////////// //End of this file. 
|