From 54b057c9cd23f935338ca413d55b4d54b61bbbf8 Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin Date: Mon, 18 Mar 2019 14:13:07 -0400 Subject: [PATCH] Add LPCNet decoder object --- dnn/Makefile | 4 +-- dnn/common.c | 65 ++++++++++++++++++++++++++++++++++++++++++++ dnn/lpcnet.c | 55 ++++++++++++++++++++++++++++++++++--- dnn/lpcnet.h | 19 +++++++++++++ dnn/lpcnet_dec.c | 4 +-- dnn/lpcnet_enc.c | 29 -------------------- dnn/lpcnet_private.h | 7 +++-- 7 files changed, 144 insertions(+), 39 deletions(-) create mode 100644 dnn/common.c diff --git a/dnn/Makefile b/dnn/Makefile index e29c7e25..32f9aca3 100644 --- a/dnn/Makefile +++ b/dnn/Makefile @@ -22,14 +22,14 @@ endif all: dump_data test_lpcnet test_vec -dump_data_objs := src/dump_data.o src/freq.o src/kiss_fft.o src/pitch.o src/celt_lpc.o src/lpcnet_dec.o src/lpcnet_enc.o src/ceps_codebooks.o +dump_data_objs := src/common.o src/dump_data.o src/freq.o src/kiss_fft.o src/pitch.o src/celt_lpc.o src/lpcnet_dec.o src/lpcnet_enc.o src/ceps_codebooks.o dump_data_deps := $(dump_data_objs:.o=.d) dump_data: $(dump_data_objs) gcc -o $@ $(CFLAGS) $(dump_data_objs) -lm -include $dump_data_deps(_deps) -test_lpcnet_objs := src/test_lpcnet.o src/lpcnet.o src/nnet.o src/nnet_data.o src/freq.o src/kiss_fft.o src/pitch.o src/celt_lpc.o +test_lpcnet_objs := src/common.o src/test_lpcnet.o src/lpcnet.o src/nnet.o src/nnet_data.o src/freq.o src/kiss_fft.o src/pitch.o src/celt_lpc.o src/lpcnet_dec.o src/ceps_codebooks.o test_lpcnet_deps := $(test_lpcnet_objs:.o=.d) test_lpcnet: $(test_lpcnet_objs) gcc -o $@ $(CFLAGS) $(test_lpcnet_objs) -lm diff --git a/dnn/common.c b/dnn/common.c new file mode 100644 index 00000000..d5a4580a --- /dev/null +++ b/dnn/common.c @@ -0,0 +1,65 @@ + +/* Copyright (c) 2017-2019 Mozilla */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "freq.h" +#include "lpcnet_private.h" + + +static void single_interp(float *x, const float *left, const float *right, int id) +{ + int i; + float ref[NB_BANDS]; + float pred[3*NB_BANDS]; + RNN_COPY(ref, x, NB_BANDS); + for (i=0;i= FORBIDDEN_INTERP); + id0 = best_id / 3; + id1 = best_id % 3; + single_interp(features[0], mem, features[1], id0); + single_interp(features[2], features[1], features[3], id1); +} diff --git a/dnn/lpcnet.c b/dnn/lpcnet.c index da3fad0f..34928525 100644 --- a/dnn/lpcnet.c +++ b/dnn/lpcnet.c @@ -89,11 +89,24 @@ void run_sample_network(NNetState *net, float *pdf, const float *condition, cons compute_mdense(&dual_fc, pdf, net->gru_b_state); } +int lpcnet_get_size() +{ + return sizeof(LPCNetState); +} + +int lpcnet_init(LPCNetState *lpcnet) +{ + memset(lpcnet, 0, lpcnet_get_size()); + lpcnet->last_exc = 128; + return 0; +} + + LPCNetState *lpcnet_create() { LPCNetState *lpcnet; - lpcnet = (LPCNetState *)calloc(sizeof(LPCNetState), 1); - lpcnet->last_exc = 128; + lpcnet = (LPCNetState *)calloc(lpcnet_get_size(), 1); + lpcnet_init(lpcnet); return lpcnet; } @@ -153,6 +166,40 @@ void lpcnet_synthesize(LPCNetState *lpcnet, short *output, const float *features start = 0; } -#if 1 -#endif +int lpcnet_decoder_get_size() +{ + return sizeof(LPCNetDecState); +} + +int lpcnet_decoder_init(LPCNetDecState *st) +{ + memset(st, 0, lpcnet_decoder_get_size()); + lpcnet_init(&st->lpcnet_state); + return 0; +} + +LPCNetDecState *lpcnet_decoder_create() +{ + LPCNetDecState *st; + st = malloc(lpcnet_decoder_get_size()); + lpcnet_decoder_init(st); + return st; +} + +void lpcnet_decoder_destroy(LPCNetDecState *st) +{ + free(st); +} + +int lpcnet_decode(LPCNetDecState *st, const unsigned char *buf, short *pcm) +{ + int k; + float features[4][NB_TOTAL_FEATURES]; + decode_packet(features, st->vq_mem, buf); + for (k=0;k<4;k++) { + lpcnet_synthesize(&st->lpcnet_state, &pcm[k*FRAME_SIZE], features[k], FRAME_SIZE); + } + return 0; +} + diff --git a/dnn/lpcnet.h b/dnn/lpcnet.h index fad60dfc..afeae5bb 100644 --- a/dnn/lpcnet.h +++ b/dnn/lpcnet.h @@ -32,8 +32,23 @@ typedef struct LPCNetState LPCNetState; +typedef struct LPCNetDecState LPCNetDecState; + typedef struct LPCNetEncState LPCNetEncState; + +int lpcnet_decoder_get_size(); + +int lpcnet_decoder_init(LPCNetDecState *st); + +LPCNetDecState *lpcnet_decoder_create(); + +void lpcnet_decoder_destroy(LPCNetDecState *st); + +int lpcnet_decode(LPCNetDecState *st, const unsigned char *buf, short *pcm); + + + int lpcnet_encoder_get_size(); int lpcnet_encoder_init(LPCNetEncState *st); @@ -46,6 +61,10 @@ int lpcnet_encode(LPCNetEncState *st, const short *pcm, unsigned char *buf); +int lpcnet_get_size(); + +int lpcnet_init(LPCNetState *lpcnet); + LPCNetState *lpcnet_create(); void lpcnet_destroy(LPCNetState *lpcnet); diff --git a/dnn/lpcnet_dec.c b/dnn/lpcnet_dec.c index 2eeb4c49..d76b9446 100644 --- a/dnn/lpcnet_dec.c +++ b/dnn/lpcnet_dec.c @@ -50,7 +50,7 @@ typedef struct { const unsigned char *chars; } unpacker; -void bits_unpacker_init(unpacker *bits, unsigned char *buf, int size) { +void bits_unpacker_init(unpacker *bits, const unsigned char *buf, int size) { bits->byte_pos = 0; bits->bit_pos = 0; bits->max_bytes = size; @@ -78,7 +78,7 @@ unsigned int bits_unpack(unpacker *bits, int nb_bits) { return d; } -void decode_packet(float features[4][NB_TOTAL_FEATURES], float *vq_mem, unsigned char buf[8]) +void decode_packet(float features[4][NB_TOTAL_FEATURES], float *vq_mem, const unsigned char buf[8]) { int c0_id; int main_pitch; diff --git a/dnn/lpcnet_enc.c b/dnn/lpcnet_enc.c index 5648cab8..17852e89 100644 --- a/dnn/lpcnet_enc.c +++ b/dnn/lpcnet_enc.c @@ -398,35 +398,6 @@ int double_interp_search(const float features[4][NB_TOTAL_FEATURES], const float return best_id - (best_id >= FORBIDDEN_INTERP); } -static void single_interp(float *x, const float *left, const float *right, int id) -{ - int i; - float ref[NB_BANDS]; - float pred[3*NB_BANDS]; - RNN_COPY(ref, x, NB_BANDS); - for (i=0;i= FORBIDDEN_INTERP); - id0 = best_id / 3; - id1 = best_id % 3; - single_interp(features[0], mem, features[1], id0); - single_interp(features[2], features[1], features[3], id1); -} void perform_interp_relaxation(float features[4][NB_TOTAL_FEATURES], const float *mem) { int id0, id1; diff --git a/dnn/lpcnet_private.h b/dnn/lpcnet_private.h index 866cbeb2..090b2c21 100644 --- a/dnn/lpcnet_private.h +++ b/dnn/lpcnet_private.h @@ -33,7 +33,10 @@ struct LPCNetState { float deemph_mem; }; - +struct LPCNetDecState { + LPCNetState lpcnet_state; + float vq_mem[NB_BANDS]; +}; struct LPCNetEncState{ float analysis_mem[OVERLAP_SIZE]; @@ -70,6 +73,6 @@ void process_superframe(LPCNetEncState *st, unsigned char *buf, FILE *ffeat, int void compute_frame_features(LPCNetEncState *st, const float *in); -void decode_packet(float features[4][NB_TOTAL_FEATURES], float *vq_mem, unsigned char buf[8]); +void decode_packet(float features[4][NB_TOTAL_FEATURES], float *vq_mem, const unsigned char buf[8]); #endif