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

📄 pasnd.c

📁 基于osip、eXosip、speex、ffmpeg的VoIP源代码
💻 C
字号:
/*mediastreamer2 library - modular sound and video processing and streamingCopyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.*/#include <speex/speex_preprocess.h>#include "mediastreamer2/mssndcard.h"#include "mediastreamer2/msfilter.h"#include "portaudio.h"MSFilter *ms_pasnd_read_new(MSSndCard *card);MSFilter *ms_pasnd_write_new(MSSndCard *card);typedef struct PASndData{  char *pcmdev;  char *mixdev;  int sound_err;  char waveoutbuffer[30][3200];  PaStream   *waveoutdev;    PaStream   *waveindev;    int rate;  int bits;  ms_thread_t thread;  ms_mutex_t mutex;  queue_t rq;  MSBufferizer * bufferizer;  bool_t read_started;  bool_t write_started;  bool_t stereo;  SpeexPreprocessState *pst;} PASndData;int SpeakerCallback(  const void *inputBuffer, void *outputBuffer,		      unsigned long framesPerBuffer,		      const PaStreamCallbackTimeInfo* timeInfo,		      PaStreamCallbackFlags statusFlags,		      void *userData ){  PASndData *device = (PASndData*)userData;  uint8_t *wtmpbuff=NULL;  int err;  memset(outputBuffer,0, framesPerBuffer*2);  if (!device->read_started && !device->write_started)    {      return 0;    }  wtmpbuff=(uint8_t*)alloca(framesPerBuffer*2);  memset(outputBuffer,0, framesPerBuffer*2);  ms_mutex_lock(&device->mutex);  /* remove extra buffer when latency is increasing:     this often happen with USB device */  if (device->bufferizer->size>=320*6){    ms_warning("Extra data for sound card (total:%i %ims)",	       device->bufferizer->size, (device->bufferizer->size*20)/320);    err=ms_bufferizer_read(device->bufferizer,wtmpbuff, framesPerBuffer*2);    err=ms_bufferizer_read(device->bufferizer,wtmpbuff, framesPerBuffer*2);    err=ms_bufferizer_read(device->bufferizer,wtmpbuff, framesPerBuffer*2);    err=ms_bufferizer_read(device->bufferizer,wtmpbuff, framesPerBuffer*2);    err=ms_bufferizer_read(device->bufferizer,wtmpbuff, framesPerBuffer*2);    ms_warning("Extra data for sound card removed (total:%i %ims)",	       device->bufferizer->size, (device->bufferizer->size*20)/320);  }  err=ms_bufferizer_read(device->bufferizer,wtmpbuff,framesPerBuffer*2);  ms_mutex_unlock(&device->mutex);  if (err==framesPerBuffer*2)    {      memcpy (outputBuffer, wtmpbuff, framesPerBuffer*2);    }  return 0;}int WaveInCallback(  const void *inputBuffer, void *outputBuffer,                     unsigned long framesPerBuffer,		     const PaStreamCallbackTimeInfo* timeInfo,		     PaStreamCallbackFlags statusFlags,		     void *userData ){  PASndData *device = (PASndData*)userData;  if (!device->read_started && !device->write_started)    {      return 0;    }  ms_mutex_lock(&device->mutex);  if (device->read_started)    {      int vad;      mblk_t *rm=NULL;      if (rm==NULL) rm=allocb(framesPerBuffer*2,0);      memcpy(rm->b_wptr,inputBuffer, framesPerBuffer*2);            if (device->pst!=NULL)	{	  vad = speex_preprocess(device->pst, (spx_int16_t *)rm->b_wptr, NULL);#if 0	  if (vad!=1)	    ms_message("WaveInCallback : %d", vad);#endif	}            rm->b_wptr+=framesPerBuffer*2;            putq(&device->rq,rm);      rm=NULL;    }  ms_mutex_unlock(&device->mutex);  return 0;}static int pasnd_open(PASndData *device, int devnumber, int bits,int stereo, int rate, int *minsz){    PaStreamParameters outputParameters;    PaStreamParameters inputParameters;    PaError err;    const PaHostApiInfo *pa_hai = Pa_GetHostApiInfo(Pa_GetDefaultHostApi());        ms_warning("pasnd_open : opening default input device: name=%s (%i)",	       pa_hai->name, pa_hai->defaultInputDevice);    ms_warning("pasnd_open : opening default output device name=%s (%i)",	       pa_hai->name, pa_hai->defaultOutputDevice);    outputParameters.device = devnumber; /* default output device */    outputParameters.device = pa_hai->defaultOutputDevice;    outputParameters.channelCount = 1;       /* stereo output */    outputParameters.sampleFormat = paInt16; /* 32 bit floating point output */    outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;    outputParameters.hostApiSpecificStreamInfo = NULL;    err = Pa_OpenStream(			&device->waveoutdev,	/* stream */			NULL,                   /* no input */			&outputParameters,	//			rate,			// double sampleRate			160*(rate/8000),	//unsigned long framesPerBuffer			paClipOff,			SpeakerCallback,	//PortAudioCallback *callback			(void *) device);	//void *userData    if (err != paNoError)    {        ms_warning("Failed to open out device. (Pa_OpenDefaultStream:0x%i)", err);        return -1;    }    inputParameters.device = devnumber; /* default input device */    inputParameters.device = pa_hai->defaultInputDevice;    inputParameters.channelCount = 1;       /* stereo input */    inputParameters.sampleFormat = paInt16; /* 32 bit floating point input */    inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;    inputParameters.hostApiSpecificStreamInfo = NULL;    err = Pa_OpenStream(			&device->waveindev,	//PortAudioStream** stream			&inputParameters,	/* input param*/			NULL,                   /* output param */			rate,			// double sampleRate			160*(rate/8000),	//unsigned long framesPerBuffer			paClipOff,			WaveInCallback,		//PortAudioCallback *callback			(void *) device);	//void *userData	    if (err != paNoError)    {        ms_warning("Failed to open in device. (Pa_OpenDefaultStream:0x%i)", err);        return -1;    }    err = Pa_StartStream( device->waveoutdev );    if( err != paNoError )      {        ms_warning("Failed to start out device. (Pa_StartStream:0x%i)", err);        return -1;      }	device->pst = speex_preprocess_state_init((device->rate/8000 * 320)/2, device->rate);	if (device->pst!=NULL) {		float f;		int i=1;		speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_VAD, &i);		i=1;		speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DENOISE, &i);		i=0;		speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_AGC, &i);		f=8000;		speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_AGC_LEVEL, &f);		i=0;		speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DEREVERB, &i);		f=.4;		speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f);		f=.3;		speex_preprocess_ctl(device->pst, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f);	}    err = Pa_StartStream( device->waveindev );    if( err != paNoError )      {        ms_warning("Failed to start in device: trying default device. (Pa_StartStream:0x%i)", err);        return -1;      }	*minsz=device->rate/8000 * 320;	return 0;}static void pasnd_set_level(MSSndCard *card, MSSndCardMixerElem e, int percent){	PASndData *d=(PASndData*)card->data;	if (d->mixdev==NULL) return;	switch(e){	case MS_SND_CARD_MASTER:	  return;	  break;        case MS_SND_CARD_CAPTURE:	  break;	case MS_SND_CARD_PLAYBACK:	  break;        default:	  ms_warning("pasnd_card_set_level: unsupported command.");	  return;	}}static int pasnd_get_level(MSSndCard *card, MSSndCardMixerElem e){	PASndData *d=(PASndData*)card->data;	if (d->mixdev==NULL) return -1;	switch(e){	case MS_SND_CARD_MASTER:	  return 60;	  break;        case MS_SND_CARD_CAPTURE:	  break;	case MS_SND_CARD_PLAYBACK:	  break;	default:	  ms_warning("pasnd_card_get_level: unsupported command.");	  return -1;	}	return -1;}static void pasnd_set_source(MSSndCard *card, MSSndCardCapture source){	PASndData *d=(PASndData*)card->data;	if (d->mixdev==NULL) return;	switch(source){		case MS_SND_CARD_MIC:		break;		case MS_SND_CARD_LINE:		break;	}	}static void pasnd_init(MSSndCard *card){	PASndData *d=ms_new(PASndData,1);	memset(d, 0, sizeof(PASndData));	d->pcmdev=NULL;	d->mixdev=NULL;	d->sound_err=-1; /* not opened */	d->read_started=FALSE;	d->write_started=FALSE;	d->bits=16;	d->rate=8000;	d->stereo=FALSE;	qinit(&d->rq);	d->bufferizer=ms_bufferizer_new();	ms_mutex_init(&d->mutex,NULL);	card->data=d;	d->pst=0;}static void pasnd_uninit(MSSndCard *card){	PASndData *d=(PASndData*)card->data;	if (d==NULL)		return;	if (d->pcmdev!=NULL) ms_free(d->pcmdev);	if (d->mixdev!=NULL) ms_free(d->mixdev);	ms_bufferizer_destroy(d->bufferizer);	flushq(&d->rq,0);	ms_mutex_destroy(&d->mutex);	if (d->pst!=NULL)	    speex_preprocess_state_destroy(d->pst);	ms_free(d);}#define DSP_NAME "/dev/dsp"#define MIXER_NAME "/dev/mixer"static void pasnd_detect(MSSndCardManager *m);static MSSndCard *pasnd_duplicate(MSSndCard *obj);MSSndCardDesc pasnd_card_desc={	"PASND",	pasnd_detect,	pasnd_init,	pasnd_set_level,	pasnd_get_level,	pasnd_set_source,	ms_pasnd_read_new,	ms_pasnd_write_new,	pasnd_uninit,	pasnd_duplicate};static MSSndCard *pasnd_duplicate(MSSndCard *obj){	MSSndCard *card=ms_snd_card_new(&pasnd_card_desc);	PASndData *dcard=(PASndData*)card->data;	PASndData *dobj=(PASndData*)obj->data;	dcard->pcmdev=ms_strdup(dobj->pcmdev);	dcard->mixdev=ms_strdup(dobj->mixdev);	card->name=ms_strdup(obj->name);	return card;}static MSSndCard *pasnd_card_new(const char *pcmdev, const char *mixdev){	MSSndCard *card=ms_snd_card_new(&pasnd_card_desc);	PASndData *d=(PASndData*)card->data;	d->pcmdev=ms_strdup(pcmdev);	d->mixdev=ms_strdup(mixdev);	card->name=ms_strdup(pcmdev);	return card;}static void pasnd_detect(MSSndCardManager *m){    int err = 0;    unsigned int numDevices;    const PaDeviceInfo *pdi;    char pcmdev[1024];    char mixdev[1024];    int i;    err = Pa_Initialize();    if( err != paNoError )      {	ms_warning("PortAudio error: %s\n", Pa_GetErrorText( err ) );	return;      }    numDevices = Pa_GetDeviceCount();    for( i=0; i<numDevices; i++ ) {      pdi = Pa_GetDeviceInfo( i );      if (pdi!=NULL)	{	  MSSndCard *card;	  snprintf(pcmdev,sizeof(pcmdev),"%s",pdi->name);	  snprintf(mixdev,sizeof(mixdev),"%s",pdi->name);	  if (i == 0)            {	      card=pasnd_card_new(pcmdev,mixdev);	      ms_snd_card_manager_add_card(m,card);            }	  card=pasnd_card_new(pcmdev,mixdev);	  ms_snd_card_manager_add_card(m,card);	}    }}static void pasnd_closedriver(PASndData *d){	if (d->sound_err==0) {	  int err = Pa_StopStream( d->waveindev );	  if( err != paNoError )	    {	      ms_warning("Failed to stop device. (Pa_StopStream:0x%i)", err);	    }	  	  err = Pa_CloseStream( d->waveindev);	  if( err != paNoError )	    {	      ms_warning("failed to close recording sound card (Pa_CloseStream:0x%i)", err);	    }	  else	    {	      ms_message("successfully closed recording sound card");	    }	  	  err = Pa_StopStream( d->waveoutdev );	  if( err != paNoError )	    {	      ms_warning("Failed to stop device. (Pa_StopStream:0x%i)", err);	    }	  	  err = Pa_CloseStream( d->waveoutdev );	  if( err != paNoError ) 	    {	      ms_error("failed to stop recording sound card (Pa_CloseStream:0x%i)", err);	    }	  else	    {	      ms_message("successfully stopped recording sound card");	    }	  	  	  d->sound_err=-1;	}}static void pasnd_start_r(MSSndCard *card){	PASndData *d=(PASndData*)card->data;	if (d->read_started==FALSE && d->write_started==FALSE){		int bsize=0;		d->read_started=TRUE;		d->sound_err=pasnd_open(d, 0, d->bits,d->stereo,d->rate,&bsize);	}else d->read_started=TRUE;}static void pasnd_stop_r(MSSndCard *card){	PASndData *d=(PASndData*)card->data;	d->read_started=FALSE;	if (d->write_started==FALSE){	  /* ms_thread_join(d->thread,NULL); */	  pasnd_closedriver(d);	}}static void pasnd_start_w(MSSndCard *card){	PASndData *d=(PASndData*)card->data;	if (d->read_started==FALSE && d->write_started==FALSE){		int bsize=0;		d->write_started=TRUE;		d->sound_err=pasnd_open(d, 0, d->bits,d->stereo,d->rate,&bsize);	}else{		d->write_started=TRUE;	}}static void pasnd_stop_w(MSSndCard *card){	PASndData *d=(PASndData*)card->data;	d->write_started=FALSE;	if (d->read_started==FALSE){	  /* ms_thread_join(d->thread,NULL); */	  pasnd_closedriver(d);	}}static mblk_t *pasnd_get(MSSndCard *card){	PASndData *d=(PASndData*)card->data;	mblk_t *m;	ms_mutex_lock(&d->mutex);	m=getq(&d->rq);	ms_mutex_unlock(&d->mutex);	return m;}static void pasnd_put(MSSndCard *card, mblk_t *m){	PASndData *d=(PASndData*)card->data;	ms_mutex_lock(&d->mutex);	ms_bufferizer_put(d->bufferizer,m);	ms_mutex_unlock(&d->mutex);}static void pasnd_read_preprocess(MSFilter *f){	MSSndCard *card=(MSSndCard*)f->data;	pasnd_start_r(card);}static void pasnd_read_postprocess(MSFilter *f){	MSSndCard *card=(MSSndCard*)f->data;	pasnd_stop_r(card);}static void pasnd_read_process(MSFilter *f){	MSSndCard *card=(MSSndCard*)f->data;	mblk_t *m;	while((m=pasnd_get(card))!=NULL){		ms_queue_put(f->outputs[0],m);	}}static void pasnd_write_preprocess(MSFilter *f){	MSSndCard *card=(MSSndCard*)f->data;	pasnd_start_w(card);}static void pasnd_write_postprocess(MSFilter *f){	MSSndCard *card=(MSSndCard*)f->data;	pasnd_stop_w(card);}static void pasnd_write_process(MSFilter *f){	MSSndCard *card=(MSSndCard*)f->data;	mblk_t *m;	while((m=ms_queue_get(f->inputs[0]))!=NULL){		pasnd_put(card,m);	}}static int set_rate(MSFilter *f, void *arg){	MSSndCard *card=(MSSndCard*)f->data;	PASndData *d=(PASndData*)card->data;	d->rate=*((int*)arg);	return 0;}static int set_nchannels(MSFilter *f, void *arg){	MSSndCard *card=(MSSndCard*)f->data;	PASndData *d=(PASndData*)card->data;	d->stereo=(*((int*)arg)==2);	return 0;}static MSFilterMethod pasnd_methods[]={	{	MS_FILTER_SET_SAMPLE_RATE	, set_rate	},	{	MS_FILTER_SET_NCHANNELS		, set_nchannels	},	{	0				, NULL		}};MSFilterDesc pasnd_read_desc={	MS_PASND_READ_ID,	"MSPasndRead",	"Sound capture filter for Port Audio Sound drivers",	MS_FILTER_OTHER,	NULL,	0,	1,	NULL,	pasnd_read_preprocess,	pasnd_read_process,	pasnd_read_postprocess,	NULL,	pasnd_methods};MSFilterDesc pasnd_write_desc={	MS_PASND_WRITE_ID,	"MSPasndWrite",	"Sound playback filter for Port Audio Sound drivers",	MS_FILTER_OTHER,	NULL,	1,	0,	NULL,	pasnd_write_preprocess,	pasnd_write_process,	pasnd_write_postprocess,	NULL,	pasnd_methods};MSFilter *ms_pasnd_read_new(MSSndCard *card){	MSFilter *f=ms_filter_new_from_desc(&pasnd_read_desc);	f->data=card;	return f;}MSFilter *ms_pasnd_write_new(MSSndCard *card){	MSFilter *f=ms_filter_new_from_desc(&pasnd_write_desc);	f->data=card;	return f;}MS_FILTER_DESC_EXPORT(pasnd_read_desc)MS_FILTER_DESC_EXPORT(pasnd_write_desc)

⌨️ 快捷键说明

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