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

📄 jvoipsoundcardoutput.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 "jvoipsoundcardoutput.h"#include "jvoiperrors.h"#include "voiceblock.h"#include "debugnew.h"#define JVOIPSOUNDCARDOUTPUT_TOTALBUFFERTIME					10000#define JVOIPSOUNDCARDOUTPUT_EXTRABLOCKSIZE					32#define JVOIPSOUNDCARDOUTPUT_DRVBYTESPERSAMPLE					2#define JVOIPSOUNDCARDOUTPUT_DRVSTEREO						2#define JVOIPSOUNDCARDOUTPUT_DRVLITTLEENDIAN					true#define JVOIPSOUNDCARDOUTPUT_DRVSIGNED						true					JVOIPSoundcardOutput::JVOIPSoundcardOutput(JVOIPSession *sess):JVOIPVoiceOutput(sess){	init = false;	sounddev = NULL;}JVOIPSoundcardOutput::~JVOIPSoundcardOutput(){	Cleanup();}int JVOIPSoundcardOutput::Init(int sampinterval,int outputsamprate,int outputbytespersample,bool stereo,const JVOIPComponentParams *componentparams){	int status;	if (init)		return ERR_JVOIPLIB_GENERAL_COMPONENTALREADYINIT;		status = OpenSoundDevice(CalculateDriveSampleRate(outputsamprate));	if (status < 0)		return status;		sampleinterval = sampinterval;	samprate = outputsamprate;	bytespersample = outputbytespersample;	needstereo = stereo;		if ((status = InitBuffers()) < 0)	{		if (sounddev != NULL)			waveOutClose(sounddev);		sounddev = NULL;		return status;	}	InitSampleConverter();			init = true;	firsttime = true;				return 0;}int JVOIPSoundcardOutput::Cleanup(){	if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;		Reset();	ClearBuffers();	if (sounddev != NULL)		waveOutClose(sounddev);	sounddev = NULL;	init = false;	return 0;}int JVOIPSoundcardOutput::Play(VoIPFramework::VoiceBlock *vb){	bool playsilence;	unsigned char *data;	double diff;	int numsamp,size;	if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	playsilence = false;	if ((data = vb->GetSamples(false)) == NULL)		playsilence = true;	if (vb->IsStereo() != needstereo)		playsilence = true;	else if (vb->GetBytesPerSample() != bytespersample)		playsilence = true;	if ((int)vb->GetSampleRate() != samprate)		playsilence = true;				if (firsttime)	{		firsttime = false;		blockpos = 0;		wantedplaytime = 0;		playtime = 0;		cycled = false;	}		if (cycled) // we should unprepare the header first	{		if ((sampleblocks[blockpos].dwFlags&WHDR_DONE) != WHDR_DONE)		{			// This means we're seriously out of sync and continuing			// would create resource problems since waveOutUnprepareHeader			// would not release the internal buffers of the wave device 			Reset();			return 0;		}		waveOutUnprepareHeader(sounddev,&sampleblocks[blockpos],sizeof(WAVEHDR));	}	wantedplaytime += (double)sampleinterval;	diff = wantedplaytime-playtime;	diff /= 1000.0; // convert to seconds	numsamp = (int)(diff*(double)drvsamprate+0.5);	size = numsamp*JVOIPSOUNDCARDOUTPUT_DRVSTEREO*JVOIPSOUNDCARDOUTPUT_DRVBYTESPERSAMPLE;	playtime += ((double)numsamp)/((double)drvsamprate)*1000.0;	if (playsilence)	{		if (JVOIPSOUNDCARDOUTPUT_DRVBYTESPERSAMPLE == 1)		{			if (JVOIPSOUNDCARDOUTPUT_DRVSIGNED)				memset(sampleblocks[blockpos].lpData,0,size);			else				memset(sampleblocks[blockpos].lpData,127,size);		}		else // two bytes per sample		{			if (JVOIPSOUNDCARDOUTPUT_DRVSIGNED)				memset(sampleblocks[blockpos].lpData,0,size);			else			{				if (JVOIPSOUNDCARDOUTPUT_DRVLITTLEENDIAN)				{					for (int i = 0 ; i < size ; i += 2)					{						sampleblocks[blockpos].lpData[i] = -1; // ( -1 is 0xFF)						sampleblocks[blockpos].lpData[i+1] = 127;					}				}				else // big endian				{					for (int i = 0 ; i < size ; i += 2)					{						sampleblocks[blockpos].lpData[i] = 127;						sampleblocks[blockpos].lpData[i+1] = -1; // ( -1 is 0xFF)					}				}			}		}	}	else	{		int actualsize;				actualsize = sampconvert.Convert(data,vb->GetNumBytes(),(unsigned char *)sampleblocks[blockpos].lpData,size);		if (actualsize < size)		{			if (JVOIPSOUNDCARDOUTPUT_DRVSTEREO == 1) // no stereo			{				if (JVOIPSOUNDCARDOUTPUT_DRVBYTESPERSAMPLE == 1)				{					unsigned char b;										b = sampleblocks[blockpos].lpData[actualsize-1];					for (     ; actualsize < size ; actualsize++)						sampleblocks[blockpos].lpData[actualsize] = b;				}				else // two bytes per sample				{					unsigned char b1,b2;										b1 = sampleblocks[blockpos].lpData[actualsize-2];					b2 = sampleblocks[blockpos].lpData[actualsize-1];					for (     ; actualsize < size ; actualsize += 2)					{						sampleblocks[blockpos].lpData[actualsize] = b1;						sampleblocks[blockpos].lpData[actualsize+1] = b2;					}				}			}			else // stereo			{				if (JVOIPSOUNDCARDOUTPUT_DRVBYTESPERSAMPLE == 1)				{					unsigned char b1,b2;										b1 = sampleblocks[blockpos].lpData[actualsize-2];					b2 = sampleblocks[blockpos].lpData[actualsize-1];					for (     ; actualsize < size ; actualsize += 2)					{						sampleblocks[blockpos].lpData[actualsize] = b1;						sampleblocks[blockpos].lpData[actualsize+1] = b2;					}				}				else // two bytes per sample				{					unsigned char b1,b2,b3,b4;										b1 = sampleblocks[blockpos].lpData[actualsize-4];					b2 = sampleblocks[blockpos].lpData[actualsize-3];					b3 = sampleblocks[blockpos].lpData[actualsize-2];					b4 = sampleblocks[blockpos].lpData[actualsize-1];					for (     ; actualsize < size ; actualsize += 4)					{						sampleblocks[blockpos].lpData[actualsize] = b1;						sampleblocks[blockpos].lpData[actualsize+1] = b2;						sampleblocks[blockpos].lpData[actualsize+2] = b3;						sampleblocks[blockpos].lpData[actualsize+3] = b4;					}				}			}		}	}		sampleblocks[blockpos].dwBufferLength = size;	sampleblocks[blockpos].dwFlags = 0;	sampleblocks[blockpos].dwLoops = 0;	sampleblocks[blockpos].dwUser = 0;	waveOutPrepareHeader(sounddev,&sampleblocks[blockpos],sizeof(WAVEHDR));	waveOutWrite(sounddev,&sampleblocks[blockpos],sizeof(WAVEHDR));	blockpos++;	if (blockpos >= numblocks)	{		blockpos = 0;		cycled = true;	}	return 0;}void JVOIPSoundcardOutput::Reset(){	int i;	if (!init)		return;		firsttime = true;	waveOutReset(sounddev);	if (cycled)	{		for (i = 0 ; i < numblocks ; i++)			waveOutUnprepareHeader(sounddev,&sampleblocks[i],sizeof(WAVEHDR));	}	else	{		for (i = 0 ; i < blockpos ; i++)			waveOutUnprepareHeader(sounddev,&sampleblocks[i],sizeof(WAVEHDR));	}}bool JVOIPSoundcardOutput::SupportsSampleInterval(int ival){	return true;}bool JVOIPSoundcardOutput::SupportsOutputSamplingRate(int orate){	return true;}bool JVOIPSoundcardOutput::SupportsOutputBytesPerSample(int outputbytespersample){	return true;}int JVOIPSoundcardOutput::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)			waveOutClose(sounddev);		sounddev = NULL;		init = false;		return status;	}	InitSampleConverter();		return 0;}int JVOIPSoundcardOutput::SetOutputSamplingRate(int orate){	int status;	if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	if (orate == samprate)		return 0;		samprate = orate;	Reset();	ClearBuffers();	if ((status = InitBuffers()) < 0)	{		if (sounddev != NULL)			waveOutClose(sounddev);		sounddev = NULL;		init = false;		return status;	}	InitSampleConverter();		return 0;}int JVOIPSoundcardOutput::SetOutputBytesPerSample(int outputbytespersample){	int status;	if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	if (outputbytespersample == bytespersample)		return 0;		bytespersample = outputbytespersample;	Reset();	ClearBuffers();	if ((status = InitBuffers()) < 0)	{		if (sounddev != NULL)			waveOutClose(sounddev);		sounddev = NULL;		init = false;		return status;	}	InitSampleConverter();		return 0;}int JVOIPSoundcardOutput::SetStereo(bool s){	int status;	if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	if (s == needstereo)		return 0;		needstereo = s;	Reset();	ClearBuffers();	if ((status = InitBuffers()) < 0)	{		if (sounddev != NULL)			waveOutClose(sounddev);		sounddev = NULL;		init = false;		return status;	}	InitSampleConverter();		return 0;}int JVOIPSoundcardOutput::GetComponentState(JVOIPComponentState **compstate){	if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	*compstate = NULL;	return 0;}int JVOIPSoundcardOutput::SetComponentState(JVOIPComponentState *compstate){	if (!init)		return ERR_JVOIPLIB_GENERAL_COMPONENTNOTINIT;	// NOTE: Nothing needs to be done here	return 0;}std::string JVOIPSoundcardOutput::GetComponentName(){	return std::string("JVOIPSoundcardOutput");}std::string JVOIPSoundcardOutput::GetComponentDescription(){	return std::string("JVOIPLIB Internal soundcard output module (Win32 version)");}std::vector<JVOIPCompParamInfo> *JVOIPSoundcardOutput::GetComponentParameters(){	return NULL;}void JVOIPSoundcardOutput::InitSampleConverter(){	int srcrate,srcbytespersample,dstrate,dstbytespersample;	bool srcstereo,srcsigned,srcLE,dststereo,dstsigned,dstLE;	dstrate = drvsamprate;	dstbytespersample = JVOIPSOUNDCARDOUTPUT_DRVBYTESPERSAMPLE;	dststereo = (JVOIPSOUNDCARDOUTPUT_DRVSTEREO == 2)?true:false;	dstsigned = JVOIPSOUNDCARDOUTPUT_DRVSIGNED;	dstLE = JVOIPSOUNDCARDOUTPUT_DRVLITTLEENDIAN;	srcrate = samprate;	srcbytespersample = bytespersample;	srcstereo = needstereo;	srcsigned = false;	srcLE = false;        		sampconvert.SetConversionParams(srcrate,srcstereo,srcbytespersample,srcsigned,srcLE,                                    dstrate,dststereo,dstbytespersample,dstsigned,dstLE);}int JVOIPSoundcardOutput::InitBuffers(){	int i,status;	if ((status = RequestSamplingRate(samprate)) < 0)		return status;	// allocate buffers for the sounddevice			numblocks = (int)(((double)JVOIPSOUNDCARDOUTPUT_TOTALBUFFERTIME)/((double)sampleinterval)+0.5);	blocksize = (int)((((double)drvsamprate*(double)sampleinterval)/1000.0)*(double)JVOIPSOUNDCARDOUTPUT_DRVBYTESPERSAMPLE*(double)JVOIPSOUNDCARDOUTPUT_DRVSTEREO+0.5);	blocksize += JVOIPSOUNDCARDOUTPUT_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;		}		sampleblocks[i].dwFlags = 0; // clear all flags	}	return 0;}void JVOIPSoundcardOutput::ClearBuffers(){	for (int i = 0 ; i < numblocks ; i++)		delete [] sampleblocks[i].lpData;	delete [] sampleblocks;}int JVOIPSoundcardOutput::OpenSoundDevice(int samplerate){	int fact;	WAVEFORMATEX format;	fact = 1;	if (JVOIPSOUNDCARDOUTPUT_DRVSTEREO != 1)		fact *= 2;	if (JVOIPSOUNDCARDOUTPUT_DRVBYTESPERSAMPLE != 1)		fact *= 2;	format.nAvgBytesPerSec = samplerate*fact;	format.nBlockAlign = fact;	format.nChannels = JVOIPSOUNDCARDOUTPUT_DRVSTEREO;	format.nSamplesPerSec = samplerate;	format.wFormatTag = WAVE_FORMAT_PCM;	format.cbSize = 0;	format.wBitsPerSample = JVOIPSOUNDCARDOUTPUT_DRVBYTESPERSAMPLE*8;		if (waveOutOpen((LPHWAVEOUT)&sounddev, WAVE_MAPPER,(LPWAVEFORMATEX)&format,0,0,CALLBACK_NULL))		return ERR_JVOIPLIB_SOUNDCARDIO_CANTOPENDEVICE;	drvsamprate = samplerate;	return 0;}int JVOIPSoundcardOutput::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 JVOIPSoundcardOutput::RequestSamplingRate(int rate){	int usedrate;	int status;	usedrate = CalculateDriveSampleRate(rate);	if (usedrate == drvsamprate) // don't have to adjust		return 0;	waveOutClose(sounddev);	sounddev = NULL;	if ((status = OpenSoundDevice(usedrate)) < 0)		return status;	return 0;}

⌨️ 快捷键说明

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