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

📄 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)    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 "jvoipsoundcardparams.h"#include "jvoipsounddevice.h"#include "jvoipsounddeviceblock.h"#include <stdlib.h>#include <string.h>#include <stdio.h>#include "debugnew.h"#define JVOIPSOUNDCARDINPUT_TOTALBUFFERTIME				10000#define JVOIPSOUNDCARDINPUT_EXTRABLOCKSIZE				32JVOIPSoundcardInput::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){	JVOIPSoundcardParams defparams,*usrparams;	int status;	if (init)		return ERR_JVOIPLIB_GENERAL_COMPONENTALREADYINIT;		// Get the soundcard parameters		if (componentparams == NULL)		usrparams = &defparams;	else if ((usrparams = dynamic_cast<JVOIPSoundcardParams *>(const_cast<JVOIPComponentParams *>(componentparams))) == NULL)		usrparams = &defparams;	multiplyfactor = usrparams->GetMultiplyFactor();	if (multiplyfactor < 1 || multiplyfactor > 256)		return ERR_JVOIPLIB_SOUNDCARDIO_ILLEGALMULTIPLYFACTOR;		status = JVOIPSoundDevice::OpenDevice(&sounddev,usrparams->GetSoundDeviceName(),true,inputsamprate);	if (status < 0)		return status;	status = sounddev->SetInputCallback(InputCallback,this);	if (status < 0)	{		delete sounddev;		return status;	}			sampleinterval = sampinterval;	samprate = inputsamprate;	bytespersample = inputbytespersample;	sounddev->RequestSamplingRate(samprate);	if ((status = InitBuffers()) < 0)	{		delete sounddev;		return status;	}	InitSampleConverter();			sigwait.ClearSignalBuffers();			init = true;	firsttime = true;	return 0;}int JVOIPSoundcardInput::Cleanup(){	if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	delete sounddev;		ClearBuffers();	init = false;	return 0;}int JVOIPSoundcardInput::StartSampling(){	int i,size,numsamp,status;	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*drvstereo*drvbytespersample;						sampleblocks[i].datalen = size;			if ((status = sounddev->AddBuffer(&sampleblocks[i])) < 0)				return status;						srcsampletime += ((double)numsamp)/((double)drvsamprate)*1000.0;		}				blockpos = 0;	}	else	{		wantedsrcsampletime += (double)sampleinterval;		diff = wantedsrcsampletime-srcsampletime;		diff /= 1000.0; // convert to seconds		numsamp = (int)(diff*(double)drvsamprate+0.5);		size = numsamp*drvstereo*drvbytespersample;					sampleblocks[blockpos].datalen = size;		if ((status = sounddev->AddBuffer(&sampleblocks[blockpos])) < 0)			return status;					srcsampletime += ((double)numsamp)/((double)drvsamprate)*1000.0;				blockpos++;		if (blockpos >= numblocks)			blockpos = 0;	}		return 0;}void JVOIPSoundcardInput::ResetDevice(){	if (!init)		return;	firsttime = true;	sounddev->Reset();	sigwait.ClearSignalBuffers();}void JVOIPSoundcardInput::Reset(){	int status;		if (!init)		return;	firsttime = true;	sounddev->Reset();	sigwait.ClearSignalBuffers();	ClearBuffers();	if ((status = InitBuffers()) < 0)	{		delete sounddev;		init = false;		std::cerr << "JVOIPSoundcardInput: couldn't init buffers during Reset, device closed" << std::endl;		return;	}	InitSampleConverter();}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(sampleblocks[blockpos].data,sampleblocks[blockpos].datalen,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;	ResetDevice();	ClearBuffers();		if ((status = InitBuffers()) < 0)	{		delete sounddev;		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;	ResetDevice();	ClearBuffers();		if ((status = InitBuffers()) < 0)	{		delete sounddev;		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;	ResetDevice();	ClearBuffers();	if ((status = InitBuffers()) < 0)	{		delete sounddev;		init = false;		return status;	}	InitSampleConverter();		return 0;}bool JVOIPSoundcardInput::HasTimeOut(){	if (!init)		return false;	if (firsttime)		return true;	return sampleblocks[blockpos].IsDone();}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 (OSS version)");}std::vector<JVOIPCompParamInfo> *JVOIPSoundcardInput::GetComponentParameters() throw (JVOIPException){	std::vector<JVOIPCompParamInfo> *paraminfo;		paraminfo = new std::vector<JVOIPCompParamInfo>(2);	if (paraminfo == NULL)		throw JVOIPException(ERR_JVOIPLIB_GENERAL_OUTOFMEM);	(*paraminfo)[0].SetParameterName(std::string("Device"));	if (sounddev == NULL)		(*paraminfo)[0].SetParameterValue(std::string("None"));	else		(*paraminfo)[0].SetParameterValue(sounddev->GetDeviceName());	char val[256];		sprintf(val,"%d",multiplyfactor);	(*paraminfo)[1].SetParameterName(std::string("Multiply Factor"));	(*paraminfo)[1].SetParameterValue(std::string(val));	return paraminfo;}int JVOIPSoundcardInput::InitBuffers(){	int i;	// Request the most appropriate sampling rate	sounddev->RequestSamplingRate(samprate);	// allocate buffers for the sounddevice	drvsamprate = sounddev->GetSamplingRate();	drvbytespersample = sounddev->GetBytesPerSample();	drvstereo = (sounddev->IsStereo())?2:1;		numblocks = (int)(((double)JVOIPSOUNDCARDINPUT_TOTALBUFFERTIME)/((double)sampleinterval)+0.5);	blocksize = (int)((((double)drvsamprate*(double)sampleinterval)/1000.0)*(double)drvbytespersample*(double)drvstereo+0.5);	blocksize += JVOIPSOUNDCARDINPUT_EXTRABLOCKSIZE;		sampleblocks = new JVOIPSoundDeviceBlock [numblocks];	if (sampleblocks == NULL)		return ERR_JVOIPLIB_GENERAL_OUTOFMEM;	for (i = 0 ; i < numblocks ; i++)	{		sampleblocks[i].data = new unsigned char[blocksize];		if (sampleblocks[i].data == NULL)		{			for (int j = 0 ; j < i ; j++)				delete [] sampleblocks[j].data;			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].data;		delete [] sampleblocks;	}		return 0;}void JVOIPSoundcardInput::ClearBuffers(){	for (int i = 0 ; i < numblocks ; i++)		delete [] sampleblocks[i].data;	delete [] sampleblocks;	delete [] convertbuffer;}void JVOIPSoundcardInput::InputCallback(void *param){	JVOIPSoundcardInput *inst;		if (!param)		return;			inst = (JVOIPSoundcardInput *)param;	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 = sounddev->GetSamplingRate();        srcbytespersample = sounddev->GetBytesPerSample();        srcstereo = sounddev->IsStereo();        srcsigned = sounddev->IsSampleSigned();        srcLE = sounddev->IsSampleLittleEndian();        dstrate = samprate;        dstbytespersample = bytespersample;        dststereo = false;        dstsigned = false;        dstLE = false;        		sampconvert.SetConversionParams(srcrate,srcstereo,srcbytespersample,srcsigned,srcLE,                                        dstrate,dststereo,dstbytespersample,dstsigned,dstLE,					multiplyfactor);}

⌨️ 快捷键说明

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