Pedal Point源码发布及说明(6)

类别:VC语言 点击:0 评论:0 推荐:

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

本文地址:http://com.8s8s.com/it/it246.htm