static void generic_plc_process(MSFilter *f) {
	generic_plc_struct *mgps=(generic_plc_struct*)f->data;
	unsigned int buff_size = mgps->rate*sizeof(int16_t)*mgps->nchannels*f->ticker->interval/1000;
	mblk_t *m;
	while((m=ms_queue_get(f->inputs[0]))!=NULL){
		int transitionBufferSize = mgps->rate*sizeof(int16_t)*TRANSITION_DELAY/1000;
		unsigned char buf[128];
		unsigned int time = (1000*(m->b_wptr - m->b_rptr))/(mgps->rate*sizeof(int16_t)*mgps->nchannels);
		ms_concealer_inc_sample_time(mgps->concealer, f->ticker->time, time, TRUE);

		/* introduce 16 sample delay (2ms) */
		memcpy(buf, m->b_wptr-transitionBufferSize, transitionBufferSize);
		memmove(m->b_rptr+transitionBufferSize, m->b_rptr, m->b_wptr - m->b_rptr - transitionBufferSize);
		memcpy(m->b_rptr, mgps->continuity_buffer, transitionBufferSize);
		memcpy(mgps->continuity_buffer, buf, transitionBufferSize);

		if (mgps->cng_running){
			/*we were doing CNG, now resuming with normal audio*/
			int16_t continuity_buffer[80];
#ifdef HAVE_G729B
			bcg729Decoder(mgps->decoderChannelContext, NULL, 0, 1, 1, 1, continuity_buffer);
#else
			memset (continuity_buffer, 0, 80*sizeof(int16_t));
#endif
			memcpy(m->b_rptr, continuity_buffer, transitionBufferSize);
			generic_plc_transition_mix((int16_t *)(m->b_rptr+transitionBufferSize), &(continuity_buffer[mgps->rate*TRANSITION_DELAY/1000]), mgps->rate*TRANSITION_DELAY/1000);
			mgps->cng_running=FALSE;
			mgps->cng_set=FALSE;
		}

		ms_queue_put(f->outputs[0], m);
	}
	if (ms_concealer_context_is_concealement_required(mgps->concealer, f->ticker->time)) {
#ifdef HAVE_G729B
		m = allocb(buff_size, 0);
		
		/* Transmitted CNG data is in mgps->cng_data : give it to bcg729 decoder -> output in m->b_wptr */
		if (mgps->cng_set) { /* received some CNG data */
			mgps->cng_set=FALSE; /* reset flag */
			mgps->cng_running=TRUE;

			bcg729Decoder(mgps->decoderChannelContext, mgps->cng_data.data, mgps->cng_data.datasize, 0, 1, 1, (int16_t *)(m->b_wptr));
			mblk_set_cng_flag(m, 1);
			generic_plc_transition_mix((int16_t *)m->b_wptr, (int16_t *)mgps->continuity_buffer, mgps->rate*TRANSITION_DELAY/1000);
			/* TODO: if ticker->interval is not 10 ms which is also G729 frame length, we must generate untransmitted frame CNG until we reach the requested data amount */
		} else if (mgps->cng_running) { /* missing frame but CNG is ongoing: shall be an untransmitted frame */
			bcg729Decoder(mgps->decoderChannelContext, NULL, 0, 1, 1, 1, (int16_t *)(m->b_wptr));
			mblk_set_cng_flag(m, 1);
		} else {
			mblk_set_plc_flag(m, 1);
			memset(m->b_wptr, 0, buff_size);
		}
#else
		m = allocb(buff_size, 0);
		if (!mgps->cng_running && mgps->cng_set){
			mgps->cng_running=TRUE;
			mblk_set_cng_flag(m, 1);
			/*TODO do something with the buffer*/
		}else{
			mblk_set_plc_flag(m, 1);
		}
		memset(m->b_wptr, 0, buff_size);

#endif
		m->b_wptr += buff_size;
		ms_queue_put(f->outputs[0], m);
		ms_concealer_inc_sample_time(mgps->concealer, f->ticker->time, f->ticker->interval, FALSE);
	}
}
示例#2
0
void generic_plc_generate_samples(plc_context_t *context, int16_t *data, uint16_t sample_nbr) {
	uint16_t continuity_buffer_sample_nbr = context->sample_rate*TRANSITION_DELAY/1000;

	/* shall we just set everything to 0 */
	if (context->plc_samples_used>=MAX_PLC_LEN*context->sample_rate/1000) {
		context->plc_samples_used += sample_nbr;
		memset(data, 0, sample_nbr*sizeof(int16_t));
		memset(context->continuity_buffer, 0, 2*continuity_buffer_sample_nbr*sizeof(int16_t));

		return;
	}

	/* it's the first missing packet, we must generate samples */
	if (context->plc_samples_used == 0) {
		/* generate samples based on the plc_buffer(previously received signal)*/
		generic_plc_fftbf(context, (int16_t *)context->plc_buffer, context->plc_out_buffer, context->sample_rate*PLC_BUFFER_LEN);

		/* mix with continuity buffer */
		generic_plc_transition_mix(context->plc_out_buffer, (int16_t *)context->continuity_buffer, continuity_buffer_sample_nbr);
	}

	/* we being asked for more sample than we have in the buffer (save some for continuity buffer, we must have twice the TRANSITION_DELAY in buffer) */
	if (context->plc_index + sample_nbr + continuity_buffer_sample_nbr*2 > 2*context->sample_rate*PLC_BUFFER_LEN ) {
		uint16_t samples_ready_nbr = 2*context->sample_rate*PLC_BUFFER_LEN - context->plc_index - continuity_buffer_sample_nbr;

		if (samples_ready_nbr>sample_nbr) { /* we had more than one but less than two TRANSITION_DELAY ms in buffer */
			samples_ready_nbr=sample_nbr;
		}

		/* copy all the remaining sample to the data buffer (save some for continuity) */
		memcpy(data, context->plc_out_buffer+context->plc_index, samples_ready_nbr*sizeof(int16_t));
		memcpy(context->continuity_buffer, context->plc_out_buffer+context->plc_index+samples_ready_nbr, continuity_buffer_sample_nbr * sizeof(int16_t));

		/* generate sample based on the plc_out_buffer(previously generated signal) */
		generic_plc_fftbf(context, context->plc_out_buffer, context->plc_out_buffer, context->sample_rate*PLC_BUFFER_LEN);

		/* mix with continuity buffer */
		generic_plc_transition_mix(context->plc_out_buffer, (int16_t *)context->continuity_buffer, continuity_buffer_sample_nbr);

		/* copy the rest of requested samples to the data buffer */
		if (sample_nbr!=samples_ready_nbr) {
			memcpy(data+samples_ready_nbr, context->plc_out_buffer, (sample_nbr - samples_ready_nbr)*sizeof(int16_t));
		}

		context->plc_index = sample_nbr - samples_ready_nbr;
		/* manage continuity buffer */
		memcpy(context->continuity_buffer, context->plc_out_buffer + context->plc_index, 2*continuity_buffer_sample_nbr * sizeof(int16_t));
	} else {

		/* copy the requested amount of data to the given buffer and update continuity buffer */
		memcpy(data, context->plc_out_buffer+context->plc_index, sample_nbr*sizeof(int16_t));

		context->plc_index += sample_nbr;
		/* update continuity buffer */
		memcpy(context->continuity_buffer, context->plc_out_buffer + context->plc_index, 2*continuity_buffer_sample_nbr * sizeof(int16_t));

	}

	/* adjust volume when PLC_DECREASE_START samples point is reached */
	if ( context->plc_samples_used + sample_nbr > PLC_DECREASE_START*context->sample_rate/1000 ) {
		int i = PLC_DECREASE_START*context->sample_rate/1000 - context->plc_samples_used;
		if (i<0) i=0;
		for (; i<sample_nbr; i++) {
			if (context->plc_samples_used+i>=MAX_PLC_LEN*context->sample_rate/1000) {
				data[i] = 0;
			} else {
				data[i] = (int16_t)((1.0+((float)(PLC_DECREASE_START*context->sample_rate/1000 - (context->plc_samples_used + i))/(float)((MAX_PLC_LEN-PLC_DECREASE_START)*context->sample_rate/1000))) * (float)data[i]);
			}
		}
	}
	context->plc_samples_used += sample_nbr;
}
示例#3
0
static void generic_plc_process(MSFilter *f) {
	generic_plc_struct *mgps=(generic_plc_struct*)f->data;
	plc_context_t *plc_context = mgps->plc_context;
	mblk_t *m;

	while((m=ms_queue_get(f->inputs[0]))!=NULL){
		int transitionBufferSize = mgps->rate*sizeof(int16_t)*TRANSITION_DELAY/1000;
		size_t msg_size = msgdsize(m);
		unsigned int time = (unsigned int)((1000*msg_size)/(mgps->rate*sizeof(int16_t)*mgps->nchannels));
		ms_concealer_inc_sample_time(mgps->concealer, f->ticker->time, time, TRUE);

		/* Store current msg in plc_buffer */
		generic_plc_update_plc_buffer(plc_context, m->b_rptr, msg_size);

		/* introduce delay (TRANSITION_DELAY ms) */
		generic_plc_update_continuity_buffer(plc_context, m->b_rptr, msg_size);

		if (mgps->cng_running){
			/*we were doing CNG, now resuming with normal audio*/
			int16_t continuity_buffer[80];
#ifdef HAVE_G729B
			bcg729Decoder(mgps->decoderChannelContext, NULL, 0, 1, 1, 1, continuity_buffer);
#else
			memset (continuity_buffer, 0, 80*sizeof(int16_t));
#endif
			memcpy(m->b_rptr, continuity_buffer, transitionBufferSize);
			generic_plc_transition_mix((int16_t *)(m->b_rptr+transitionBufferSize), continuity_buffer, mgps->rate*TRANSITION_DELAY/1000);
			mgps->cng_running=FALSE;
			mgps->cng_set=FALSE;
		}

		if (plc_context->plc_samples_used!=0) {
			/*we were doing PLC, now resuming with normal audio, continuity buffer is twice the transition delay lengths,
			 * the second half is untouched by the update function and contains transition data generated by PLC */
			generic_plc_transition_mix((int16_t *)(m->b_rptr+transitionBufferSize), (int16_t *)(plc_context->continuity_buffer+transitionBufferSize), mgps->rate*TRANSITION_DELAY/1000);
		}
		plc_context->plc_index=0;
		plc_context->plc_samples_used=0;

		ms_queue_put(f->outputs[0], m);
	}
	if (ms_concealer_context_is_concealement_required(mgps->concealer, f->ticker->time)) {
		unsigned int buff_size = mgps->rate*sizeof(int16_t)*mgps->nchannels*f->ticker->interval/1000;
#ifdef HAVE_G729B
		m = allocb(buff_size, 0);

		/* Transmitted CNG data is in mgps->cng_data : give it to bcg729 decoder -> output in m->b_wptr */
		if (mgps->cng_set) { /* received some CNG data */
			mgps->cng_set=FALSE; /* reset flag */
			mgps->cng_running=TRUE;

			bcg729Decoder(mgps->decoderChannelContext, mgps->cng_data.data, mgps->cng_data.datasize, 0, 1, 1, (int16_t *)(m->b_wptr));
			mblk_set_cng_flag(m, 1);
			generic_plc_transition_mix((int16_t *)m->b_wptr, (int16_t *)plc_context->continuity_buffer, mgps->rate*TRANSITION_DELAY/1000);
			/* TODO: if ticker->interval is not 10 ms which is also G729 frame length, we must generate untransmitted frame CNG until we reach the requested data amount */
		} else if (mgps->cng_running) { /* missing frame but CNG is ongoing: shall be an untransmitted frame */
			bcg729Decoder(mgps->decoderChannelContext, NULL, 0, 1, 1, 1, (int16_t *)(m->b_wptr));
			mblk_set_cng_flag(m, 1);
		} else { /* plc */
			mblk_set_plc_flag(m, 1);
			generic_plc_generate_samples(plc_context, (int16_t *)m->b_wptr, buff_size/sizeof(int16_t));
			/* store the generated samples into plc_buffer */
			generic_plc_update_plc_buffer(plc_context, m->b_wptr, buff_size);
			//memset(m->b_wptr, 0, buff_size);
		}
#else
		m = allocb(buff_size, 0);
		if (mgps->cng_set){
			mgps->cng_set=FALSE; /* reset flag */
			mgps->cng_running=TRUE;
			mblk_set_cng_flag(m, 1);
			/*TODO do something with the buffer*/
			memset(m->b_wptr, 0, buff_size);
		} else if (mgps->cng_running) { /* missing frame but CNG is ongoing: shall be an untransmitted frame */
			memset(m->b_wptr, 0, buff_size);
			mblk_set_cng_flag(m, 1);
		}else{ /* plc */
			mblk_set_plc_flag(m, 1);
			generic_plc_generate_samples(plc_context, (int16_t *)m->b_wptr, buff_size/sizeof(int16_t));
			/* store the generated samples into plc_buffer */
			generic_plc_update_plc_buffer(plc_context, m->b_wptr, buff_size);
			//memset(m->b_wptr, 0, buff_size);
		}

#endif
		m->b_wptr += buff_size;
		ms_queue_put(f->outputs[0], m);
		ms_concealer_inc_sample_time(mgps->concealer, f->ticker->time, f->ticker->interval, FALSE);
	}
}