Unverified Commit 1bee6b93 authored by Jean-Marc Valin's avatar Jean-Marc Valin
Browse files

Adding some LPC extension code

parent 68896ecf
......@@ -48,6 +48,8 @@
#define MAX_CHANNELS 8
#define LPC_PADDING 120
#define LPC_ORDER 24
#define LPC_INPUT 480
/* Allow up to 2 seconds for delayed decision. */
#define MAX_LOOKAHEAD 96000
......@@ -610,6 +612,8 @@ OPE_EXPORT int ope_get_page(OggOpusEnc *enc, unsigned char **page, int *len, int
}
}
static void extend_signal(float *x, int before, int after, int channels);
int ope_drain(OggOpusEnc *enc) {
if (enc->unrecoverable) return OPE_UNRECOVERABLE;
/* Check if it's already been drained. */
......@@ -620,6 +624,7 @@ int ope_drain(OggOpusEnc *enc) {
shift_buffer(enc);
/* FIXME: Do LPC extension instead. */
memset(&enc->buffer[enc->channels*enc->buffer_end], 0, pad_samples*enc->channels);
extend_signal(&enc->buffer[enc->channels*enc->buffer_end], enc->buffer_end, LPC_PADDING, enc->channels);
enc->decision_delay = 0;
enc->buffer_end += pad_samples;
assert(enc->buffer_end <= BUFFER_SAMPLES);
......@@ -855,3 +860,127 @@ int ope_encoder_ctl(OggOpusEnc *enc, int request, ...) {
assert(ret == 0 || ret < -10);
return ret;
}
static void vorbis_lpc_from_data(float *data, float *lpci, int n, int stride);
static void extend_signal(float *x, int before, int after, int channels) {
int c;
before = MIN(before, LPC_INPUT);
if (before < 4*LPC_ORDER) {
int i;
for (i=0;i<after*channels;i++) x[i] = 0;
return;
}
for (c=0;c<channels;c++) {
int i;
float lpc[LPC_ORDER];
vorbis_lpc_from_data(x-channels*before, lpc, before, channels);
for (i=0;i<after;i++) {
float sum;
int j;
sum = 0;
for (j=0;j<LPC_ORDER;j++) sum -= x[i-j-1]*lpc[j];
x[i] = sum;
}
}
}
/* Some of these routines (autocorrelator, LPC coefficient estimator)
are derived from code written by Jutta Degener and Carsten Bormann;
thus we include their copyright below. The entirety of this file
is freely redistributable on the condition that both of these
copyright notices are preserved without modification. */
/* Preserved Copyright: *********************************************/
/* Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
Technische Universita"t Berlin
Any use of this software is permitted provided that this notice is not
removed and that neither the authors nor the Technische Universita"t
Berlin are deemed to have made any representations as to the
suitability of this software for any purpose nor are held responsible
for any defects of this software. THERE IS ABSOLUTELY NO WARRANTY FOR
THIS SOFTWARE.
As a matter of courtesy, the authors request to be informed about uses
this software has found, about bugs in this software, and about any
improvements that may be of general interest.
Berlin, 28.11.1994
Jutta Degener
Carsten Bormann
*********************************************************************/
static void vorbis_lpc_from_data(float *data, float *lpci, int n, int stride) {
double aut[LPC_ORDER+1];
double lpc[LPC_ORDER];
double error;
double epsilon;
int i,j;
/* FIXME: Apply a window to the input. */
/* autocorrelation, p+1 lag coefficients */
j=LPC_ORDER+1;
while(j--){
double d=0; /* double needed for accumulator depth */
for(i=j;i<n;i++)d+=(double)data[i*stride]*data[(i-j)*stride];
aut[j]=d;
}
/* FIXME: Apply lag windowing (better than bandwidth expansion) */
/* Generate lpc coefficients from autocorr values */
/* FIXME: This noise floor is insane! */
/* set our noise floor to about -100dB */
error=aut[0] * (1. + 1e-10);
epsilon=1e-9*aut[0]+1e-10;
for(i=0;i<LPC_ORDER;i++){
double r= -aut[i+1];
if(error<epsilon){
memset(lpc+i,0,(LPC_ORDER-i)*sizeof(*lpc));
goto done;
}
/* Sum up this iteration's reflection coefficient; note that in
Vorbis we don't save it. If anyone wants to recycle this code
and needs reflection coefficients, save the results of 'r' from
each iteration. */
for(j=0;j<i;j++)r-=lpc[j]*aut[i-j];
r/=error;
/* Update LPC coefficients and total error */
lpc[i]=r;
for(j=0;j<i/2;j++){
double tmp=lpc[j];
lpc[j]+=r*lpc[i-1-j];
lpc[i-1-j]+=r*tmp;
}
if(i&1)lpc[j]+=lpc[j]*r;
error*=1.-r*r;
}
done:
/* slightly damp the filter */
{
double g = .99;
double damp = g;
for(j=0;j<LPC_ORDER;j++){
lpc[j]*=damp;
damp*=g;
}
}
for(j=0;j<LPC_ORDER;j++)lpci[j]=(float)lpc[j];
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment