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

📄 jvoipsoundcardinput.cpp

📁 使用VOIP进行网络传输声音的类库
💻 CPP
字号:
/*    This file is a part of JVOIPLIB, a library designed to facilitate    the use of Voice over IP (VoIP).    Copyright (C) 2000-2004  Jori Liesenborgs (jori@lumumba.luc.ac.be)    This library (JVOIPLIB) is based upon work done for my thesis at    the School for Knowledge Technology (Belgium/The Netherlands)    This file was developed at the 'Expertise Centre for Digital    Media' (EDM) in Diepenbeek, Belgium (http://www.edm.luc.ac.be).    The EDM is a research institute of the 'Limburgs Universitair    Centrum' (LUC) (http://www.luc.ac.be).    The full GNU Library General Public License can be found in the    file LICENSE.LGPL which is included in the source code archive.    This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Library General Public    License as published by the Free Software Foundation; either    version 2 of the License, or (at your option) any later version.    This library is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    Library General Public License for more details.    You should have received a copy of the GNU Library General Public    License along with this library; if not, write to the Free    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307    USA*/#include "jvoipconfig.h"#include "jvoipsoundcardinput.h"#include "jvoiperrors.h"#include "debugnew.h"#define JVOIPSOUNDCARDINPUT_TOTALBUFFERTIME				10000#define JVOIPSOUNDCARDINPUT_EXTRABLOCKSIZE				32#define JVOIPSOUNDCARDINPUT_DRVBYTESPERSAMPLE					2#define JVOIPSOUNDCARDINPUT_DRVSTEREO						1#define JVOIPSOUNDCARDINPUT_DRVLITTLEENDIAN					true#define JVOIPSOUNDCARDINPUT_DRVSIGNED						trueJVOIPSoundcardInput::JVOIPSoundcardInput(JVOIPSession *sess) throw (JVOIPException) : JVOIPVoiceInput(sess){	init = false;	sounddev = NULL;	if (sigwait.Init() < 0)		throw JVOIPException(ERR_JVOIPLIB_GENERAL_CANTINITSIGWAIT);}JVOIPSoundcardInput::~JVOIPSoundcardInput(){	Cleanup();}int JVOIPSoundcardInput::Init(int sampinterval,int inputsamprate,int inputbytespersample,const JVOIPComponentParams *componentparams){	JVOIPSoundcardInputParams defparams,*usrparams;	int status;	if (init)		return ERR_JVOIPLIB_GENERAL_COMPONENTALREADYINIT;		usrparams = dynamic_cast<JVOIPSoundcardInputParams*>(const_cast<JVOIPComponentParams*>(componentparams));	if (usrparams == NULL)		usrparams = &defparams;	nastyresetbug = usrparams->GetNastyResetBugFix();	if ((status = OpenSoundDevice(CalculateDriveSampleRate(inputsamprate))) < 0)		return status;	sampleinterval = sampinterval;	samprate = inputsamprate;	bytespersample = inputbytespersample;		if ((status = InitBuffers()) < 0)	{		if (sounddev != NULL)			waveInClose(sounddev);		sounddev = NULL;		return status;	}	InitSampleConverter();			sigwait.ClearSignalBuffers();			init = true;	firsttime = true;	resetting = false;	return 0;}int JVOIPSoundcardInput::Cleanup(){	if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	Reset();	ClearBuffers();	if (sounddev != NULL)		waveInClose(sounddev);	sounddev = NULL;	init = false;	return 0;}int JVOIPSoundcardInput::StartSampling(){	int i,size,numsamp;	double diff;		if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;		if (firsttime)	{		firsttime = false;		srcsampletime = 0;		wantedsrcsampletime = 0;				for (i = 0 ; i < numblocks ; i++)		{			wantedsrcsampletime += (double)sampleinterval;			diff = wantedsrcsampletime-srcsampletime;			diff /= 1000.0; // convert to seconds			numsamp = (int)(diff*(double)drvsamprate+0.5);			size = numsamp*JVOIPSOUNDCARDINPUT_DRVSTEREO*JVOIPSOUNDCARDINPUT_DRVBYTESPERSAMPLE;						sampleblocks[i].dwBufferLength = size;			sampleblocks[i].dwBytesRecorded = 0;			sampleblocks[i].dwUser = 0;			sampleblocks[i].dwFlags = 0;			sampleblocks[i].dwLoops = 0;			waveInPrepareHeader(sounddev,&sampleblocks[i],sizeof(WAVEHDR));			waveInAddBuffer(sounddev,&sampleblocks[i],sizeof(WAVEHDR));						srcsampletime += ((double)numsamp)/((double)drvsamprate)*1000.0;		}		waveInStart(sounddev);		blockpos = 0;	}	else	{		wantedsrcsampletime += (double)sampleinterval;		diff = wantedsrcsampletime-srcsampletime;		diff /= 1000.0; // convert to seconds		numsamp = (int)(diff*(double)drvsamprate+0.5);		size = numsamp*JVOIPSOUNDCARDINPUT_DRVSTEREO*JVOIPSOUNDCARDINPUT_DRVBYTESPERSAMPLE;					waveInUnprepareHeader(sounddev,&sampleblocks[blockpos],sizeof(WAVEHDR));		sampleblocks[blockpos].dwBufferLength = size;		sampleblocks[blockpos].dwBytesRecorded = 0;		sampleblocks[blockpos].dwUser = 0;		sampleblocks[blockpos].dwFlags = 0;		sampleblocks[blockpos].dwLoops = 0;		waveInPrepareHeader(sounddev,&sampleblocks[blockpos],sizeof(WAVEHDR));		waveInAddBuffer(sounddev,&sampleblocks[blockpos],sizeof(WAVEHDR));					srcsampletime += ((double)numsamp)/((double)drvsamprate)*1000.0;				blockpos++;		if (blockpos >= numblocks)			blockpos = 0;	}		return 0;}void JVOIPSoundcardInput::Reset(){	int status;	bool wasfirsttime;	if (!init)		return;	wasfirsttime = firsttime;	firsttime = true;	if (nastyresetbug)		status = mixstat.LoadStatus();	waveInStop(sounddev);	resetting = true;	waveInReset(sounddev);	resetting = false;	if (nastyresetbug)	{		if (status >= 0)			mixstat.RestoreStatus();	}	if (!wasfirsttime)	{		int i;               			for (i = 0 ; i < numblocks ; i++)			waveInUnprepareHeader(sounddev,&sampleblocks[i],sizeof(WAVEHDR));	}	sigwait.ClearSignalBuffers();}int JVOIPSoundcardInput::GetSampleBlock(VoIPFramework::VoiceBlock *vb){	int numsamp,size;	double diff;		if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;		if (firsttime) // this will happen only once, and 'firsttime' will be set	{              // to 'false', in 'StartSampling' (which is called after this function)		dstsampletime = 0;		wanteddstsampletime = 0;	}				wanteddstsampletime += (double)sampleinterval;	diff = wanteddstsampletime-dstsampletime;	diff /= 1000.0; // convert to seconds	numsamp = (int)(diff*(double)samprate+0.5);	size = numsamp*bytespersample;	dstsampletime += ((double)numsamp)/((double)samprate)*1000.0;		if (firsttime) // we'll have to return silence, since we haven't sampled anything yet	{		// Here, we follow the assumption that we deliver sample in big endian and unsigned			if (bytespersample == 1)			memset(convertbuffer,127,numsamp);		else // two bytes per sample		{			for (int i = 0 ; i < size ; i += 2)			{				convertbuffer[i] = 127;				convertbuffer[i+1] = 255;			}		}	}	else	{		int actualsize;		actualsize = sampconvert.Convert((unsigned char *)sampleblocks[blockpos].lpData,sampleblocks[blockpos].dwBufferLength,convertbuffer,size);		if (actualsize < size) // we'll have to fill a bit		{			if (bytespersample == 1)			{				unsigned char b;								b = convertbuffer[actualsize-1];				for (    ;  actualsize < size ; actualsize++)					convertbuffer[actualsize] = b;			}			else // two bytes per sample			{				unsigned char b1,b2;								b1 = convertbuffer[actualsize-2];				b2 = convertbuffer[actualsize-1];				for (    ;  actualsize < size ; actualsize += 2)				{					convertbuffer[actualsize] = b1;					convertbuffer[actualsize + 1] = b2;				}			}		}	}		// Ok, now we have what we want, and we'll just have to fill in the info in the	// voice block	vb->SetSamples(convertbuffer,size);	vb->SetNumSamples(numsamp);	vb->SetStereo(false);	vb->SetBytesPerSample(bytespersample);	vb->SetSampleRate(samprate);	vb->SetDataDeleteHandler(BlockDeleteHandler,this);		return 0;}bool JVOIPSoundcardInput::SupportsSampleInterval(int ival){	return true;}bool JVOIPSoundcardInput::SupportsInputSamplingRate(int irate){	return true;}bool JVOIPSoundcardInput::SupportsInputBytesPerSample(int inputbytespersample){	return true;	}int JVOIPSoundcardInput::SetSampleInterval(int ival){	int status;		if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	if (ival == sampleinterval)		return 0;	sampleinterval = ival;	Reset();	ClearBuffers();	if ((status = InitBuffers()) < 0)	{		if (sounddev != NULL)			waveInClose(sounddev);		sounddev = NULL;		init = false;		return status;			}	InitSampleConverter();		return 0;}int JVOIPSoundcardInput::SetInputSamplingRate(int irate){	int status;		if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	if (irate == samprate)		return 0;		samprate = irate;	Reset();	ClearBuffers();	if ((status = InitBuffers()) < 0)	{		if (sounddev != NULL)			waveInClose(sounddev);		sounddev = NULL;		init = false;		return status;	}	InitSampleConverter();		return 0;}int JVOIPSoundcardInput::SetInputBytesPerSample(int inputbytespersample){	int status;		if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	if (inputbytespersample == bytespersample)		return 0;		bytespersample = inputbytespersample;	Reset();	ClearBuffers();	if ((status = InitBuffers()) < 0)	{		if (sounddev != NULL)			waveInClose(sounddev);		sounddev = NULL;		init = false;		return status;	}	InitSampleConverter();		return 0;}bool JVOIPSoundcardInput::HasTimeOut(){	if (!init)		return false;	if (firsttime)		return true;	return ((sampleblocks[blockpos].dwFlags&WHDR_DONE) == WHDR_DONE)?true:false;}int JVOIPSoundcardInput::RestartTimer(){	if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;		// NOTE: nothing needs to be done here	return 0;}int JVOIPSoundcardInput::GetComponentState(JVOIPComponentState **compstate){	if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;		*compstate = NULL;	return 0;}int JVOIPSoundcardInput::SetComponentState(JVOIPComponentState *compstate){	if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	// NOTE: nothing needs to be done here	return 0;}std::string JVOIPSoundcardInput::GetComponentName(){	return std::string("JVOIPSoundcardInput");}std::string JVOIPSoundcardInput::GetComponentDescription(){	return std::string("JVOIPLIB Internal soundcard input module (Win32 version)");}std::vector<JVOIPCompParamInfo> *JVOIPSoundcardInput::GetComponentParameters() throw (JVOIPException){	return NULL;}int JVOIPSoundcardInput::InitBuffers(){	int i;	// allocate buffers for the sounddevice			numblocks = (int)(((double)JVOIPSOUNDCARDINPUT_TOTALBUFFERTIME)/((double)sampleinterval)+0.5);	blocksize = (int)((((double)drvsamprate*(double)sampleinterval)/1000.0)*(double)JVOIPSOUNDCARDINPUT_DRVBYTESPERSAMPLE*(double)JVOIPSOUNDCARDINPUT_DRVSTEREO+0.5);	blocksize += JVOIPSOUNDCARDINPUT_EXTRABLOCKSIZE;		sampleblocks = new WAVEHDR[numblocks];	if (sampleblocks == NULL)		return ERR_JVOIPLIB_GENERAL_OUTOFMEM;	for (i = 0 ; i < numblocks ; i++)	{		sampleblocks[i].lpData = new char[blocksize];		if (sampleblocks[i].lpData == NULL)		{			for (int j = 0 ; j < i ; j++)				delete [] sampleblocks[j].lpData;			delete [] sampleblocks;			return ERR_JVOIPLIB_GENERAL_OUTOFMEM;		}	}	// allocate a buffer to hold the converted data			convertbufsize = (int)((((double)samprate*(double)sampleinterval)/1000.0)*(double)bytespersample+0.5);	convertbufsize += JVOIPSOUNDCARDINPUT_EXTRABLOCKSIZE;		convertbuffer = new unsigned char [convertbufsize];	if (convertbuffer == NULL)	{		for (i = 0 ; i < numblocks ; i++)			delete [] sampleblocks[i].lpData;		delete [] sampleblocks;	}		return 0;}void JVOIPSoundcardInput::ClearBuffers(){	for (int i = 0 ; i < numblocks ; i++)		delete [] sampleblocks[i].lpData;	delete [] sampleblocks;	delete [] convertbuffer;}void JVOIPSoundcardInput::InputCallback(HWAVEIN hwi,UINT uMsg,DWORD dwInstance,DWORD dwParam1,DWORD dwParam2){	JVOIPSoundcardInput *inst;		if (!dwInstance)		return;		inst = (JVOIPSoundcardInput *)dwInstance;	if (inst->resetting)		return;	inst->sigwait.Signal();}void JVOIPSoundcardInput::BlockDeleteHandler(unsigned char **data,void *param){	*data = NULL;}void JVOIPSoundcardInput::InitSampleConverter(){	int srcrate,srcbytespersample,dstrate,dstbytespersample;	bool srcstereo,srcsigned,srcLE,dststereo,dstsigned,dstLE;	srcrate = drvsamprate;	srcbytespersample = JVOIPSOUNDCARDINPUT_DRVBYTESPERSAMPLE;	srcstereo = (JVOIPSOUNDCARDINPUT_DRVSTEREO == 1)?false:true;	srcsigned = JVOIPSOUNDCARDINPUT_DRVSIGNED;	srcLE = JVOIPSOUNDCARDINPUT_DRVLITTLEENDIAN;	dstrate = samprate;	dstbytespersample = bytespersample;	dststereo = false;	dstsigned = false;	dstLE = false;        		sampconvert.SetConversionParams(srcrate,srcstereo,srcbytespersample,srcsigned,srcLE,                                        dstrate,dststereo,dstbytespersample,dstsigned,dstLE);}int JVOIPSoundcardInput::OpenSoundDevice(int samplerate){	int fact;	WAVEFORMATEX format;		fact = 1;	if (JVOIPSOUNDCARDINPUT_DRVSTEREO != 1)		fact *= 2;	if (JVOIPSOUNDCARDINPUT_DRVBYTESPERSAMPLE != 1)		fact *= 2;	format.nAvgBytesPerSec = samplerate*fact;	format.nBlockAlign = fact;	format.nChannels = JVOIPSOUNDCARDINPUT_DRVSTEREO;	format.nSamplesPerSec = samplerate;	format.wFormatTag = WAVE_FORMAT_PCM;	format.cbSize = 0;	format.wBitsPerSample = JVOIPSOUNDCARDINPUT_DRVBYTESPERSAMPLE*8;		if (waveInOpen((LPHWAVEIN)&sounddev, WAVE_MAPPER,(LPWAVEFORMATEX)&format,(DWORD)InputCallback,(DWORD)this,CALLBACK_FUNCTION))		return ERR_JVOIPLIB_SOUNDCARDIO_CANTOPENDEVICE;		drvsamprate = samplerate;	return 0;}int JVOIPSoundcardInput::CalculateDriveSampleRate(int requestedrate){	int usedsamplerate;	if (requestedrate <= 5000)		usedsamplerate = 5000;	else if (requestedrate <= 11025)		usedsamplerate = 11025;	else if (requestedrate <= 22050)		usedsamplerate = 22050;	else 		usedsamplerate = 44100;	return usedsamplerate;}int JVOIPSoundcardInput::RequestSamplingRate(int rate){	int usedrate;	int status;	usedrate = CalculateDriveSampleRate(rate);	if (usedrate == drvsamprate) // don't have to adjust		return 0;	waveInClose(sounddev);	sounddev = NULL;	if ((status = OpenSoundDevice(usedrate)) < 0)		return status;	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -