shithub: opus

Download patch

ref: 575d8d6fa450d5a37701afed0cc0a4e32818c6e6
parent: 91c9524af3b8235bf6798e0c10975983ba97e440
author: Jean-Marc Valin <jmvalin@jmvalin.ca>
date: Mon Nov 26 06:04:41 EST 2018

Adding sampling

--- a/dnn/lpcnet.c
+++ b/dnn/lpcnet.c
@@ -33,6 +33,9 @@
 
 #define NB_FEATURES 38
 
+#define PITCH_GAIN_FEATURE 37
+#define PDF_FLOOR 0.002
+
 #define FRAME_INPUT_SIZE (NB_FEATURES + EMBED_PITCH_OUT_SIZE)
 
 #define SAMPLE_INPUT_SIZE (2*EMBED_SIG_OUT_SIZE + EMBED_EXC_OUT_SIZE + FEATURE_DENSE2_OUT_SIZE)
@@ -79,11 +82,10 @@
     RNN_CLEAR(lpc, LPC_ORDER);
 }
 
-int run_sample_network(NNetState *net, const float *condition, int last_exc, int last_sig, int pred)
+void run_sample_network(NNetState *net, float *pdf, const float *condition, int last_exc, int last_sig, int pred)
 {
     float in_a[SAMPLE_INPUT_SIZE];
     float in_b[GRU_A_STATE_SIZE+FEATURE_DENSE2_OUT_SIZE];
-    float pdf[DUAL_FC_OUT_SIZE];
     compute_embedding(&embed_sig, &in_a[0], last_sig);
     compute_embedding(&embed_sig, &in_a[EMBED_SIG_OUT_SIZE], pred);
     compute_embedding(&embed_exc, &in_a[2*EMBED_SIG_OUT_SIZE], last_exc);
@@ -93,8 +95,6 @@
     RNN_COPY(&in_b[GRU_A_STATE_SIZE], condition, FEATURE_DENSE2_OUT_SIZE);
     compute_gru(&gru_b, net->gru_b_state, in_b);
     compute_mdense(&dual_fc, pdf, net->gru_b_state);
-    /* FIXME: Do the actual sampling here. */
-    return 0;
 }
 
 void generate_samples(LPCNetState *lpcnet, short *output, const float *features, int pitch, int N)
@@ -102,6 +102,7 @@
     int i;
     float condition[FEATURE_DENSE2_OUT_SIZE];
     float lpc[LPC_ORDER];
+    float pdf[DUAL_FC_OUT_SIZE];
     run_frame_network(&lpcnet->nnet, condition, lpc, features, pitch);
     for (i=0;i<N;i++)
     {
@@ -115,7 +116,8 @@
         pred = (int)floor(.5f + sum);
         last_sig_ulaw = lin2ulaw(lpcnet->last_sig[0]);
         pred_ulaw = lin2ulaw(pred);
-        exc = run_sample_network(&lpcnet->nnet, condition, lpcnet->last_exc, last_sig_ulaw, pred_ulaw);
+        run_sample_network(&lpcnet->nnet, pdf, condition, lpcnet->last_exc, last_sig_ulaw, pred_ulaw);
+        exc = sample_from_pdf(pdf, DUAL_FC_OUT_SIZE, MAX16(0, 1.5f*features[PITCH_GAIN_FEATURE] - .5f), PDF_FLOOR);
         output[i] = pred + ulaw2lin(exc);
         RNN_MOVE(&lpcnet->last_sig[1], &lpcnet->last_sig[0], LPC_ORDER-1);
         lpcnet->last_sig[0] = output[i];
--- a/dnn/nnet.c
+++ b/dnn/nnet.c
@@ -30,6 +30,7 @@
 #include "config.h"
 #endif
 
+#include <stdlib.h>
 #include <math.h>
 #include "opus_types.h"
 #include "arch.h"
@@ -236,3 +237,32 @@
    }    
 }
 
+int sample_from_pdf(const float *pdf, int N, float exp_boost, float pdf_floor)
+{
+    int i;
+    float sum, norm;
+    float r;
+    float tmp[DUAL_FC_OUT_SIZE];
+    celt_assert(N <= DUAL_FC_OUT_SIZE);
+    sum = 0;
+    /* Decrease the temperature of the sampling. */
+    for (i=0;i<N;i++)
+    {
+        tmp[i] = pow(pdf[i], 1.f+exp_boost);
+        sum += tmp[i];
+    }
+    norm = 1.f/sum;
+    /* Convert tmp to a CDF while subtracting the floor */
+    tmp[0] = MAX16(0, norm*tmp[0] - pdf_floor);
+    for (i=1;i<N;i++)
+    {
+        tmp[i] = tmp[i-1] + MAX16(0, norm*tmp[i] - pdf_floor);
+    }
+    /* Do the sampling (from the cdf). */
+    r = tmp[N-1] * ((float)rand()/RAND_MAX);
+    for (i=0;i<N-1;i++)
+    {
+        if (r > tmp[i]) return r;
+    }
+    return N-1;
+}
--- a/dnn/nnet.h
+++ b/dnn/nnet.h
@@ -89,5 +89,6 @@
 
 void compute_embedding(const EmbeddingLayer *layer, float *output, int input);
 
+int sample_from_pdf(const float *pdf, int N, float exp_boost, float pdf_floor);
 
 #endif /* _MLP_H_ */
--