1*1295d682SXin Li /* Copyright (c) 2018 Gregor Richards */
2*1295d682SXin Li /*
3*1295d682SXin Li Redistribution and use in source and binary forms, with or without
4*1295d682SXin Li modification, are permitted provided that the following conditions
5*1295d682SXin Li are met:
6*1295d682SXin Li
7*1295d682SXin Li - Redistributions of source code must retain the above copyright
8*1295d682SXin Li notice, this list of conditions and the following disclaimer.
9*1295d682SXin Li
10*1295d682SXin Li - Redistributions in binary form must reproduce the above copyright
11*1295d682SXin Li notice, this list of conditions and the following disclaimer in the
12*1295d682SXin Li documentation and/or other materials provided with the distribution.
13*1295d682SXin Li
14*1295d682SXin Li THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15*1295d682SXin Li ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16*1295d682SXin Li LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17*1295d682SXin Li A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
18*1295d682SXin Li CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19*1295d682SXin Li EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20*1295d682SXin Li PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21*1295d682SXin Li PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22*1295d682SXin Li LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23*1295d682SXin Li NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24*1295d682SXin Li SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*1295d682SXin Li */
26*1295d682SXin Li
27*1295d682SXin Li #ifdef HAVE_CONFIG_H
28*1295d682SXin Li #include "config.h"
29*1295d682SXin Li #endif
30*1295d682SXin Li
31*1295d682SXin Li #include <stdio.h>
32*1295d682SXin Li #include <stdlib.h>
33*1295d682SXin Li #include <sys/types.h>
34*1295d682SXin Li
35*1295d682SXin Li #include "rnn.h"
36*1295d682SXin Li #include "rnn_data.h"
37*1295d682SXin Li #include "rnnoise.h"
38*1295d682SXin Li
39*1295d682SXin Li /* Although these values are the same as in rnn.h, we make them separate to
40*1295d682SXin Li * avoid accidentally burning internal values into a file format */
41*1295d682SXin Li #define F_ACTIVATION_TANH 0
42*1295d682SXin Li #define F_ACTIVATION_SIGMOID 1
43*1295d682SXin Li #define F_ACTIVATION_RELU 2
44*1295d682SXin Li
rnnoise_model_from_file(FILE * f)45*1295d682SXin Li RNNModel *rnnoise_model_from_file(FILE *f)
46*1295d682SXin Li {
47*1295d682SXin Li int i, in;
48*1295d682SXin Li
49*1295d682SXin Li if (fscanf(f, "rnnoise-nu model file version %d\n", &in) != 1 || in != 1)
50*1295d682SXin Li return NULL;
51*1295d682SXin Li
52*1295d682SXin Li RNNModel *ret = calloc(1, sizeof(RNNModel));
53*1295d682SXin Li if (!ret)
54*1295d682SXin Li return NULL;
55*1295d682SXin Li
56*1295d682SXin Li #define ALLOC_LAYER(type, name) \
57*1295d682SXin Li type *name; \
58*1295d682SXin Li name = calloc(1, sizeof(type)); \
59*1295d682SXin Li if (!name) { \
60*1295d682SXin Li rnnoise_model_free(ret); \
61*1295d682SXin Li return NULL; \
62*1295d682SXin Li } \
63*1295d682SXin Li ret->name = name
64*1295d682SXin Li
65*1295d682SXin Li ALLOC_LAYER(DenseLayer, input_dense);
66*1295d682SXin Li ALLOC_LAYER(GRULayer, vad_gru);
67*1295d682SXin Li ALLOC_LAYER(GRULayer, noise_gru);
68*1295d682SXin Li ALLOC_LAYER(GRULayer, denoise_gru);
69*1295d682SXin Li ALLOC_LAYER(DenseLayer, denoise_output);
70*1295d682SXin Li ALLOC_LAYER(DenseLayer, vad_output);
71*1295d682SXin Li
72*1295d682SXin Li #define INPUT_VAL(name) do { \
73*1295d682SXin Li if (fscanf(f, "%d", &in) != 1 || in < 0 || in > 128) { \
74*1295d682SXin Li rnnoise_model_free(ret); \
75*1295d682SXin Li return NULL; \
76*1295d682SXin Li } \
77*1295d682SXin Li name = in; \
78*1295d682SXin Li } while (0)
79*1295d682SXin Li
80*1295d682SXin Li #define INPUT_ACTIVATION(name) do { \
81*1295d682SXin Li int activation; \
82*1295d682SXin Li INPUT_VAL(activation); \
83*1295d682SXin Li switch (activation) { \
84*1295d682SXin Li case F_ACTIVATION_SIGMOID: \
85*1295d682SXin Li name = ACTIVATION_SIGMOID; \
86*1295d682SXin Li break; \
87*1295d682SXin Li case F_ACTIVATION_RELU: \
88*1295d682SXin Li name = ACTIVATION_RELU; \
89*1295d682SXin Li break; \
90*1295d682SXin Li default: \
91*1295d682SXin Li name = ACTIVATION_TANH; \
92*1295d682SXin Li } \
93*1295d682SXin Li } while (0)
94*1295d682SXin Li
95*1295d682SXin Li #define INPUT_ARRAY(name, len) do { \
96*1295d682SXin Li rnn_weight *values = malloc((len) * sizeof(rnn_weight)); \
97*1295d682SXin Li if (!values) { \
98*1295d682SXin Li rnnoise_model_free(ret); \
99*1295d682SXin Li return NULL; \
100*1295d682SXin Li } \
101*1295d682SXin Li name = values; \
102*1295d682SXin Li for (i = 0; i < (len); i++) { \
103*1295d682SXin Li if (fscanf(f, "%d", &in) != 1) { \
104*1295d682SXin Li rnnoise_model_free(ret); \
105*1295d682SXin Li return NULL; \
106*1295d682SXin Li } \
107*1295d682SXin Li values[i] = in; \
108*1295d682SXin Li } \
109*1295d682SXin Li } while (0)
110*1295d682SXin Li
111*1295d682SXin Li #define INPUT_DENSE(name) do { \
112*1295d682SXin Li INPUT_VAL(name->nb_inputs); \
113*1295d682SXin Li INPUT_VAL(name->nb_neurons); \
114*1295d682SXin Li ret->name ## _size = name->nb_neurons; \
115*1295d682SXin Li INPUT_ACTIVATION(name->activation); \
116*1295d682SXin Li INPUT_ARRAY(name->input_weights, name->nb_inputs * name->nb_neurons); \
117*1295d682SXin Li INPUT_ARRAY(name->bias, name->nb_neurons); \
118*1295d682SXin Li } while (0)
119*1295d682SXin Li
120*1295d682SXin Li #define INPUT_GRU(name) do { \
121*1295d682SXin Li INPUT_VAL(name->nb_inputs); \
122*1295d682SXin Li INPUT_VAL(name->nb_neurons); \
123*1295d682SXin Li ret->name ## _size = name->nb_neurons; \
124*1295d682SXin Li INPUT_ACTIVATION(name->activation); \
125*1295d682SXin Li INPUT_ARRAY(name->input_weights, name->nb_inputs * name->nb_neurons * 3); \
126*1295d682SXin Li INPUT_ARRAY(name->recurrent_weights, name->nb_neurons * name->nb_neurons * 3); \
127*1295d682SXin Li INPUT_ARRAY(name->bias, name->nb_neurons * 3); \
128*1295d682SXin Li } while (0)
129*1295d682SXin Li
130*1295d682SXin Li INPUT_DENSE(input_dense);
131*1295d682SXin Li INPUT_GRU(vad_gru);
132*1295d682SXin Li INPUT_GRU(noise_gru);
133*1295d682SXin Li INPUT_GRU(denoise_gru);
134*1295d682SXin Li INPUT_DENSE(denoise_output);
135*1295d682SXin Li INPUT_DENSE(vad_output);
136*1295d682SXin Li
137*1295d682SXin Li return ret;
138*1295d682SXin Li }
139*1295d682SXin Li
rnnoise_model_free(RNNModel * model)140*1295d682SXin Li void rnnoise_model_free(RNNModel *model)
141*1295d682SXin Li {
142*1295d682SXin Li #define FREE_MAYBE(ptr) do { if (ptr) free(ptr); } while (0)
143*1295d682SXin Li #define FREE_DENSE(name) do { \
144*1295d682SXin Li if (model->name) { \
145*1295d682SXin Li free((void *) model->name->input_weights); \
146*1295d682SXin Li free((void *) model->name->bias); \
147*1295d682SXin Li free((void *) model->name); \
148*1295d682SXin Li } \
149*1295d682SXin Li } while (0)
150*1295d682SXin Li #define FREE_GRU(name) do { \
151*1295d682SXin Li if (model->name) { \
152*1295d682SXin Li free((void *) model->name->input_weights); \
153*1295d682SXin Li free((void *) model->name->recurrent_weights); \
154*1295d682SXin Li free((void *) model->name->bias); \
155*1295d682SXin Li free((void *) model->name); \
156*1295d682SXin Li } \
157*1295d682SXin Li } while (0)
158*1295d682SXin Li
159*1295d682SXin Li if (!model)
160*1295d682SXin Li return;
161*1295d682SXin Li FREE_DENSE(input_dense);
162*1295d682SXin Li FREE_GRU(vad_gru);
163*1295d682SXin Li FREE_GRU(noise_gru);
164*1295d682SXin Li FREE_GRU(denoise_gru);
165*1295d682SXin Li FREE_DENSE(denoise_output);
166*1295d682SXin Li FREE_DENSE(vad_output);
167*1295d682SXin Li free(model);
168*1295d682SXin Li }
169