Ejemplo n.º 1
0
static void discard_well_choosed_samples(mblk_t *m, int nsamples, int todrop){
	int i;
	int16_t *samples=(int16_t*)m->b_rptr;
	int min_diff=32768;
	int pos=0;

	
#ifdef TWO_SAMPLES_CRITERIA
	for(i=0;i<nsamples-1;++i){
		int tmp=abs((int)samples[i]- (int)samples[i+1]);
#else
	for(i=0;i<nsamples-2;++i){
		int tmp=abs((int)samples[i]- (int)samples[i+1])+abs((int)samples[i+1]- (int)samples[i+2]);
#endif
		if (tmp<=min_diff){
			pos=i;
			min_diff=tmp;
		}
	}
	/*ms_message("min_diff=%i at pos %i",min_diff, pos);*/
#ifdef TWO_SAMPLES_CRITERIA
	memmove(samples+pos,samples+pos+1,(nsamples-pos-1)*2);
#else
	memmove(samples+pos+1,samples+pos+2,(nsamples-pos-2)*2);
#endif
	
	todrop--;
	m->b_wptr-=2;
	nsamples--;
	if (todrop>0){
		/*repeat the same process again*/
		discard_well_choosed_samples(m,nsamples,todrop);
	}
}

mblk_t * audio_flow_controller_process(AudioFlowController *ctl, mblk_t *m){
	if (ctl->total_samples>0 && ctl->target_samples>0){
		int nsamples=(m->b_wptr-m->b_rptr)/2;
		if (ctl->target_samples*16>ctl->total_samples){
			ms_warning("Too many samples to drop, dropping entire frames");
			m->b_wptr=m->b_rptr;
			ctl->current_pos+=nsamples;
		}else{
			int th_dropped;
			int todrop;
	
			ctl->current_pos+=nsamples;
			th_dropped=(ctl->target_samples*ctl->current_pos)/ctl->total_samples;
			todrop=th_dropped-ctl->current_dropped;
			if (todrop>0){
				if (todrop>nsamples) todrop=nsamples;
				discard_well_choosed_samples(m,nsamples,todrop);
				/*ms_message("th_dropped=%i, current_dropped=%i, %i samples dropped.",th_dropped,ctl->current_dropped,todrop);*/
				ctl->current_dropped+=todrop;
			}
		}
		if (ctl->current_pos>=ctl->total_samples) ctl->target_samples=0;/*stop discarding*/
	}
	return m;
}


//#define EC_DUMP 1
#ifdef ANDROID
#define EC_DUMP_PREFIX "/sdcard"
#else
#define EC_DUMP_PREFIX "."
#endif

static const float smooth_factor=0.05;
static const int framesize=64;
static const int flow_control_interval_ms=5000;


typedef struct SpeexECState{
	SpeexEchoState *ecstate;
	SpeexPreprocessState *den;
	MSBufferizer delayed_ref;
	MSBufferizer ref;
	MSBufferizer echo;
	int framesize;
	int filterlength;
	int samplerate;
	int delay_ms;
	int tail_length_ms;
	int nominal_ref_samples;
	int min_ref_samples;
	AudioFlowController afc;
	uint64_t flow_control_time;
	char *state_str;
#ifdef EC_DUMP
	FILE *echofile;
	FILE *reffile;
	FILE *cleanfile;
#endif
	bool_t echostarted;
	bool_t bypass_mode;
	bool_t using_zeroes;
}SpeexECState;

static void speex_ec_init(MSFilter *f){
	SpeexECState *s=(SpeexECState *)ms_new(SpeexECState,1);

	s->samplerate=8000;
	ms_bufferizer_init(&s->delayed_ref);
	ms_bufferizer_init(&s->echo);
	ms_bufferizer_init(&s->ref);
	s->delay_ms=0;
	s->tail_length_ms=250;
	s->ecstate=NULL;
	s->framesize=framesize;
	s->den = NULL;
	s->state_str=NULL;
	s->using_zeroes=FALSE;
	s->echostarted=FALSE;
	s->bypass_mode=FALSE;

#ifdef EC_DUMP
	{
		char *fname=ms_strdup_printf("%s/msspeexec-%p-echo.raw", EC_DUMP_PREFIX,f);
		s->echofile=fopen(fname,"w");
		ms_free(fname);
		fname=ms_strdup_printf("%s/msspeexec-%p-ref.raw", EC_DUMP_PREFIX,f);
		s->reffile=fopen(fname,"w");
		ms_free(fname);
		fname=ms_strdup_printf("%s/msspeexec-%p-clean.raw", EC_DUMP_PREFIX,f);
		s->cleanfile=fopen(fname,"w");
		ms_free(fname);
	}
#endif
	
	f->data=s;
}
Ejemplo n.º 2
0
 msandroid_sound_read_data() : audio_record(0),audio_record_class(0),read_buff(0),read_chunk_size(0) {
     ms_bufferizer_init(&rb);
     aec=NULL;
 }
Ejemplo n.º 3
0
static void channel_init(ConfState *s, Channel *chan, int pos){
#ifndef DISABLE_SPEEX
	float f;
	int val;
#endif
	memset(chan, 0, sizeof(Channel));
	ms_bufferizer_init(&chan->buff);
#ifndef DISABLE_SPEEX
	chan->speex_pp = speex_preprocess_state_init(s->conf_gran/2, s->samplerate);
	if (chan->speex_pp==NULL)
		return;

	/* configure sound card input on pin 0 */
	val=0;
	if (pos==0)
		val=1;

	if (s->enable_halfduplex>0 && pos%2==1)
		val=1;

	speex_preprocess_ctl(chan->speex_pp, SPEEX_PREPROCESS_SET_DENOISE, &val);
	val = -30;
	speex_preprocess_ctl(chan->speex_pp, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &val);

	/* enable VAD only on incoming RTP stream */
	val=0;
	if (pos%2==1 || (pos==0 && s->enable_halfduplex>0))
	{
		val=1;
	}

	speex_preprocess_ctl(chan->speex_pp, SPEEX_PREPROCESS_SET_VAD, &val);
	if (s->vad_prob_start>0 && s->vad_prob_continue>0)
	{
		val = s->vad_prob_start; // xx%
		speex_preprocess_ctl(chan->speex_pp, SPEEX_PREPROCESS_SET_PROB_START, &val);
		val = s->vad_prob_continue; // xx%
		speex_preprocess_ctl(chan->speex_pp, SPEEX_PREPROCESS_SET_PROB_CONTINUE, &val);
	}

	/* enable AGC only on local soundcard */
	val=0;
	f=12000;
	if (s->agc_level>0 && pos==0)
		val=1;
	else if (pos==0 && s->enable_halfduplex>0)
		val=1;
	else if ( pos%2==1 && s->enable_halfduplex>0)
		val=1; //1; should not do that
	if (s->agc_level>0)
		f=(float)s->agc_level;


	speex_preprocess_ctl(chan->speex_pp, SPEEX_PREPROCESS_SET_AGC, &val);
	speex_preprocess_ctl(chan->speex_pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &f);

	val=s->max_gain;
	if ( pos%2==1 && s->enable_halfduplex>0)
		val=1;

	speex_preprocess_ctl(chan->speex_pp, SPEEX_PREPROCESS_SET_AGC_MAX_GAIN, &val);

	val=0;
#if 0
	val=1; // do more testing
#endif
	speex_preprocess_ctl(chan->speex_pp, SPEEX_PREPROCESS_SET_DEREVERB, &val);
	f=(float).4;
	speex_preprocess_ctl(chan->speex_pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f);
	f=(float).3;
	speex_preprocess_ctl(chan->speex_pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f);

#endif
}