shithub: opus

Download patch

ref: e0d2b105a2f319f9d8817172d97c419849637ca7
parent: 1dcd57323f59ddd61c7d825471096b1cb884eb65
author: Jean-Marc Valin <jmvalin@jmvalin.ca>
date: Fri Dec 7 13:16:19 EST 2018

Compute LPC from features

--- a/dnn/common.h
+++ b/dnn/common.h
@@ -9,6 +9,8 @@
 #define RNN_INLINE inline
 #define OPUS_INLINE inline
 
+float lpc_from_cepstrum(float *lpc, const float *cepstrum);
+
 
 /** RNNoise wrapper for malloc(). To do your own dynamic allocation, all you need t
 o do is replace this function and rnnoise_free */
--- a/dnn/denoise.c
+++ b/dnn/denoise.c
@@ -222,6 +222,19 @@
   }
 }
 
+static void idct(float *out, const float *in) {
+  int i;
+  check_init();
+  for (i=0;i<NB_BANDS;i++) {
+    int j;
+    float sum = 0;
+    for (j=0;j<NB_BANDS;j++) {
+      sum += in[j] * common.dct_table[i*NB_BANDS + j];
+    }
+    out[i] = sum*sqrt(2.*22)*(1.f/NB_BANDS);
+  }
+}
+
 #if 0
 static void idct(float *out, const float *in) {
   int i;
@@ -311,6 +324,41 @@
   int i;
   i = (int)floor(.5+x);
   return IMAX(-32767, IMIN(32767, i));
+}
+
+static float lpc_from_bands(float *lpc, const float *Ex)
+{
+   int i;
+   float e;
+   float ac[LPC_ORDER+1];
+   float rc[LPC_ORDER];
+   float Xr[FREQ_SIZE];
+   kiss_fft_cpx X_auto[FREQ_SIZE];
+   float x_auto[FRAME_SIZE];
+   interp_band_gain(Xr, Ex);
+   RNN_CLEAR(X_auto, FREQ_SIZE);
+   for (i=0;i<160;i++) X_auto[i].r = Xr[i];
+   inverse_transform(x_auto, X_auto);
+   for (i=0;i<LPC_ORDER+1;i++) ac[i] = x_auto[i];
+
+   /* -40 dB noise floor. */
+   ac[0] += ac[0]*1e-4 + 320/12/38.;
+   /* Lag windowing. */
+   for (i=1;i<LPC_ORDER+1;i++) ac[i] *= (1 - 6e-5*i*i);
+   e = _celt_lpc(lpc, rc, ac, LPC_ORDER);
+   return e;
+}
+
+float lpc_from_cepstrum(float *lpc, const float *cepstrum)
+{
+   int i;
+   float Ex[NB_BANDS];
+   float tmp[NB_BANDS];
+   RNN_COPY(tmp, cepstrum, NB_BANDS);
+   tmp[0] += 4;
+   idct(Ex, tmp);
+   for (i=0;i<NB_BANDS;i++) Ex[i] = pow(10.f, Ex[i]);
+   return lpc_from_bands(lpc, Ex);
 }
 
 static float frame_analysis(DenoiseState *st, signed char *iexc, short *pred, short *pcm, float *lpc, kiss_fft_cpx *X, float *Ex, const float *in) {
--- a/dnn/lpcnet.c
+++ b/dnn/lpcnet.c
@@ -142,7 +142,7 @@
     free(lpcnet);
 }
 
-void lpcnet_synthesize(LPCNetState *lpcnet, short *output, const float *features, const float *new_lpc, int N)
+void lpcnet_synthesize(LPCNetState *lpcnet, short *output, const float *features, int N)
 {
     int i;
     float condition[FEATURE_DENSE2_OUT_SIZE];
@@ -160,7 +160,7 @@
     run_frame_network(lpcnet, condition, gru_a_condition, features, pitch);
     memcpy(lpc, lpcnet->old_lpc[FEATURES_DELAY-1], LPC_ORDER*sizeof(lpc[0]));
     memmove(lpcnet->old_lpc[1], lpcnet->old_lpc[0], (FEATURES_DELAY-1)*LPC_ORDER*sizeof(lpc[0]));
-    memcpy(lpcnet->old_lpc[0], new_lpc, LPC_ORDER*sizeof(lpc[0]));
+    lpc_from_cepstrum(lpcnet->old_lpc[0], features);
     if (lpcnet->frame_count <= FEATURES_DELAY)
     {
         RNN_CLEAR(output, N);
@@ -208,14 +208,12 @@
     while (1) {
         float in_features[NB_TOTAL_FEATURES];
         float features[NB_FEATURES];
-        float lpc[LPC_ORDER];
         short pcm[FRAME_SIZE];
         fread(in_features, sizeof(features[0]), NB_TOTAL_FEATURES, fin);
         RNN_COPY(features, in_features, NB_FEATURES);
         RNN_CLEAR(&features[18], 18);
-        RNN_COPY(lpc, &in_features[NB_TOTAL_FEATURES-LPC_ORDER], LPC_ORDER);
         if (feof(fin)) break;
-        lpcnet_synthesize(net, pcm, features, lpc, FRAME_SIZE);
+        lpcnet_synthesize(net, pcm, features, FRAME_SIZE);
         fwrite(pcm, sizeof(pcm[0]), FRAME_SIZE, fout);
     }
     fclose(fin);
--- a/dnn/lpcnet.h
+++ b/dnn/lpcnet.h
@@ -33,6 +33,6 @@
 
 void lpcnet_destroy(LPCNetState *lpcnet);
 
-void lpcnet_synthesize(LPCNetState *lpcnet, short *output, const float *features, const float *new_lpc, int N);
+void lpcnet_synthesize(LPCNetState *lpcnet, short *output, const float *features, int N);
 
 #endif
--