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

📄 jvoiplpccompression.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"#ifndef JVOIPDISABLE_COMPRESSION_LPC#include "jvoiplpccompression.h"#include "jvoiperrors.h"#include <stdio.h>#include <string.h>#include <list>#ifdef WIN32	#include <winsock2.h>#else	#include <sys/time.h>	#include <sys/types.h>	#include <unistd.h>#endif // WIN32#include "debugnew.h"#define JVOIPLPCCOMPRESSION_SAMPLEINTERVAL			20#define JVOIPLPCCOMPRESSION_SAMPLERATE				8000#define JVOIPLPCCOMPRESSION_FRAMESIZE				14#define JVOIPLPCCOMPRESSION_EIGHTBITSCALE			256#define JVOIPLPCCOMPRESSION_CHECKDELAY				(60*5)#define JVOIPLPCCOMPRESSION_TIMEOUTDELAY			(60*9)JVOIPLPCCompression::JVOIPLPCCompression(JVOIPSession *sess) : JVOIPCompressionModule(sess){	compinit = false;	stopthreadmutex.Init();	statemutex.Init();}JVOIPLPCCompression::~JVOIPLPCCompression(){	CleanupCompressor();	CleanupDecompressor();}int JVOIPLPCCompression::InitCompressor(int sampinterval,int inputsamprate,int inputbytespersample,const JVOIPComponentParams *componentparams){	if (compinit)		return ERR_JVOIPLIB_GENERAL_COMPONENTALREADYINIT;	if ((sampinterval <= 0) || (sampinterval % JVOIPLPCCOMPRESSION_SAMPLEINTERVAL) != 0)		return ERR_JVOIPLIB_LPCCOMP_UNSUPPORTEDSAMPLEINTERVAL;	if (inputsamprate != JVOIPLPCCOMPRESSION_SAMPLERATE)		return ERR_JVOIPLIB_LPCCOMP_UNSUPPORTEDSAMPLERATE;	compinit = true;	return 0;}int JVOIPLPCCompression::CleanupCompressor(){	if (!compinit)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;		compinit = false;	return 0;}int JVOIPLPCCompression::InitDecompressor(){	stopthread = false;	if (Start() < 0) // Start the thread which cleans the LPC state info map from time to time		return ERR_JVOIPLIB_LPCCOMP_CANTSTARTTHREAD;	return 0;}int JVOIPLPCCompression::CleanupDecompressor(){	// We have to clean up the LPC states	std::map<VoIPFramework::VOIPuint64,LPCStateInfo *>::const_iterator it;	StopThread();	for (it = lpcstates.begin() ; it != lpcstates.end() ; ++it)		delete it->second; // delete the LPCStateInfo part;	lpcstates.clear();	return 0;}int JVOIPLPCCompression::Compress(VoIPFramework::VoiceBlock *vb){	unsigned char *frame,*data;	int signalbuf[160];	int datalen,numsamples;	int i,j,numframes,offset;	int frameoffset;	data = vb->GetSamples(false);	datalen = vb->GetNumBytes();	numsamples = vb->GetNumSamples();	numframes = numsamples/160;	if (numsamples%160 != 0)		numframes++;		frame = new unsigned char[JVOIPLPCCOMPRESSION_FRAMESIZE*numframes];	if (frame == NULL)		return ERR_JVOIPLIB_GENERAL_OUTOFMEM;	offset = 0;	frameoffset = 0;	while (offset < numsamples)	{		int samp;				samp = numsamples - offset;		if (samp > 160)			samp = 160;				memset(signalbuf,0,sizeof(int) * 160);		// fill in the signal buffer		if (vb->GetBytesPerSample() == 1)		{			for (i = 0 ; i < samp ; i++)			{				int val;				val = (((int)data[i+offset])-127)*JVOIPLPCCOMPRESSION_EIGHTBITSCALE;				signalbuf[i] = val;			}		}		else // two bytes per sample		{			for (i = 0,j = offset*2 ; i < samp ; i++,j += 2)			{				int val;							val = (((int)data[j])<<8)|((int)data[j+1]);				val -= 32767;				signalbuf[i] = val;			}		}			lpcencoder.Encode(signalbuf,frame+frameoffset);		frameoffset += JVOIPLPCCOMPRESSION_FRAMESIZE;		offset += 160;	}	vb->SetSamples(frame,JVOIPLPCCOMPRESSION_FRAMESIZE*numframes);	return 0;}int JVOIPLPCCompression::Decompress(VoIPFramework::VoiceBlock *vb,VoIPFramework::VOIPuint64 sourceid){	unsigned char *frame;	unsigned char *speech;	int signalbuf[160];	int framelen,i,j;	LPCStateInfo *stateinf;	int numframes,framepos,samppos;	frame = vb->GetSamples(false);	if (frame == NULL)		return 0;	framelen = vb->GetNumBytes();	if ((framelen <= 0) || (framelen % JVOIPLPCCOMPRESSION_FRAMESIZE) != 0)	{		vb->Clear();		return 0;	}	numframes = framelen/JVOIPLPCCOMPRESSION_FRAMESIZE;	// Obtain the LPC state info for this participant. This is done by the	// map. If the key isn't found, the map creates a default entry, so	// in that case the lpcstate will be NULL.		statemutex.Lock();		stateinf = lpcstates[sourceid];	if (stateinf == NULL)	{		stateinf = new LPCStateInfo();		if (stateinf == NULL)		{			statemutex.Unlock();			return ERR_JVOIPLIB_GENERAL_OUTOFMEM;		}		lpcstates[sourceid] = stateinf;	}	else			stateinf->lasttime = time(NULL);	// We'll encode it in 16 bit values. This way we have more precision.	// Conversion to the right output rate and sample type will be done	// in the mixer.	speech = new unsigned char[160*2*numframes];	if (speech == NULL)	{		statemutex.Unlock();		return ERR_JVOIPLIB_GENERAL_OUTOFMEM;	}		// Now, we simply have to decode the frame and put it in the voiceblock	for (framepos = 0,samppos = 0 ; framepos < framelen ; framepos += JVOIPLPCCOMPRESSION_FRAMESIZE,samppos += 160*2)	{		stateinf->lpcdecoder.Decode(frame+framepos,signalbuf);			for (i = 0,j = samppos ; i < 160 ; i++,j += 2)		{			int val;			val = signalbuf[i];			val = val+32767;			if (val < 0)				val = 0;			else if (val > 65535)				val = 65535;			speech[j] = (unsigned char)((val>>8)&0xFF);			speech[j+1] = (unsigned char)(val&0xFF);		}	}	statemutex.Unlock();	// Now, we simply have to store the decodes samples in the voiceblock	vb->SetSamples(speech,160*2*numframes);	vb->SetNumSamples(160*numframes);	vb->SetBytesPerSample(2);		return 0;}bool JVOIPLPCCompression::SupportsSampleInterval(int ival){	if (!compinit)		return false;	if ((ival <= 0) || (ival % JVOIPLPCCOMPRESSION_SAMPLEINTERVAL) != 0)		return false;	return true;}int JVOIPLPCCompression::SetSampleInterval(int ival){	if (!compinit)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	if ((ival <= 0) || (ival % JVOIPLPCCOMPRESSION_SAMPLEINTERVAL) != 0)		return ERR_JVOIPLIB_LPCCOMP_UNSUPPORTEDSAMPLEINTERVAL;	return 0;}bool JVOIPLPCCompression::SupportsInputSamplingRate(int irate){	if (!compinit)		return false;	if (irate != JVOIPLPCCOMPRESSION_SAMPLERATE)		return false;	return true;}int JVOIPLPCCompression::SetInputSamplingRate(int irate){	if (!compinit)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	if (irate != JVOIPLPCCOMPRESSION_SAMPLERATE)		return ERR_JVOIPLIB_LPCCOMP_UNSUPPORTEDSAMPLERATE;	return 0;}bool JVOIPLPCCompression::SupportsInputBytesPerSample(int inputbytespersample){	if (!compinit)		return false;	return true;}int JVOIPLPCCompression::SetInputBytesPerSample(int inputbytespersample){	if (!compinit)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	return 0;}int JVOIPLPCCompression::GetComponentState(JVOIPComponentState **compstate){	if (!compinit)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	*compstate = NULL;	return 0;}int JVOIPLPCCompression::SetComponentState(JVOIPComponentState *compstate){	if (!compinit)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	return 0;}std::string JVOIPLPCCompression::GetComponentName(){	return std::string("JVOIPLPCCompression");}std::string JVOIPLPCCompression::GetComponentDescription(){	return std::string("JVOIPLIB Internal LPC 5.4kbps compression module");}std::vector<JVOIPCompParamInfo> *JVOIPLPCCompression::GetComponentParameters() throw (JVOIPException){	return NULL;}void *JVOIPLPCCompression::Thread(){	JThread::ThreadStarted();		bool stop;	time_t prevchecktime;	prevchecktime = time(NULL);	stopthreadmutex.Lock();	stop = stopthread;	stopthreadmutex.Unlock();	while (!stop)	{		time_t curtime;		struct timeval tv;				tv.tv_sec = 0;		tv.tv_usec = 100000; // 100 millisecods -> make sure we don't have to wait too long#ifndef WIN32		select(FD_SETSIZE,NULL,NULL,NULL,&tv);#else		Sleep((DWORD)(((double)tv.tv_sec)*1000.0+((double)tv.tv_usec)/1000.0));#endif // WIN32		curtime = time(NULL);		if ((curtime - prevchecktime) > JVOIPLPCCOMPRESSION_CHECKDELAY)		{			std::map<VoIPFramework::VOIPuint64,LPCStateInfo *>::iterator it;			std::list<VoIPFramework::VOIPuint64> sourceids;			std::list<VoIPFramework::VOIPuint64>::const_iterator it2;						statemutex.Lock();			it = lpcstates.begin();			while (it != lpcstates.end())			{				if ((curtime - it->second->lasttime) > JVOIPLPCCOMPRESSION_TIMEOUTDELAY)				{					// NOTE: we cannot simply call an 'erase'					// function because the map::erase function					// does not return a new iterator. So, we'll					// store the keys which need to be erased					// in a list and delete all entries afterwards					// Also note that we do need to erase the					// LPCStateInfo* here					delete it->second; 					sourceids.push_back(it->first);				}				it++;			}			for (it2 = sourceids.begin() ; it2 != sourceids.end() ; ++it2)				lpcstates.erase(*it2);			statemutex.Unlock();					prevchecktime = curtime;		}				stopthreadmutex.Lock();		stop = stopthread;		stopthreadmutex.Unlock();	}	return NULL;}void JVOIPLPCCompression::StopThread(){	time_t t = time(NULL);	stopthreadmutex.Lock();	stopthread = true;	stopthreadmutex.Unlock();	while (IsRunning() && (time(NULL) - t) < 5)		;	if (IsRunning())	{		std::cerr << "JVOIPLPCCompression::StopThread -- warning: having to kill thread" << std::endl;		Kill();	}}#endif // JVOIPDISABLE_COMPRESSION_LPC

⌨️ 快捷键说明

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