static void _preextrapolate_helper(vorbis_dsp_state *v) { int i; int order=32; float *lpc=(float *)alloca(order*sizeof(*lpc)); float *work=(float *)alloca(v->pcm_current*sizeof(*work)); long j; v->preextrapolate=1; if(v->pcm_current-v->centerW>order*2) { /* safety */ for(i=0; i<v->vi->channels; i++) { /* need to run the extrapolation in reverse! */ for(j=0; j<v->pcm_current; j++) work[j]=v->pcm[i][v->pcm_current-j-1]; /* prime as above */ vorbis_lpc_from_data(work,lpc,v->pcm_current-v->centerW,order); /* run the predictor filter */ vorbis_lpc_predict(lpc,work+v->pcm_current-v->centerW-order, order, work+v->pcm_current-v->centerW, v->centerW); for(j=0; j<v->pcm_current; j++) v->pcm[i][v->pcm_current-j-1]=work[j]; } } }
void CoreAudioPaddedEncoder::extrapolate(float *input, size_t ilen, float *output, size_t olen) { unsigned n = getInputDescription().mChannelsPerFrame; float lpc[LPC_ORDER]; for (unsigned i = 0; i < n; ++i) { vorbis_lpc_from_data(input + i, lpc, ilen, LPC_ORDER, n); vorbis_lpc_predict(lpc, &input[i + n * (ilen - LPC_ORDER)], LPC_ORDER, output + i, olen, n); } }
static int extrapolate(extrapolater_t *self, const buffer_t *bp, void *dst, unsigned nframes) { const pcm_sample_description_t *sfmt = pcm_get_format(self->src); unsigned i, n = sfmt->channels_per_frame; float lpc[LPC_ORDER]; for (i = 0; i < n; ++i) { vorbis_lpc_from_data(bp->data + i, lpc, bp->count, LPC_ORDER, n); vorbis_lpc_predict(lpc, &bp->data[i + n * (bp->count - LPC_ORDER)], LPC_ORDER, (sample_t*)dst + i, nframes, n); } return nframes; }
static void _preextrapolate_helper( vorbis_dsp_state *v ) { int i; int order = 16; float *lpc = alloca( order * sizeof( *lpc ) ); float *work = alloca( v->pcm_current * sizeof( *work ) ); long j; v->preextrapolate = 1; if ( v->pcm_current - v->centerW > order*2 ) { /* safety */ for ( i = 0;i < v->vi->channels;i++ ) { /* need to run the extrapolation in reverse! */ for ( j = 0;j < v->pcm_current;j++ ) work[j] = v->pcm[i][v->pcm_current-j-1]; /* prime as above */ vorbis_lpc_from_data( work, lpc, v->pcm_current - v->centerW, order ); #if 0 if ( v->vi->channels == 2 ) { if ( i == 0 ) _analysis_output( "predataL", 0, work, v->pcm_current - v->centerW, 0, 0, 0 ); else _analysis_output( "predataR", 0, work, v->pcm_current - v->centerW, 0, 0, 0 ); } else { _analysis_output( "predata", 0, work, v->pcm_current - v->centerW, 0, 0, 0 ); } #endif /* run the predictor filter */ vorbis_lpc_predict( lpc, work + v->pcm_current - v->centerW - order, order, work + v->pcm_current - v->centerW, v->centerW ); for ( j = 0;j < v->pcm_current;j++ ) v->pcm[i][v->pcm_current-j-1] = work[j]; } } }
int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){ vorbis_info *vi=v->vi; codec_setup_info *ci=vi->codec_setup; if(vals<=0){ int order=32; int i; float *lpc=alloca(order*sizeof(*lpc)); /* if it wasn't done earlier (very short sample) */ if(!v->preextrapolate) _preextrapolate_helper(v); /* We're encoding the end of the stream. Just make sure we have [at least] a few full blocks of zeroes at the end. */ /* actually, we don't want zeroes; that could drop a large amplitude off a cliff, creating spread spectrum noise that will suck to encode. Extrapolate for the sake of cleanliness. */ vorbis_analysis_buffer(v,ci->blocksizes[1]*3); v->eofflag=v->pcm_current; v->pcm_current+=ci->blocksizes[1]*3; for(i=0;i<vi->channels;i++){ if(v->eofflag>order*2){ /* extrapolate with LPC to fill in */ long n; /* make a predictor filter */ n=v->eofflag; if(n>ci->blocksizes[1])n=ci->blocksizes[1]; vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order); /* run the predictor filter */ vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order, v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag); }else{ /* not enough data to extrapolate (unlikely to happen due to guarding the overlap, but bulletproof in case that assumtion goes away). zeroes will do. */ memset(v->pcm[i]+v->eofflag,0, (v->pcm_current-v->eofflag)*sizeof(*v->pcm[i])); } } }else{ if(v->pcm_current+vals>v->pcm_storage) return(OV_EINVAL); v->pcm_current+=vals; /* we may want to reverse extrapolate the beginning of a stream too... in case we're beginning on a cliff! */ /* clumsy, but simple. It only runs once, so simple is good. */ if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1]) _preextrapolate_helper(v); } return(0); }
void dumb_it_add_lpc(struct DUMB_IT_SIGDATA *sigdata){ float lpc[lpc_order * 2]; float lpc_input[lpc_max * 2]; float lpc_output[lpc_extra * 2]; signed char * s8; signed short * s16; int n, o, offset, lpc_samples; for ( n = 0; n < sigdata->n_samples; n++ ) { IT_SAMPLE * sample = sigdata->sample + n; if ( ( sample->flags & ( IT_SAMPLE_EXISTS | IT_SAMPLE_LOOP) ) == IT_SAMPLE_EXISTS ) { /* If we have enough sample data to train the filter, use the filter to generate the padding */ if ( sample->length >= lpc_order ) { lpc_samples = sample->length; if (lpc_samples > lpc_max) lpc_samples = lpc_max; offset = sample->length - lpc_samples; if ( sample->flags & IT_SAMPLE_STEREO ) { if ( sample->flags & IT_SAMPLE_16BIT ) { s16 = ( signed short * ) sample->data; s16 += offset * 2; for ( o = 0; o < lpc_samples; o++ ) { lpc_input[ o ] = s16[ o * 2 + 0 ]; lpc_input[ o + lpc_max ] = s16[ o * 2 + 1 ]; } } else { s8 = ( signed char * ) sample->data; s8 += offset * 2; for ( o = 0; o < lpc_samples; o++ ) { lpc_input[ o ] = s8[ o * 2 + 0 ]; lpc_input[ o + lpc_max ] = s8[ o * 2 + 1 ]; } } vorbis_lpc_from_data( lpc_input, lpc, lpc_samples, lpc_order ); vorbis_lpc_from_data( lpc_input + lpc_max, lpc + lpc_order, lpc_samples, lpc_order ); vorbis_lpc_predict( lpc, lpc_input + lpc_samples - lpc_order, lpc_order, lpc_output, lpc_extra ); vorbis_lpc_predict( lpc + lpc_order, lpc_input + lpc_max + lpc_samples - lpc_order, lpc_order, lpc_output + lpc_extra, lpc_extra ); if ( sample->flags & IT_SAMPLE_16BIT ) { s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 * sizeof(short) ); sample->data = s16; s16 += sample->length * 2; sample->length += lpc_extra; for ( o = 0; o < lpc_extra; o++ ) { s16[ o * 2 + 0 ] = (signed short)lpc_output[ o ]; s16[ o * 2 + 1 ] = (signed short)lpc_output[ o + lpc_extra ]; } } else { s8 = ( signed char * ) realloc( sample->data, ( sample->length + lpc_extra ) * 2 ); sample->data = s8; s8 += sample->length * 2; sample->length += lpc_extra; for ( o = 0; o < lpc_extra; o++ ) { s8[ o * 2 + 0 ] = (signed char)lpc_output[ o ]; s8[ o * 2 + 1 ] = (signed char)lpc_output[ o + lpc_extra ]; } } } else { if ( sample->flags & IT_SAMPLE_16BIT ) { s16 = ( signed short * ) sample->data; s16 += offset; for ( o = 0; o < lpc_samples; o++ ) { lpc_input[ o ] = s16[ o ]; } } else { s8 = ( signed char * ) sample->data; s8 += offset; for ( o = 0; o < lpc_samples; o++ ) { lpc_input[ o ] = s8[ o ]; } } vorbis_lpc_from_data( lpc_input, lpc, lpc_samples, lpc_order ); vorbis_lpc_predict( lpc, lpc_input + lpc_samples - lpc_order, lpc_order, lpc_output, lpc_extra ); if ( sample->flags & IT_SAMPLE_16BIT ) { s16 = ( signed short * ) realloc( sample->data, ( sample->length + lpc_extra ) * sizeof(short) ); sample->data = s16; s16 += sample->length; sample->length += lpc_extra; for ( o = 0; o < lpc_extra; o++ ) { s16[ o ] = (signed short)lpc_output[ o ]; } } else { s8 = ( signed char * ) realloc( sample->data, sample->length + lpc_extra ); sample->data = s8; s8 += sample->length; sample->length += lpc_extra; for ( o = 0; o < lpc_extra; o++ ) { s8[ o ] = (signed char)lpc_output[ o ]; } } } } else /* Otherwise, pad with silence. */ { offset = sample->length; lpc_samples = lpc_extra; sample->length += lpc_samples; n = 1; if ( sample->flags & IT_SAMPLE_STEREO ) n *= 2; if ( sample->flags & IT_SAMPLE_16BIT ) n *= 2; offset *= n; lpc_samples *= n; sample->data = realloc( sample->data, offset + lpc_samples ); memset( (char*)sample->data + offset, 0, lpc_samples ); } } } }