📄 lcywaveinlib.cpp
字号:
#include "stdafx.h"
#include <mmsystem.h>
/**********数据及函数说明开始,可作为头文件的开始*********/
//读每个缓冲区的最小时间(毫秒)。
const int LCY_MIN_MSEm_PER_HOST_BUFFER=10;
//读每个缓冲区的最大时间(毫秒),不要超过此数。
const int LCY_MAX_MSEm_PER_HOST_BUFFER=100;
//最小缓冲区数。
const int LCY_MIN_NUM_HOST_BUFFERS=4;
//最大缓冲区数,如果需要可加大此数。
const int LCY_MAX_NUM_HOST_BUFFERS=16;
//有错误标志
bool err=1;
//无错误标志
bool Noerr=0;
//该程序内声卡已打开标志
bool Opened=0;
//声卡关闭的次数
UINT NumsClosed=0;
//开辟内存的次数
int NumsNew=0;
//16位整数的采样格式。
#define LCYInt16 ((unsigned long) (1<<1))
/*回调函数类型说明
inputBuffer :输入缓冲区指针。
framesPerBuffer:每次采样数据帧数。
*/
typedef int (PortAudioCallback)(
void *inputBuffer,
unsigned long framesPerBuffer);
//结构数据,用于存储各个变量。
struct AudioStream
{
unsigned long m_FramesPerUserBuffer;
unsigned long m_InputSampleFormat;
double m_SampleRate;
int m_NumInputChannels;
int m_CurrentInputBuffer;
int m_BytesPerHostInputBuffer;
int m_BytesPerUserInputBuffer;
int m_NumHostBuffers;
int m_UserBuffersPerHostBuffer;
volatile int m_IsActive;
HWAVEIN m_HWaveIn;
WAVEHDR *m_InBuffersPr;
PortAudioCallback *m_Callback;
};
AudioStream *st=NULL;
//开始采集输入端数据函数子函数
int SUB_StartInStream( void );
//打开声卡输入端函数子函数
bool SUB_OpenInputStream(void);
//计算所需缓冲区数函数
void LCY_CalcNumHostBuffers(void);
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*打开声卡输入端函数及参数说明:
numInputChannels:设置声道数,1时,单声道;2时,双声道。
sampleRate:设置采样频率,1KHz至200KHz。
framesPerBuffer:每次采样数据帧数。
callback:回调函数指针。*/
bool LCY_OpenSoundCardIn(
int numInputChannels,
double sampleRate,
unsigned long framesPerBuffer,
PortAudioCallback *callback);
//关闭声卡输入端函数
int LCY_CloseSoundCardIn(void );
//开始采集输入端数据函数
bool LCY_StartInStream( void );
#ifdef __cplusplus
}
#endif /* __cplusplus */
/**********数据及函数说明结束,可作为头文件的结束*********/
/********************定义函数*****************************/
/*打开声卡输入端函数*/
bool LCY_OpenSoundCardIn(
int numInputChannels,
double sampleRate,
unsigned long framesPerBuffer,
PortAudioCallback *callback)
{
st = NULL;
/*检验参数错误*/
if(waveInGetNumDevs()<=0){
MessageBox (0, "系统没有声卡", "系统设备错误",
MB_ICONEXCLAMATION | MB_OK);
return err;
}
if( numInputChannels <= 0 ){
MessageBox (0, "声道数必须大于0",
"声卡声道数设置错误",MB_ICONEXCLAMATION | MB_OK);
return err;
}
if( (sampleRate < 1000.0) || (sampleRate > 200000.0) ){
MessageBox (0, "采样频率必须是1KHz——200kHz",
"声卡采样频率设置错误",MB_ICONEXCLAMATION | MB_OK);
return err;
}
if(framesPerBuffer<=0){
MessageBox (0, "设置的声卡缓冲区数必须大于等于1",
"声卡声卡缓冲区数设置错误",MB_ICONEXCLAMATION | MB_OK);
return err;
}
if( callback == NULL ){
MessageBox (0, "回调函数指针不能为空",
"程序设计错误",MB_ICONEXCLAMATION | MB_OK);
return err;
}
if( Opened != 0 ){
MessageBox (0, "声卡已打开,要重新打开,请先关闭,再打开。",
"打开声卡错误",MB_ICONEXCLAMATION | MB_OK);
return err;
}
Opened = 1;
/*开辟内存*/
st=new AudioStream;
if( st == NULL ){
MessageBox (0, "开辟内存失败",
"开辟内存错误",MB_ICONEXCLAMATION | MB_OK);
goto cleanup;
}
NumsNew=1;NumsClosed=0;
/*初始化数据流结构*/
st->m_FramesPerUserBuffer = framesPerBuffer;
st->m_Callback = callback;
st->m_InputSampleFormat = LCYInt16;
st->m_NumInputChannels = numInputChannels;
st->m_SampleRate = sampleRate;
/*调计算所需用户缓冲区数函数*/
LCY_CalcNumHostBuffers( );
st->m_BytesPerUserInputBuffer = st->m_FramesPerUserBuffer *
st->m_NumInputChannels * sizeof(short);
st->m_BytesPerHostInputBuffer = st->m_UserBuffersPerHostBuffer*
st->m_BytesPerUserInputBuffer;
if(SUB_OpenInputStream()!=Noerr)
goto cleanup;
return Noerr;
cleanup:
LCY_CloseSoundCardIn( );
return err;
}
/*打开输入端数据流子函数*/
bool SUB_OpenInputStream( )
{
MMRESULT mmresult;
int i,bytesPerInputFrame;
WAVEFORMATEX wfx;
/*设定打开数据流参数*/
bytesPerInputFrame = sizeof(short) * st->m_NumInputChannels;
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = (WORD) st->m_NumInputChannels;
wfx.nSamplesPerSec = (DWORD) st->m_SampleRate;
wfx.nAvgBytesPerSec = (DWORD)(bytesPerInputFrame * st->
m_SampleRate);
wfx.nBlockAlign = (WORD)bytesPerInputFrame;
wfx.wBitsPerSample = (WORD)((bytesPerInputFrame/st->
m_NumInputChannels) * 8);
wfx.cbSize = 0;
mmresult=waveInOpen( &st->m_HWaveIn, WAVE_MAPPER, &wfx,0,(DWORD) st, 0 );
if(MMSYSERR_NOERROR!=mmresult){
if(mmresult==MMSYSERR_ALLOCATED){
MessageBox (0, "其他程序正在使用声卡,请关闭其他程序",
"声卡打开错误",MB_ICONEXCLAMATION | MB_OK);
}
goto cleanup;
}
/*开辟存储指针缓冲区*/
if(st!=NULL)
st->m_InBuffersPr =NULL;
st->m_InBuffersPr =new WAVEHDR[st->m_NumHostBuffers];
if(st->m_InBuffersPr==NULL) goto cleanup;
memset( st->m_InBuffersPr, 0, sizeof(WAVEHDR)*st->m_NumHostBuffers );
NumsNew=2;
/*开辟存储各个指针的缓冲区*/
if(st!=NULL)
for( i=0; i<st->m_NumHostBuffers; i++ )
st->m_InBuffersPr[i].lpData =NULL;
for( i=0; i<st->m_NumHostBuffers; i++ ){
st->m_InBuffersPr[i].lpData =new char[st->m_BytesPerHostInputBuffer];
if( st->m_InBuffersPr[i].lpData == NULL ){
goto cleanup;
}
NumsNew=3;
st->m_InBuffersPr[i].dwBufferLength =st->m_BytesPerHostInputBuffer;
st->m_InBuffersPr[i].dwUser = i;
st->m_InBuffersPr[i].dwFlags = 0;
st->m_InBuffersPr[i].dwLoops = 0;
if(st->m_HWaveIn)
if( (MMSYSERR_NOERROR!=waveInPrepareHeader( st->m_HWaveIn, &st->
m_InBuffersPr[i],sizeof(WAVEHDR) ))){
goto cleanup;
}
}
return Noerr;
cleanup:
LCY_CloseSoundCardIn( );
return err;
}
/*开始采集输入端数据函数*/
bool LCY_StartInStream( )
{
if(st->m_HWaveIn){
for(int i=0; i<st->m_NumHostBuffers; i++ ){
if(MMSYSERR_NOERROR!=waveInAddBuffer( st->m_HWaveIn,
&st->m_InBuffersPr[i], sizeof(WAVEHDR))){
goto cleanup;
}
}
if(MMSYSERR_NOERROR!=waveInStart( st->m_HWaveIn )){
goto cleanup;
}
st->m_IsActive = 1;
}
SUB_StartInStream( );
if(st->m_HWaveIn){
if(MMSYSERR_NOERROR!=waveInReset( st->m_HWaveIn )){
goto cleanup;
}
}
return Noerr;
cleanup:
LCY_CloseSoundCardIn( );
return err;
}
/*开始采集输入端数据函数子函数*/
int SUB_StartInStream( )
{
int gotInput = 0,done = 0,result = 0;
char *inBufPtr;
st->m_CurrentInputBuffer = 0;
while(st->m_IsActive){
while(!done){
gotInput = 0;
inBufPtr = NULL;
if(st->m_InBuffersPr[st->m_CurrentInputBuffer]
.dwFlags & WHDR_DONE){
inBufPtr = st->m_InBuffersPr[st->m_CurrentInputBuffer].lpData;
gotInput = 1;
}
if( !gotInput ) break;
for(int i=0; i<st->m_UserBuffersPerHostBuffer; i++ ){
if(!done ){
//调回调函数
result = st->m_Callback(
(short *) inBufPtr,
st->m_FramesPerUserBuffer);
if( result != 0) done = 1;
}
if( gotInput ) inBufPtr += st->m_BytesPerUserInputBuffer;
}
if( gotInput ){
if(st->m_HWaveIn)
if(MMSYSERR_NOERROR!=waveInAddBuffer( st->m_HWaveIn,
&st->m_InBuffersPr[ st->m_CurrentInputBuffer ],
sizeof(WAVEHDR) )){
result = 8;break;
}
st->m_CurrentInputBuffer = (st->m_CurrentInputBuffer
+1>=st->m_NumHostBuffers) ?0 : st->
m_CurrentInputBuffer+1;
}
}
result=(result != 0) ? result : done;
if(result!=0) st->m_IsActive = 0;
}
return result;
}
/*关闭声卡输入端函数*/
int LCY_CloseSoundCardIn( )
{
int i,result=0;
if(NumsClosed==0&&st!=NULL){
switch(NumsNew){
case 3:
for(i=0; i<st->m_NumHostBuffers; i++ ){
if(st->m_InBuffersPr[i].lpData != NULL )
delete st->m_InBuffersPr[i].lpData;
}
case 2:
if(st->m_InBuffersPr!=NULL)
delete st->m_InBuffersPr;
case 1:
if( st->m_HWaveIn!=NULL){
if(MMSYSERR_NOERROR!=waveInReset( st->m_HWaveIn ))result=1;
if(MMSYSERR_NOERROR!=waveInClose( st->m_HWaveIn ))result=1;
}
delete st;
}
Opened = 0;
}
NumsClosed++;
return result;
}
/*计算所需缓冲区数*/
void LCY_CalcNumHostBuffers( )
{
int minFramesPerHostBuffer;
int maxFramesPerHostBuffer;
int minTotalFrames;
int userBuffersPerHostBuffer;
int framesPerHostBuffer;
int numHostBuffers;
//计算缓冲区最大和最小数
minFramesPerHostBuffer = (int) (LCY_MIN_MSEm_PER_HOST_BUFFER *
st->m_SampleRate / 1000.0);
minFramesPerHostBuffer = (minFramesPerHostBuffer + 7) & ~7;
maxFramesPerHostBuffer = (int) (LCY_MAX_MSEm_PER_HOST_BUFFER *
st->m_SampleRate / 1000.0);
maxFramesPerHostBuffer = (maxFramesPerHostBuffer + 7) & ~7;
minTotalFrames = 2 * st->m_FramesPerUserBuffer;
if( (int) st->m_FramesPerUserBuffer < minFramesPerHostBuffer ){
userBuffersPerHostBuffer =(minFramesPerHostBuffer + st->
m_FramesPerUserBuffer - 1) /st->m_FramesPerUserBuffer;
}
else{userBuffersPerHostBuffer = 1;}
framesPerHostBuffer = st->m_FramesPerUserBuffer *
userBuffersPerHostBuffer;
//计算实际需要的缓冲区数
numHostBuffers = (minTotalFrames + framesPerHostBuffer - 1) /
framesPerHostBuffer;
//确认有足够的缓冲区数
if( numHostBuffers < LCY_MIN_NUM_HOST_BUFFERS){
numHostBuffers = LCY_MIN_NUM_HOST_BUFFERS;
}
else if( (numHostBuffers > LCY_MAX_NUM_HOST_BUFFERS) &&
((int) st->m_FramesPerUserBuffer <
(maxFramesPerHostBuffer/2) ) ){
//如果需要更多的缓冲区数,增加缓冲区数
while(numHostBuffers > LCY_MAX_NUM_HOST_BUFFERS){
userBuffersPerHostBuffer += 1;
framesPerHostBuffer = st->m_FramesPerUserBuffer *
userBuffersPerHostBuffer;
numHostBuffers = (minTotalFrames + framesPerHostBuffer - 1)/
framesPerHostBuffer;
//如果缓冲区数太大,就减少缓冲区数
if( (framesPerHostBuffer > maxFramesPerHostBuffer) ||
(numHostBuffers < LCY_MAX_NUM_HOST_BUFFERS) ){
userBuffersPerHostBuffer -= 1;
framesPerHostBuffer = st->m_FramesPerUserBuffer *
userBuffersPerHostBuffer;
numHostBuffers = (minTotalFrames + framesPerHostBuffer - 1)/
framesPerHostBuffer;
break;
}
}
}
st->m_UserBuffersPerHostBuffer = userBuffersPerHostBuffer;
st->m_NumHostBuffers = numHostBuffers;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -