本文属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.