Пример #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");
			freemsg(m);
			ctl->current_pos += nsamples;
			m=NULL;
		} 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;
}
Пример #2
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;
}