diff --git a/dnn/dump_lpcnet.py b/dnn/dump_lpcnet.py index 2bc4dd19..c52b8836 100755 --- a/dnn/dump_lpcnet.py +++ b/dnn/dump_lpcnet.py @@ -187,10 +187,10 @@ hf.write('#define MAX_CONV_INPUTS {}\n\n'.format(max_conv_inputs)) hf.write('#define MAX_MDENSE_TMP {}\n\n'.format(max_mdense_tmp)) -hf.write('struct RNNState {\n') +hf.write('typedef struct {\n') for i, name in enumerate(layer_list): hf.write(' float {}_state[{}_STATE_SIZE];\n'.format(name, name.upper())) -hf.write('};\n') +hf.write('} LPCNetState;\n') hf.write('\n\n#endif\n') diff --git a/dnn/lpcnet.c b/dnn/lpcnet.c new file mode 100644 index 00000000..ee1ca0ab --- /dev/null +++ b/dnn/lpcnet.c @@ -0,0 +1,52 @@ +/* Copyright (c) 2018 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. +*/ + +#include "nnet_data.h" +#include "nnet.h" +#include "common.h" +#include "arch.h" + +#define NB_FEATURES 38 + +#define FRAME_INPUT_SIZE (NB_FEATURES + EMBED_PITCH_OUT_SIZE) + +void run_frame_network(LPCNetState *net, float *out, const float *features, int pitch) +{ + int i; + float in[FRAME_INPUT_SIZE]; + float conv1_out[FEATURE_CONV1_OUT_SIZE]; + float conv2_out[FEATURE_CONV2_OUT_SIZE]; + float dense1_out[FEATURE_DENSE1_OUT_SIZE]; + RNN_COPY(in, features, NB_FEATURES); + compute_embedding(&embed_pitch, &in[NB_FEATURES], pitch); + compute_conv1d(&feature_conv1, conv1_out, net->feature_conv1_state, in); + compute_conv1d(&feature_conv2, conv2_out, net->feature_conv2_state, conv1_out); + celt_assert(FRAME_INPUT_SIZE == FEATURE_CONV2_OUT_SIZE); + for (i=0;inb_inputs; N = layer->nb_neurons; stride = N; + celt_assert(input != output); for (i=0;ibias[i]; gemm_accum(output, layer->input_weights, N, M, stride, input); @@ -134,6 +135,7 @@ void compute_mdense(const MDenseLayer *layer, float *output, const float *input) int N, M, C; int stride; float tmp[MAX_MDENSE_TMP]; + celt_assert(input != output); M = layer->nb_inputs; N = layer->nb_neurons; C = layer->nb_channels; @@ -163,6 +165,7 @@ void compute_gru(const GRULayer *gru, float *state, const float *input) float r[MAX_RNN_NEURONS]; float h[MAX_RNN_NEURONS]; celt_assert(gru->nb_neurons <= MAX_RNN_NEURONS); + celt_assert(input != state); M = gru->nb_inputs; N = gru->nb_neurons; stride = 3*N; @@ -210,6 +213,7 @@ void compute_conv1d(const Conv1DLayer *layer, float *output, float *mem, const f int N, M; int stride; float tmp[MAX_CONV_INPUTS]; + celt_assert(input != output); celt_assert(layer->nb_inputs*layer->kernel_size <= MAX_CONV_INPUTS); RNN_COPY(tmp, mem, layer->nb_inputs*(layer->kernel_size-1)); RNN_COPY(tmp, input, layer->nb_inputs);