Better rounding

This commit is contained in:
Jean-Marc Valin 2018-11-27 13:11:41 -05:00
parent 0ddfdfc7c0
commit 3c694db226
2 changed files with 18 additions and 15 deletions

View file

@ -49,7 +49,7 @@
struct LPCNetState { struct LPCNetState {
NNetState nnet; NNetState nnet;
int last_exc; int last_exc;
short last_sig[LPC_ORDER]; float last_sig[LPC_ORDER];
float old_input[FEATURES_DELAY][FEATURE_CONV2_OUT_SIZE]; float old_input[FEATURES_DELAY][FEATURE_CONV2_OUT_SIZE];
float old_lpc[FEATURES_DELAY][LPC_ORDER]; float old_lpc[FEATURES_DELAY][LPC_ORDER];
int frame_count; int frame_count;
@ -57,22 +57,22 @@ struct LPCNetState {
}; };
static int ulaw2lin(int u) static float ulaw2lin(float u)
{ {
float s; float s;
float scale_1 = 32768.f/255.f; float scale_1 = 32768.f/255.f;
u = u - 128; u = u - 128;
s = u >= 0 ? 1 : -1; s = u >= 0 ? 1 : -1;
u = abs(u); u = fabs(u);
return s*scale_1*(exp(u/128.*log(256))-1); return s*scale_1*(exp(u/128.*log(256))-1);
} }
static int lin2ulaw(int x) static int lin2ulaw(float x)
{ {
float u; float u;
float scale = 255.f/32768.f; float scale = 255.f/32768.f;
int s = x >= 0 ? 1 : -1; int s = x >= 0 ? 1 : -1;
x = abs(x); x = fabs(x);
u = (s*(128*log(1+scale*x)/log(256))); u = (s*(128*log(1+scale*x)/log(256)));
u = 128 + u; u = 128 + u;
if (u < 0) u = 0; if (u < 0) u = 0;
@ -148,6 +148,8 @@ void lpcnet_synthesize(LPCNetState *lpcnet, short *output, const float *features
float pdf[DUAL_FC_OUT_SIZE]; float pdf[DUAL_FC_OUT_SIZE];
int pitch; int pitch;
float pitch_gain; float pitch_gain;
/* FIXME: Remove this -- it's just a temporary hack to match the Python code. */
static int start = LPC_ORDER+1;
/* FIXME: Do proper rounding once the Python code rounds properly. */ /* FIXME: Do proper rounding once the Python code rounds properly. */
pitch = (int)floor(50*features[36]+100); pitch = (int)floor(50*features[36]+100);
/* FIXME: get the pitch gain from 2 frames in the past. */ /* FIXME: get the pitch gain from 2 frames in the past. */
@ -161,27 +163,28 @@ void lpcnet_synthesize(LPCNetState *lpcnet, short *output, const float *features
RNN_CLEAR(output, N); RNN_CLEAR(output, N);
return; return;
} }
for (i=0;i<N;i++) for (i=start;i<N;i++)
{ {
int j; int j;
int pred; float pcm;
int exc; int exc;
int last_sig_ulaw; int last_sig_ulaw;
int pred_ulaw; int pred_ulaw;
float sum = 0; float pred = 0;
for (j=0;j<LPC_ORDER;j++) sum -= lpcnet->last_sig[j]*lpc[j]; for (j=0;j<LPC_ORDER;j++) pred -= lpcnet->last_sig[j]*lpc[j];
pred = (int)floor(.5f + sum);
last_sig_ulaw = lin2ulaw(lpcnet->last_sig[0]); last_sig_ulaw = lin2ulaw(lpcnet->last_sig[0]);
pred_ulaw = lin2ulaw(pred); pred_ulaw = lin2ulaw(pred);
run_sample_network(&lpcnet->nnet, pdf, 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*pitch_gain - .5f), PDF_FLOOR); exc = sample_from_pdf(pdf, DUAL_FC_OUT_SIZE, MAX16(0, 1.5f*pitch_gain - .5f), PDF_FLOOR);
output[i] = pred + ulaw2lin(exc); pcm = pred + ulaw2lin(exc);
RNN_MOVE(&lpcnet->last_sig[1], &lpcnet->last_sig[0], LPC_ORDER-1); RNN_MOVE(&lpcnet->last_sig[1], &lpcnet->last_sig[0], LPC_ORDER-1);
lpcnet->last_sig[0] = output[i]; lpcnet->last_sig[0] = pcm;
lpcnet->last_exc = exc; lpcnet->last_exc = exc;
output[i] += PREEMPH*lpcnet->deemph_mem; pcm += PREEMPH*lpcnet->deemph_mem;
lpcnet->deemph_mem = output[i]; lpcnet->deemph_mem = pcm;
output[i] = (int)floor(.5 + pcm);
} }
start = 0;
} }
#if 1 #if 1

View file

@ -101,7 +101,7 @@ for c in range(0, nb_frames):
fexc[0, 0, 0] = lin2ulaw(pcm[f*frame_size + i]) fexc[0, 0, 0] = lin2ulaw(pcm[f*frame_size + i])
mem = coef*mem + pcm[f*frame_size + i] mem = coef*mem + pcm[f*frame_size + i]
#print(mem) #print(mem)
np.array([mem], dtype='int16').tofile(fout) np.array([np.round(mem)], dtype='int16').tofile(fout)
skip = 0 skip = 0