1 /* Copyright (c) 2018 Mozilla */
2 /*
3 Redistribution and use in source and binary forms, with or without
4 modification, are permitted provided that the following conditions
5 are met:
6
7 - Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9
10 - Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
18 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <math.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include "arch.h"
36 #include "lpcnet.h"
37 #include "freq.h"
38 #include "os_support.h"
39 #include "fargan.h"
40 #include "cpu_support.h"
41
42 #ifdef USE_WEIGHTS_FILE
43 # if __unix__
44 # include <fcntl.h>
45 # include <sys/mman.h>
46 # include <unistd.h>
47 # include <sys/stat.h>
48 /* When available, mmap() is preferable to reading the file, as it leads to
49 better resource utilization, especially if multiple processes are using the same
50 file (mapping will be shared in cache). */
load_blob(const char * filename,int * len)51 void *load_blob(const char *filename, int *len) {
52 int fd;
53 void *data;
54 struct stat st;
55 if (stat(filename, &st)) {
56 *len = 0;
57 return NULL;
58 }
59 *len = st.st_size;
60 fd = open(filename, O_RDONLY);
61 if (fd<0) {
62 *len = 0;
63 return NULL;
64 }
65 data = mmap(NULL, *len, PROT_READ, MAP_SHARED, fd, 0);
66 if (data == MAP_FAILED) {
67 *len = 0;
68 data = NULL;
69 }
70 close(fd);
71 return data;
72 }
free_blob(void * blob,int len)73 void free_blob(void *blob, int len) {
74 if (blob) munmap(blob, len);
75 }
76 # else
load_blob(const char * filename,int * len)77 void *load_blob(const char *filename, int *len) {
78 FILE *file;
79 void *data;
80 file = fopen(filename, "r");
81 if (file == NULL)
82 {
83 perror("could not open blob file");
84 *len = 0;
85 return NULL;
86 }
87 fseek(file, 0L, SEEK_END);
88 *len = ftell(file);
89 fseek(file, 0L, SEEK_SET);
90 if (*len <= 0) {
91 *len = 0;
92 return NULL;
93 }
94 data = malloc(*len);
95 if (!data) {
96 *len = 0;
97 return NULL;
98 }
99 *len = fread(data, 1, *len, file);
100 return data;
101 }
free_blob(void * blob,int len)102 void free_blob(void *blob, int len) {
103 free(blob);
104 (void)len;
105 }
106 # endif
107 #endif
108
109 #define MODE_FEATURES 2
110 /*#define MODE_SYNTHESIS 3*/
111 #define MODE_ADDLPC 5
112 #define MODE_FWGAN_SYNTHESIS 6
113 #define MODE_FARGAN_SYNTHESIS 7
114
usage(void)115 void usage(void) {
116 fprintf(stderr, "usage: lpcnet_demo -features <input.pcm> <features.f32>\n");
117 fprintf(stderr, " lpcnet_demo -fargan-synthesis <features.f32> <output.pcm>\n");
118 fprintf(stderr, " lpcnet_demo -addlpc <features_without_lpc.f32> <features_with_lpc.lpc>\n\n");
119 fprintf(stderr, " plc_options:\n");
120 fprintf(stderr, " causal: normal (causal) PLC\n");
121 fprintf(stderr, " codec: normal (causal) PLC without cross-fade (will glitch)\n");
122 exit(1);
123 }
124
main(int argc,char ** argv)125 int main(int argc, char **argv) {
126 int mode=0;
127 int arch;
128 FILE *fin, *fout;
129 #ifdef USE_WEIGHTS_FILE
130 int len;
131 void *data;
132 const char *filename = "weights_blob.bin";
133 #endif
134 arch = opus_select_arch();
135 if (argc < 4) usage();
136 if (strcmp(argv[1], "-features") == 0) mode=MODE_FEATURES;
137 else if (strcmp(argv[1], "-fargan-synthesis") == 0) mode=MODE_FARGAN_SYNTHESIS;
138 else if (strcmp(argv[1], "-addlpc") == 0){
139 mode=MODE_ADDLPC;
140 } else {
141 usage();
142 }
143 if (argc != 4) usage();
144 fin = fopen(argv[2], "rb");
145 if (fin == NULL) {
146 fprintf(stderr, "Can't open %s\n", argv[2]);
147 exit(1);
148 }
149
150 fout = fopen(argv[3], "wb");
151 if (fout == NULL) {
152 fprintf(stderr, "Can't open %s\n", argv[3]);
153 exit(1);
154 }
155 #ifdef USE_WEIGHTS_FILE
156 data = load_blob(filename, &len);
157 #endif
158 if (mode == MODE_FEATURES) {
159 LPCNetEncState *net;
160 net = lpcnet_encoder_create();
161 while (1) {
162 float features[NB_TOTAL_FEATURES];
163 opus_int16 pcm[LPCNET_FRAME_SIZE];
164 size_t ret;
165 ret = fread(pcm, sizeof(pcm[0]), LPCNET_FRAME_SIZE, fin);
166 if (feof(fin) || ret != LPCNET_FRAME_SIZE) break;
167 lpcnet_compute_single_frame_features(net, pcm, features, arch);
168 fwrite(features, sizeof(float), NB_TOTAL_FEATURES, fout);
169 }
170 lpcnet_encoder_destroy(net);
171 } else if (mode == MODE_FARGAN_SYNTHESIS) {
172 FARGANState fargan;
173 size_t ret, i;
174 float in_features[5*NB_TOTAL_FEATURES];
175 float zeros[320] = {0};
176 fargan_init(&fargan);
177 #ifdef USE_WEIGHTS_FILE
178 fargan_load_model(&fargan, data, len);
179 #endif
180 /* uncomment the following to align with Python code */
181 /*ret = fread(&in_features[0], sizeof(in_features[0]), NB_TOTAL_FEATURES, fin);*/
182 for (i=0;i<5;i++) {
183 ret = fread(&in_features[i*NB_FEATURES], sizeof(in_features[0]), NB_TOTAL_FEATURES, fin);
184 }
185 fargan_cont(&fargan, zeros, in_features);
186 while (1) {
187 float features[NB_FEATURES];
188 float fpcm[LPCNET_FRAME_SIZE];
189 opus_int16 pcm[LPCNET_FRAME_SIZE];
190 ret = fread(in_features, sizeof(features[0]), NB_TOTAL_FEATURES, fin);
191 if (feof(fin) || ret != NB_TOTAL_FEATURES) break;
192 OPUS_COPY(features, in_features, NB_FEATURES);
193 fargan_synthesize(&fargan, fpcm, features);
194 for (i=0;i<LPCNET_FRAME_SIZE;i++) pcm[i] = (int)floor(.5 + MIN32(32767, MAX32(-32767, 32768.f*fpcm[i])));
195 fwrite(pcm, sizeof(pcm[0]), LPCNET_FRAME_SIZE, fout);
196 }
197 } else if (mode == MODE_ADDLPC) {
198 float features[36];
199 size_t ret;
200
201 while (1) {
202 ret = fread(features, sizeof(features[0]), 36, fin);
203 if (ret != 36 || feof(fin)) break;
204 lpc_from_cepstrum(&features[20], &features[0]);
205 fwrite(features, sizeof(features[0]), 36, fout);
206 }
207
208 } else {
209 fprintf(stderr, "unknown action\n");
210 }
211 fclose(fin);
212 fclose(fout);
213 #ifdef USE_WEIGHTS_FILE
214 free_blob(data, len);
215 #endif
216 return 0;
217 }
218