⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcywaveinlib.cpp

📁 该程序是在VC++6.0环境中
💻 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 + -