From 4f0af9b2ba169a93ff88cb6ff2ceef4260aeccee Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Wed, 19 Jan 2022 11:20:27 +0900 Subject: [PATCH 1/2] Add `rnnoise_model_from_string` function --- include/rnnoise.h | 7 ++++ src/rnn_reader.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/include/rnnoise.h b/include/rnnoise.h index 953fe6f6..ef81283d 100644 --- a/include/rnnoise.h +++ b/include/rnnoise.h @@ -102,6 +102,13 @@ RNNOISE_EXPORT float rnnoise_process_frame(DenoiseState* st, */ RNNOISE_EXPORT RNNModel* rnnoise_model_from_file(FILE* f); + /** + * Load a model from a string + * + * It must be deallocated with rnnoise_model_free() + */ +RNNOISE_EXPORT RNNModel* rnnoise_model_from_string(const char* s); + /** * Free a custom model * diff --git a/src/rnn_reader.c b/src/rnn_reader.c index 2dbbc366..7ac614b1 100644 --- a/src/rnn_reader.c +++ b/src/rnn_reader.c @@ -142,6 +142,110 @@ RNNModel* rnnoise_model_from_file(FILE* f) { return ret; } +RNNModel* rnnoise_model_from_string(const char* s) { + int i, in; + int n; + + if (sscanf(s, "rnnoise-nu model file version %d\n%n", &in, &n) != 1 || in != 1) + return NULL; + s += n; + + RNNModel* ret = calloc(1, sizeof(RNNModel)); + if (!ret) + return NULL; + +#define ALLOC_LAYER(type, name) \ + type* name; \ + name = calloc(1, sizeof(type)); \ + if (!name) { \ + rnnoise_model_free(ret); \ + return NULL; \ + } \ + ret->name = name + + ALLOC_LAYER(DenseLayer, input_dense); + ALLOC_LAYER(GRULayer, vad_gru); + ALLOC_LAYER(GRULayer, noise_gru); + ALLOC_LAYER(GRULayer, denoise_gru); + ALLOC_LAYER(DenseLayer, denoise_output); + ALLOC_LAYER(DenseLayer, vad_output); + +#define INPUT_VAL(name) \ + do { \ + if (sscanf(s, "%d%n", &in, &n) != 1 || in < 0 || in > 128) { \ + rnnoise_model_free(ret); \ + return NULL; \ + } \ + s += n; \ + name = in; \ + } while (0) + +#define INPUT_ACTIVATION(name) \ + do { \ + int activation; \ + INPUT_VAL(activation); \ + switch (activation) { \ + case F_ACTIVATION_SIGMOID: \ + name = ACTIVATION_SIGMOID; \ + break; \ + case F_ACTIVATION_RELU: \ + name = ACTIVATION_RELU; \ + break; \ + default: \ + name = ACTIVATION_TANH; \ + } \ + } while (0) + +#define INPUT_ARRAY(name, len) \ + do { \ + rnn_weight* values = malloc((len) * sizeof(rnn_weight)); \ + if (!values) { \ + rnnoise_model_free(ret); \ + return NULL; \ + } \ + name = values; \ + for (i = 0; i < (len); i++) { \ + if (sscanf(s, "%d%n", &in, &n) != 1) { \ + rnnoise_model_free(ret); \ + return NULL; \ + } \ + s += n; \ + values[i] = in; \ + } \ + } while (0) + +#define INPUT_DENSE(name) \ + do { \ + INPUT_VAL(name->nb_inputs); \ + INPUT_VAL(name->nb_neurons); \ + ret->name##_size = name->nb_neurons; \ + INPUT_ACTIVATION(name->activation); \ + INPUT_ARRAY(name->input_weights, name->nb_inputs * name->nb_neurons); \ + INPUT_ARRAY(name->bias, name->nb_neurons); \ + } while (0) + +#define INPUT_GRU(name) \ + do { \ + INPUT_VAL(name->nb_inputs); \ + INPUT_VAL(name->nb_neurons); \ + ret->name##_size = name->nb_neurons; \ + INPUT_ACTIVATION(name->activation); \ + INPUT_ARRAY(name->input_weights, name->nb_inputs * name->nb_neurons * 3); \ + INPUT_ARRAY(name->recurrent_weights, \ + name->nb_neurons * name->nb_neurons * 3); \ + INPUT_ARRAY(name->bias, name->nb_neurons * 3); \ + } while (0) + + INPUT_DENSE(input_dense); + INPUT_GRU(vad_gru); + INPUT_GRU(noise_gru); + INPUT_GRU(denoise_gru); + INPUT_DENSE(denoise_output); + INPUT_DENSE(vad_output); + + return ret; +} + void rnnoise_model_free(RNNModel* model) { #define FREE_MAYBE(ptr) \ do { \ From e71093d30018007e5c05147091ab9bf46b0f01ba Mon Sep 17 00:00:00 2001 From: Takeru Ohta Date: Thu, 20 Jan 2022 10:14:36 +0900 Subject: [PATCH 2/2] Add `#undef` to fix compiler warnings --- src/rnn_reader.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/rnn_reader.c b/src/rnn_reader.c index 7ac614b1..f01149ce 100644 --- a/src/rnn_reader.c +++ b/src/rnn_reader.c @@ -154,6 +154,7 @@ RNNModel* rnnoise_model_from_string(const char* s) { if (!ret) return NULL; +#undef ALLOC_LAYER #define ALLOC_LAYER(type, name) \ type* name; \ name = calloc(1, sizeof(type)); \ @@ -170,6 +171,7 @@ RNNModel* rnnoise_model_from_string(const char* s) { ALLOC_LAYER(DenseLayer, denoise_output); ALLOC_LAYER(DenseLayer, vad_output); +#undef INPUT_VAL #define INPUT_VAL(name) \ do { \ if (sscanf(s, "%d%n", &in, &n) != 1 || in < 0 || in > 128) { \ @@ -180,6 +182,7 @@ RNNModel* rnnoise_model_from_string(const char* s) { name = in; \ } while (0) +#undef INPUT_ACTIVATION #define INPUT_ACTIVATION(name) \ do { \ int activation; \ @@ -196,6 +199,7 @@ RNNModel* rnnoise_model_from_string(const char* s) { } \ } while (0) +#undef INPUT_ARRAY #define INPUT_ARRAY(name, len) \ do { \ rnn_weight* values = malloc((len) * sizeof(rnn_weight)); \ @@ -214,6 +218,7 @@ RNNModel* rnnoise_model_from_string(const char* s) { } \ } while (0) +#undef INPUT_DENSE #define INPUT_DENSE(name) \ do { \ INPUT_VAL(name->nb_inputs); \ @@ -224,6 +229,7 @@ RNNModel* rnnoise_model_from_string(const char* s) { INPUT_ARRAY(name->bias, name->nb_neurons); \ } while (0) +#undef INPUT_GRU #define INPUT_GRU(name) \ do { \ INPUT_VAL(name->nb_inputs); \