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

📄 alsasounddevice.cxx

📁 MiniSip Client with DomainKeys Authentication, Sip, Audio communications, Echo Cancel
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) 2004-2006 the Minisip Team  This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.  You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA *//* Copyright (C) 2004  * * Authors: Erik Eliasson <eliasson@it.kth.se> *          Johan Bilien <jobi@via.ecp.fr> *	    Cesc Santasusana <c e s c DOT s a n t a [AT} g m a i l DOT c o m>*/#include<config.h>#include<libminisip/soundcard/AlsaSoundDevice.h>#include<libmutil/Thread.h>#include<libmutil/mtime.h>/**Note (Cesc)I have tried and getting alsa to work in non-blocking for a wide range of soundcardsis difficult, very. When it seems to work, you may start getting errors, or clicks on the audio ...Only turn non-blocking to true (and play with the settings (buffer size - see the header, and number of periods and periodsize) if sound using alsa is bad. Godd luck!*/#define OPEN_ALSA_IN_NON_BLOCKING_MODE false;using namespace std;AlsaSoundDevice::AlsaSoundDevice( string device ):SoundDevice( device ){	readHandle = NULL;	writeHandle = NULL;	periodSize = 0;	numPeriods = 0;}int AlsaSoundDevice::closePlayback(){	if( !openedPlayback ){#ifdef DEBUG_OUTPUT		cerr << "WARNING: doing close on already "			"closed sound card (ALSA)"<< endl;#endif		return -1;	}	if( writeHandle != NULL ){		snd_pcm_close( writeHandle );		writeHandle = NULL;	}	openedPlayback = false;	return 1;}int AlsaSoundDevice::closeRecord(){	if( !openedRecord ){		cerr << "WARNING: doing close on already "			"closed sound card (ALSA)"<< endl;		return -1;	}	if( readHandle != NULL ){		snd_pcm_close( readHandle );		readHandle = NULL;	}	openedRecord = false;	return 1;}int AlsaSoundDevice::calculateAlsaParams( unsigned long &periodSizeMin, 					unsigned long &periodSizeMax, 					uint32_t &periodsMin, 					uint32_t &periodsMax,					unsigned long &bufferMax ) {	unsigned long buffer;		//if it has already been opened ... return old values ...	if( this->periodSize != 0 && this->numPeriods != 0 ) {		periodSizeMin = this->periodSize;		periodsMin = this->numPeriods;		return 0;	}		unsigned long bufferMin = (unsigned long) periodsMin * periodSizeMin;	if( periodsMin == 1 ) periodsMin = 2; //we want at least two periods ... 	//set the goal for the buffer size between the limits ...	buffer = (MIN_HW_PO_BUFFER/1000) * (this->samplingRate/1000); //size in alsa Frames	if( buffer < bufferMin ) buffer = bufferMin;	else if( buffer > bufferMax ) buffer = bufferMax;#ifdef DEBUG_OUTPUT		printf( "Alsa Calc Values: sampling = %d, period size [%d,%d],\n"	        "                  num periods = [%d, %d], buffer size = [%d, %d]\n", (int)this->samplingRate/1000, 							(int)periodSizeMin, 							(int)periodSizeMax, 							(int)periodsMin, 							(int)periodsMax, 							(int)bufferMin, 							(int)bufferMax );	printf( "Alsa Calc: buffer we want is = %d [alsaframes]\n", (int)buffer );#endif	//Now ... iteratively calculate the best possible values ... we 	//prefer having biffer period size and the smaller possible period size ..		//the first time we obtain a buffer size >= our goal, we break;	bool found = false;	unsigned long tmp;	uint32_t per;	unsigned long siz; 	for(  per = periodsMin; per<periodsMax; per++ ) {		for(  siz = periodSizeMin; siz < periodSizeMax; siz+=4 ) {			tmp = per * siz;			if( tmp >= buffer ) {				if(  tmp > bufferMax ) { tmp = bufferMax; }				found = true;				buffer = tmp;				break;			}		}//inner loop		if( found ) break;	} // outer loop#ifdef DEBUG_OUTPUT	cerr << "Alsa - CalculatedParams: periodSize = " << siz << "; numPeriods = " << per << "; bufferSize = " << buffer << flush << endl;#endif	if( !found ) {		return -1;	}	this->periodSize = siz ;	this->numPeriods = per;	bufferMin = buffer;	return 0;}int AlsaSoundDevice::openPlayback( int samplingRate, int nChannels, int format ){	snd_pcm_hw_params_t *hwparams;	snd_pcm_sw_params_t *swparams;	snd_pcm_hw_params_alloca(&hwparams);	snd_pcm_sw_params_alloca(&swparams);		lockOpen.lock();	// Play ...	int openMode = 0;	bool openNonBlocking = OPEN_ALSA_IN_NON_BLOCKING_MODE;		if( openNonBlocking ) {		sleepTime = 20; //min time between calls ... simulated		openMode = SND_PCM_NONBLOCK;#ifdef DEBUG_OUTPUT		cerr << "ALSA: opening playback in non-blocking mode" << endl;#endif	} else {		openMode = 0;		sleepTime = 0;#ifdef DEBUG_OUTPUT		cerr << "ALSA: opening playback in non-blocking mode" << endl;#endif	}		if (snd_pcm_open(&writeHandle, dev.c_str(), SND_PCM_STREAM_PLAYBACK,  openMode ) < 0 ) {		cerr << "Could not open ALSA sound card (playback)" << endl;		exit(-1);	}		if (snd_pcm_hw_params_any(writeHandle, hwparams) < 0) {		cerr << "Could not get ALSA sound card parameters (playback)" << endl;		exit(-1);	}	if (snd_pcm_hw_params_set_access(writeHandle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {		cerr << "Could not set ALSA mode (playback)" << endl;		exit(-1);	}		if (snd_pcm_hw_params_set_channels(writeHandle, hwparams, nChannels)<0){		cerr << "Cound not configure ALSA (playback) for playout on "<<  nChannels<< endl;		exit(-1);	}	this->nChannelsPlay = nChannels;	_snd_pcm_format alsaFormat;	setFormat( format );		switch( format ){		case SOUND_S16LE:			alsaFormat = SND_PCM_FORMAT_S16_LE;			break;		case SOUND_S16BE:			alsaFormat = SND_PCM_FORMAT_S16_BE;			break;		case SOUND_U16LE:			alsaFormat = SND_PCM_FORMAT_U16_LE;			break;		case SOUND_U16BE:			alsaFormat = SND_PCM_FORMAT_U16_BE;			break;		default:			cerr << "Unhandled sound format (ALSA) (playback)" << endl;			exit( -1 );	}	if (snd_pcm_hw_params_set_format(writeHandle, hwparams, 				alsaFormat) < 0) {		cerr << "Could not set ALSA format (playback)" << endl;		exit(-1);	}		unsigned int wantedSamplingRate = (unsigned int)samplingRate; 	if( snd_pcm_hw_params_set_rate_near(writeHandle, hwparams, (unsigned int *)&samplingRate, NULL) < 0){		cerr << "Could not set ALSA rate (playback)" << endl;		exit(-1);	}	if( (unsigned int)samplingRate != wantedSamplingRate  ){#ifdef DEBUG_OUTPUT		cerr << "ALSA (playback): Could not set chosen rate of " << wantedSamplingRate << ", set to "<< samplingRate <<endl;#endif	}	this->samplingRate = samplingRate;		unsigned long periodSizeMin = 960; //desired size of one period ... in number of frames	unsigned long periodSizeMax; //size of one period ... in number of frames	uint32_t numPeriodsMin;  //desired buffer length in number of periods	uint32_t numPeriodsMax;  //desired buffer length in number of periods	unsigned long max_buffer_size; //max buffer size allowd		uint32_t startThreshold = 16;  //number of frames in the buffer so the hw will start processing	uint32_t minAvailable = 32;   //number of available frames so we can read/write		int32_t dir;	//fetch the params ... exit if not able ...		if( snd_pcm_hw_params_get_period_size_min (hwparams, &periodSizeMin, &dir) < 0 ) {		cerr << "Playback: Could not get ALSA period min size" << endl;		exit( -1 );	}	if( snd_pcm_hw_params_get_period_size_max (hwparams, &periodSizeMax, &dir) < 0 ) {		cerr << "Playback: Could not get ALSA period max size" << endl;		exit( -1 );	}	if( snd_pcm_hw_params_get_periods_min (hwparams, &numPeriodsMin, &dir) < 0 ) {		cerr << "Playback: Could not get ALSA periods min " << endl;		exit( -1 );	}		if( snd_pcm_hw_params_get_periods_max (hwparams, &numPeriodsMax, &dir) < 0 ) {		cerr << "Playback: Could not get ALSA periods max " << endl;		exit( -1 );	}		if( snd_pcm_hw_params_get_buffer_size_max (hwparams, &max_buffer_size) < 0 ) {		cerr << "Playback: Could not get ALSA max buffer size " << endl;		exit( -1 );	}		if( calculateAlsaParams( periodSizeMin, 				periodSizeMax, 				numPeriodsMin, 				numPeriodsMax,				max_buffer_size)  < 0 ) {		cerr << "Playback: Could Not calculate Alsa Params" << endl;		exit( -1 );	}#ifdef DEBUG_OUTPUT	printf( "ALSA playback: setting values numperiods %d, period Size %d\n", (int)this->numPeriods, (int)this->periodSize );#endif	//Set the calculated params ... they should not give an eror ... still, check ...		if( snd_pcm_hw_params_set_periods (writeHandle, hwparams, this->numPeriods, 0) < 0 ) {		cerr << "Could not set ALSA (playback) periods" << endl;		exit( -1 );	}	if( snd_pcm_hw_params_set_period_size_near (writeHandle, hwparams, &this->periodSize, 0) < 0 ) {		cerr << "Could not set ALSA (playback) period size" << endl;		exit( -1 );	} else {		#ifdef DEBUG_OUTPUT		cerr << "Record: alsa period size set to " << this->periodSize << endl;		#endif	}	if (snd_pcm_hw_params(writeHandle, hwparams) < 0) {		cerr << "Could not apply parameters to ALSA (playback) sound card for playout" << endl;		exit(-1);	}		if (snd_pcm_sw_params_current(writeHandle, swparams) < 0) {		cerr << "Could not get ALSA software parameters (playback)" << endl;		exit(-1);	}	if (snd_pcm_sw_params_set_start_threshold(writeHandle, swparams, startThreshold)){		#ifdef DEBUG_OUTPUT			cerr << "Could not set ALSA start threshold (playback)" << endl;		#endif

⌨️ 快捷键说明

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