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

📄 speexec.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 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 "mediastreamer2/msfilter.h"#include <speex/speex_echo.h>#include <speex/speex_preprocess.h>#ifdef HAVE_CONFIG_H#include "mediastreamer-config.h"#endif#ifdef WIN32#include <malloc.h> /* for alloca */#endifstatic const int framesize=128;static const int filter_length=2048; /*250 ms*/typedef struct SpeexECState{	SpeexEchoState *ecstate;	MSBufferizer speak_delay;	int size_delay;	int playback_delay;	MSBufferizer in[2];	int framesize;	int filterlength;	int samplerate;	SpeexPreprocessState *den;        int ref;        int echo;        int out;}SpeexECState;static void speex_ec_init(MSFilter *f){	SpeexECState *s=(SpeexECState *)ms_new(SpeexECState,1);	s->samplerate=8000;	s->framesize=framesize;	s->filterlength=filter_length;	ms_bufferizer_init(&s->speak_delay);	s->size_delay=0;	s->playback_delay=0;	ms_bufferizer_init(&s->in[0]);	ms_bufferizer_init(&s->in[1]);	s->ecstate=speex_echo_state_init(s->framesize,s->filterlength);	s->den = speex_preprocess_state_init(s->framesize, s->samplerate);	speex_echo_ctl(s->ecstate, SPEEX_ECHO_SET_SAMPLING_RATE, &s->samplerate);	speex_preprocess_ctl(s->den, SPEEX_PREPROCESS_SET_ECHO_STATE, s->ecstate);	f->data=s;}static void speex_ec_uninit(MSFilter *f){	SpeexECState *s=(SpeexECState*)f->data;	ms_bufferizer_uninit(&s->speak_delay);	ms_bufferizer_uninit(&s->in[0]);	ms_bufferizer_uninit(&s->in[1]);	speex_echo_state_destroy(s->ecstate);	if (s->den!=NULL)	  speex_preprocess_state_destroy(s->den);	ms_free(s);}/*	inputs[0]= reference signal (sent to soundcard)	inputs[1]= echo signal	(read from soundcard)*/static void speex_ec_process(MSFilter *f){	SpeexECState *s=(SpeexECState*)f->data;	int nbytes=s->framesize*2;	uint8_t *in1;	mblk_t *om0,*om1;#ifdef AMD_WIN32_HACK	static int count=0;#endif	mblk_t *m;	mblk_t *md;		if (s->size_delay<s->playback_delay){		while((m=ms_queue_get(f->inputs[0]))!=NULL        && s->size_delay<s->playback_delay){			// Duplicate queue : one to write to the output speaker, the other will be delayed for AEC			int size=msgdsize(m);    	  	md = copyb(m);	      	s->size_delay = s->size_delay + size;			ms_queue_put(f->outputs[0],md);    	  	ms_bufferizer_put(&s->in[0],m);		}		while((m=ms_queue_get(f->inputs[1]))!=NULL){    		ms_queue_put(f->outputs[1],m);		}		/* we are now equal and speaker is delayed */		return;    }	ms_bufferizer_put_from_queue(&s->in[1],f->inputs[1]);	/*read input and put in bufferizers*/	while((m=ms_queue_get(f->inputs[0]))!=NULL){		md = copyb(m);		// Duplicate queue : one to write to the output speaker, the other will be delayed for AEC		ms_bufferizer_put(&s->in[0],m);		ms_bufferizer_put(&s->speak_delay,md);		}		in1=(uint8_t*)alloca(nbytes);	//ms_debug("speexec:  in0=%i, in1=%i",ms_bufferizer_get_avail(&s->in[0]),ms_bufferizer_get_avail(&s->in[1]));	while (ms_bufferizer_get_avail(&s->speak_delay)>=nbytes && ms_bufferizer_get_avail(&s->in[1])>=nbytes){		om0=allocb(nbytes,0);		ms_bufferizer_read(&s->speak_delay,(uint8_t*)om0->b_wptr,nbytes);		om0->b_wptr+=nbytes;		ms_queue_put(f->outputs[0],om0);		om0=allocb(nbytes,0);		ms_bufferizer_read(&s->in[0],(uint8_t*)om0->b_wptr,nbytes);		/* we have reference signal */		/* the reference signal is sent through outputs[0]*/				om0->b_wptr+=nbytes;		//ms_queue_put(f->outputs[0],om0);		ms_bufferizer_read(&s->in[1],in1,nbytes);		/* we have echo signal */		om1=allocb(nbytes,0);		speex_echo_cancel(s->ecstate,(short*)in1,(short*)om0->b_rptr,(short*)om1->b_wptr,NULL);		speex_preprocess_run(s->den, (short*)om1->b_wptr);		om1->b_wptr+=nbytes;		ms_queue_put(f->outputs[1],om1);#ifdef AMD_WIN32_HACK		count++;		if (count==100*3)		{			ms_message("periodic reset of echo canceller.");			speex_echo_state_reset(s->ecstate);			count=0;		}		#endif    freeb(om0);	}	if (ms_bufferizer_get_avail(&s->speak_delay)> 4*320*(s->samplerate/8000)) /* above 4*20ms -> useless */	  {	    /* reset evrything */	    ms_warning("speexec: -reset of echo canceller- in0=%i, in1=%i",ms_bufferizer_get_avail(&s->in[0]),ms_bufferizer_get_avail(&s->in[1]));	    flushq(&s->in[1].q,0);	    flushq(&s->in[0].q,0);      flushq(&s->speak_delay.q,0);	    ms_bufferizer_init(&s->in[0]);	    ms_bufferizer_init(&s->in[1]);	    ms_bufferizer_init(&s->speak_delay);      s->size_delay=0;	    speex_echo_state_reset(s->ecstate);	  }	while (ms_bufferizer_get_avail(&s->in[1])> 4*320*(s->samplerate/8000)){		om1=allocb(nbytes,0);		ms_bufferizer_read(&s->in[1],(uint8_t*)om1->b_wptr,nbytes);		om1->b_wptr+=nbytes;		ms_queue_put(f->outputs[1],om1);		ms_message("too much echo signal, sending anyway.");		speex_echo_state_reset(s->ecstate);	}	}static void speex_ec_postprocess(MSFilter *f){	SpeexECState *s=(SpeexECState*)f->data;	flushq(&s->in[1].q,0);	flushq(&s->in[0].q,0);	flushq(&s->speak_delay.q,0);	ms_bufferizer_init(&s->in[0]);	ms_bufferizer_init(&s->in[1]);	ms_bufferizer_init(&s->speak_delay);	s->size_delay=0;	if (s->ecstate!=NULL)		speex_echo_state_destroy(s->ecstate);	if (s->den!=NULL)	  speex_preprocess_state_destroy(s->den);	s->ecstate=speex_echo_state_init(s->framesize,s->filterlength*(s->samplerate/8000));	s->den = speex_preprocess_state_init(s->framesize, s->samplerate);	speex_echo_ctl(s->ecstate, SPEEX_ECHO_SET_SAMPLING_RATE, &s->samplerate);	speex_preprocess_ctl(s->den, SPEEX_PREPROCESS_SET_ECHO_STATE, s->ecstate);}static int speex_ec_set_sr(MSFilter *f, void *arg){	SpeexECState *s=(SpeexECState*)f->data;	s->samplerate = *(int*)arg;	if (s->ecstate!=NULL)		speex_echo_state_destroy(s->ecstate);	if (s->den!=NULL)	  speex_preprocess_state_destroy(s->den);	s->ecstate=speex_echo_state_init(s->framesize,s->filterlength*(s->samplerate/8000));	s->den = speex_preprocess_state_init(s->framesize, s->samplerate);	speex_echo_ctl(s->ecstate, SPEEX_ECHO_SET_SAMPLING_RATE, &s->samplerate);	speex_preprocess_ctl(s->den, SPEEX_PREPROCESS_SET_ECHO_STATE, s->ecstate);	return 0;}static int speex_ec_set_framesize(MSFilter *f, void *arg){	SpeexECState *s=(SpeexECState*)f->data;	s->framesize = *(int*)arg;	if (s->ecstate!=NULL)		speex_echo_state_destroy(s->ecstate);	if (s->den!=NULL)	  speex_preprocess_state_destroy(s->den);	s->ecstate=speex_echo_state_init(s->framesize,s->filterlength*(s->samplerate/8000));	s->den = speex_preprocess_state_init(s->framesize, s->samplerate);	speex_echo_ctl(s->ecstate, SPEEX_ECHO_SET_SAMPLING_RATE, &s->samplerate);	speex_preprocess_ctl(s->den, SPEEX_PREPROCESS_SET_ECHO_STATE, s->ecstate);	return 0;}static int speex_ec_set_filterlength(MSFilter *f, void *arg){	SpeexECState *s=(SpeexECState*)f->data;	s->filterlength = *(int*)arg;	if (s->ecstate!=NULL)		speex_echo_state_destroy(s->ecstate);	if (s->den!=NULL)	  speex_preprocess_state_destroy(s->den);	s->ecstate=speex_echo_state_init(s->framesize,s->filterlength*(s->samplerate/8000));	s->den = speex_preprocess_state_init(s->framesize, s->samplerate);	speex_echo_ctl(s->ecstate, SPEEX_ECHO_SET_SAMPLING_RATE, &s->samplerate);	speex_preprocess_ctl(s->den, SPEEX_PREPROCESS_SET_ECHO_STATE, s->ecstate);	return 0;}static int speex_ec_set_playbackdelay(MSFilter *f, void *arg){	SpeexECState *s=(SpeexECState*)f->data;		s->playback_delay = *(int*)arg;	flushq(&s->in[1].q,0);	flushq(&s->in[0].q,0);	flushq(&s->speak_delay.q,0);	ms_bufferizer_init(&s->in[0]);	ms_bufferizer_init(&s->in[1]);	ms_bufferizer_init(&s->speak_delay);	s->size_delay=0;	speex_echo_state_reset(s->ecstate);	return 0;}static MSFilterMethod speex_ec_methods[]={	{	MS_FILTER_SET_SAMPLE_RATE, speex_ec_set_sr },	{	MS_FILTER_SET_FRAMESIZE, speex_ec_set_framesize },	{	MS_FILTER_SET_FILTERLENGTH, speex_ec_set_filterlength },  {	MS_FILTER_SET_PLAYBACKDELAY, speex_ec_set_playbackdelay },	{	0			, NULL}};#ifdef _MSC_VERMSFilterDesc ms_speex_ec_desc={	MS_SPEEX_EC_ID,	"MSSpeexEC",	N_("Echo canceler using speex library"),	MS_FILTER_OTHER,	NULL,	2,	2,	speex_ec_init,	NULL,	speex_ec_process,	speex_ec_postprocess,	speex_ec_uninit,	speex_ec_methods};#elseMSFilterDesc ms_speex_ec_desc={	.id=MS_SPEEX_EC_ID,	.name="MSSpeexEC",	.text=N_("Echo canceler using speex library"),	.category=MS_FILTER_OTHER,	.ninputs=2,	.noutputs=2,	.init=speex_ec_init,	.process=speex_ec_process,	.postprocess=speex_ec_postprocess,	.uninit=speex_ec_uninit,	.methods=speex_ec_methods};#endifMS_FILTER_DESC_EXPORT(ms_speex_ec_desc)

⌨️ 快捷键说明

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