ref: 8b1dd1006ffe513bdc506d9b54c4f55f09c1a47c
parent: 25c9d378d527604f86819d1cc33e77b4f36f3ae5
author: Chris Moeller <[email protected]>
date: Wed Jul 4 15:06:31 EDT 2012
Implemented LPC in audio input padder.
--- a/Makefile.am
+++ b/Makefile.am
@@ -13,6 +13,7 @@
noinst_HEADERS = src/arch.h \
src/diag_range.h \
src/info_opus.h \
+ src/lpc.h \
src/opusenc.h \
src/opus_header.h \
src/opusinfo.h \
@@ -26,7 +27,7 @@
dist_man_MANS = man/opusenc.1 man/opusdec.1 man/opusinfo.1
-opusenc_SOURCES = src/opus_header.c src/opusenc.c src/resample.c src/audio-in.c src/diag_range.c
+opusenc_SOURCES = src/opus_header.c src/opusenc.c src/resample.c src/audio-in.c src/diag_range.c src/lpc.c
opusenc_LDADD = $(OGG_LIBS) $(Opus_LIBS) -lm
opusenc_MANS = man/opusenc.1
--- a/src/audio-in.c
+++ b/src/audio-in.c
@@ -67,6 +67,7 @@
#include <ogg/ogg.h>
#include "opusenc.h"
#include "speex_resampler.h"
+#include "lpc.h"
#ifdef HAVE_LIBFLAC
#include "flac.h"
@@ -822,7 +823,9 @@
void *real_readdata;
ogg_int64_t *original_samples;
int channels;
+ int lpc_ptr;
int *extra_samples;
+ float *lpc_out;
} padder;
static long read_padder(void *data, float *buffer, int samples) {
@@ -829,15 +832,29 @@
padder *d = data;
long in_samples = d->real_reader(d->real_readdata, buffer, samples);
int i, extra=0;
+ const int lpc_order=32;
if(d->original_samples)*d->original_samples+=in_samples;
if(in_samples<samples){
+ if(d->lpc_ptr<0){
+ d->lpc_out=calloc(d->channels * *d->extra_samples, sizeof(*d->lpc_out));
+ if(in_samples>lpc_order*2){
+ float *lpc=alloca(lpc_order*sizeof(*lpc));
+ for(i=0;i<d->channels;i++){
+ vorbis_lpc_from_data(buffer+i,lpc,in_samples,lpc_order,d->channels);
+ vorbis_lpc_predict(lpc,buffer+i+(in_samples-lpc_order)*d->channels,
+ lpc_order,d->lpc_out+i,*d->extra_samples,d->channels);
+ }
+ }
+ d->lpc_ptr=0;
+ }
extra=samples-in_samples;
if(extra>*d->extra_samples)extra=*d->extra_samples;
*d->extra_samples-=extra;
}
- for(i=0;i<extra*d->channels;i++)buffer[(in_samples*d->channels)+i]=0;
+ memcpy(buffer+in_samples*d->channels,d->lpc_out+d->lpc_ptr*d->channels,extra*d->channels*sizeof(*buffer));
+ d->lpc_ptr+=extra;
return in_samples+extra;
}
@@ -852,6 +869,8 @@
d->channels = opt->channels;
d->extra_samples = &opt->extraout;
d->original_samples=original_samples;
+ d->lpc_ptr = -1;
+ d->lpc_out = NULL;
}
void clear_padder(oe_enc_opt *opt) {
@@ -860,6 +879,7 @@
opt->read_samples = d->real_reader;
opt->readdata = d->real_readdata;
+ if(d->lpc_out)free(d->lpc_out);
free(d);
}
--- /dev/null
+++ b/src/lpc.c
@@ -1,0 +1,157 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
+ * by the Xiph.Org Foundation http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function: LPC low level routines
+ last mod: $Id: lpc.c 16227 2009-07-08 06:58:46Z xiphmont $
+
+ ********************************************************************/
+
+/* 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
+
+*********************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "stack_alloc.h"
+#include "lpc.h"
+
+/* Autocorrelation LPC coeff generation algorithm invented by
+ N. Levinson in 1947, modified by J. Durbin in 1959. */
+
+/* Input : n elements of time doamin data
+ Output: m lpc coefficients, excitation energy */
+
+float vorbis_lpc_from_data(float *data,float *lpci,int n,int m,int stride){
+ double *aut=alloca(sizeof(*aut)*(m+1));
+ double *lpc=alloca(sizeof(*lpc)*(m));
+ double error;
+ double epsilon;
+ int i,j;
+
+ /* autocorrelation, p+1 lag coefficients */
+ j=m+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;
+ }
+
+ /* Generate lpc coefficients from autocorr values */
+
+ /* set our noise floor to about -100dB */
+ error=aut[0] * (1. + 1e-10);
+ epsilon=1e-9*aut[0]+1e-10;
+
+ for(i=0;i<m;i++){
+ double r= -aut[i+1];
+
+ if(error<epsilon){
+ memset(lpc+i,0,(m-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<m;j++){
+ lpc[j]*=damp;
+ damp*=g;
+ }
+ }
+
+ for(j=0;j<m;j++)lpci[j]=(float)lpc[j];
+
+ /* we need the error value to know how big an impulse to hit the
+ filter with later */
+
+ return error;
+}
+
+void vorbis_lpc_predict(float *coeff,float *prime,int m,
+ float *data,long n,int stride){
+
+ /* in: coeff[0...m-1] LPC coefficients
+ prime[0...m-1] initial values (allocated size of n+m-1)
+ out: data[0...n-1] data samples */
+
+ long i,j,o,p;
+ float y;
+ float *work=alloca(sizeof(*work)*(m+n));
+
+ if(!prime)
+ for(i=0;i<m;i++)
+ work[i]=0.f;
+ else
+ for(i=0;i<m;i++)
+ work[i]=prime[i*stride];
+
+ for(i=0;i<n;i++){
+ y=0;
+ o=i;
+ p=m;
+ for(j=0;j<m;j++)
+ y-=work[o++]*coeff[--p];
+
+ data[i*stride]=work[o]=y;
+ }
+}
--- /dev/null
+++ b/src/lpc.h
@@ -1,0 +1,27 @@
+/********************************************************************
+ * *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
+ * *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
+ * by the Xiph.Org Foundation http://www.xiph.org/ *
+ * *
+ ********************************************************************
+
+ function: LPC low level routines
+ last mod: $Id: lpc.h 16037 2009-05-26 21:10:58Z xiphmont $
+
+ ********************************************************************/
+
+#ifndef _V_LPC_H_
+#define _V_LPC_H_
+
+/* simple linear scale LPC code */
+extern float vorbis_lpc_from_data(float *data,float *lpc,int n,int m,int stride);
+
+extern void vorbis_lpc_predict(float *coeff,float *prime,int m,
+ float *data,long n,int stride);
+
+#endif