FreeCalypso > hg > gsm-codec-lib
comparison hrutil/dec-craft.c @ 518:087a88d25ba2
new program gsmhr-dec-craft
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 01 Sep 2024 18:58:02 +0000 |
parents | |
children | 6f8abfe253a4 |
comparison
equal
deleted
inserted
replaced
517:2d703e1e9107 | 518:087a88d25ba2 |
---|---|
1 /* | |
2 * This program facilitates hand-crafting HRv1 decoder input files (*.dec). | |
3 * It reads a line-based ASCII source and compiles it into binary *.dec format. | |
4 */ | |
5 | |
6 #include <sys/types.h> | |
7 #include <ctype.h> | |
8 #include <stdio.h> | |
9 #include <stdint.h> | |
10 #include <stdlib.h> | |
11 #include <string.h> | |
12 #include <strings.h> | |
13 #include "../libgsmhr1/tw_gsmhr.h" | |
14 | |
15 #define MAX_FIELDS 18 | |
16 | |
17 static char *infname, *outfname; | |
18 static FILE *inf, *outf; | |
19 | |
20 static int lineno; | |
21 static char linebuf[256]; | |
22 static char *fields[MAX_FIELDS]; | |
23 static unsigned nfields; | |
24 | |
25 static int16_t dec_frame[GSMHR_NUM_PARAMS_DEC]; | |
26 static unsigned taf_count; | |
27 | |
28 static void | |
29 set_all_0() | |
30 { | |
31 bzero(dec_frame, sizeof(int16_t) * GSMHR_NUM_PARAMS); | |
32 } | |
33 | |
34 static void | |
35 set_dhf() | |
36 { | |
37 bcopy(gsmhr_dhf_params, dec_frame, sizeof(int16_t) * GSMHR_NUM_PARAMS); | |
38 } | |
39 | |
40 static void | |
41 set_sid_cw() | |
42 { | |
43 /* Int_LPC and Mode */ | |
44 dec_frame[4] = 1; | |
45 dec_frame[5] = 3; | |
46 /* subframe 1 */ | |
47 dec_frame[6] = 0xFF; | |
48 dec_frame[7] = 0x1FF; | |
49 dec_frame[8] = 0x1F; | |
50 /* subframe 2 */ | |
51 dec_frame[9] = 0xF; | |
52 dec_frame[10] = 0x1FF; | |
53 dec_frame[11] = 0x1F; | |
54 /* subframe 3 */ | |
55 dec_frame[12] = 0xF; | |
56 dec_frame[13] = 0x1FF; | |
57 dec_frame[14] = 0x1F; | |
58 /* subframe 4 */ | |
59 dec_frame[15] = 0xF; | |
60 dec_frame[16] = 0x1FF; | |
61 dec_frame[17] = 0x1F; | |
62 } | |
63 | |
64 static int | |
65 get_line() | |
66 { | |
67 char *cp; | |
68 | |
69 if (!fgets(linebuf, sizeof linebuf, inf)) | |
70 return 1; | |
71 lineno++; | |
72 if (!index(linebuf, '\n')) { | |
73 fprintf(stderr, "%s line %d: too long or missing newline\n", | |
74 infname, lineno); | |
75 exit(1); | |
76 } | |
77 nfields = 0; | |
78 for (cp = linebuf; ; ) { | |
79 while (isspace(*cp)) | |
80 cp++; | |
81 if (*cp == '\0' || *cp == '#') | |
82 break; | |
83 if (nfields >= MAX_FIELDS) { | |
84 fprintf(stderr, "%s line %d: too many fields\n", | |
85 infname, lineno); | |
86 exit(1); | |
87 } | |
88 fields[nfields++] = cp; | |
89 while (*cp && !isspace(*cp)) | |
90 cp++; | |
91 if (*cp) | |
92 *cp++ = '\0'; | |
93 } | |
94 return 0; | |
95 } | |
96 | |
97 static int | |
98 get_line_nonempty() | |
99 { | |
100 int rc; | |
101 | |
102 for (;;) { | |
103 rc = get_line(); | |
104 if (rc) | |
105 return rc; | |
106 if (nfields) | |
107 return 0; | |
108 } | |
109 } | |
110 | |
111 static void | |
112 set_speech_params(start_param, start_arg) | |
113 unsigned start_param, start_arg; | |
114 { | |
115 unsigned ni, no; | |
116 u_long val; | |
117 char *cp; | |
118 | |
119 no = start_param; | |
120 for (ni = start_arg; ni < nfields; ni++) { | |
121 if (!isxdigit(fields[ni][0])) { | |
122 inv_number: fprintf(stderr, | |
123 "%s line %d: field \"%s\" is not a valid number\n", | |
124 infname, lineno, fields[ni]); | |
125 exit(1); | |
126 } | |
127 val = strtoul(fields[ni], &cp, 16); | |
128 if (*cp) | |
129 goto inv_number; | |
130 if (val > 0x7FF) { | |
131 fprintf(stderr, | |
132 "%s line %d: number \"%s\" is too large for a speech parameter\n", | |
133 infname, lineno, fields[ni]); | |
134 exit(1); | |
135 } | |
136 dec_frame[no++] = val; | |
137 } | |
138 } | |
139 | |
140 static void | |
141 handle_r0() | |
142 { | |
143 if (nfields != 2) { | |
144 fprintf(stderr, "%s line %d: R0 takes one argument\n", | |
145 infname, lineno); | |
146 exit(1); | |
147 } | |
148 set_speech_params(0, 1); | |
149 } | |
150 | |
151 static void | |
152 handle_lpc() | |
153 { | |
154 if (nfields != 5) { | |
155 fprintf(stderr, "%s line %d: LPC takes 4 arguments\n", | |
156 infname, lineno); | |
157 exit(1); | |
158 } | |
159 set_speech_params(1, 1); | |
160 } | |
161 | |
162 static void | |
163 handle_mode() | |
164 { | |
165 if (nfields != 2) { | |
166 fprintf(stderr, "%s line %d: Mode takes one argument\n", | |
167 infname, lineno); | |
168 exit(1); | |
169 } | |
170 set_speech_params(5, 1); | |
171 } | |
172 | |
173 static void | |
174 handle_sf() | |
175 { | |
176 unsigned sf_0_based; | |
177 | |
178 if (nfields != 5) { | |
179 fprintf(stderr, "%s line %d: sf takes 4 arguments\n", | |
180 infname, lineno); | |
181 exit(1); | |
182 } | |
183 if (fields[1][0] < '1' || fields[1][0] > '4' || fields[1][1]) { | |
184 fprintf(stderr, | |
185 "%s line %d: first argument to sf must be in range [1,4]\n", | |
186 infname, lineno); | |
187 exit(1); | |
188 } | |
189 sf_0_based = fields[1][0] - '0'; | |
190 set_speech_params(6 + sf_0_based * 3, 2); | |
191 } | |
192 | |
193 static void | |
194 handle_bfi() | |
195 { | |
196 if (nfields != 2) { | |
197 fprintf(stderr, "%s line %d: BFI takes one argument\n", | |
198 infname, lineno); | |
199 exit(1); | |
200 } | |
201 if (fields[1][0] < '0' || fields[1][0] > '1' || fields[1][1]) { | |
202 fprintf(stderr, | |
203 "%s line %d: invalid BFI argument \"%s\" (must be 0 or 1)\n", | |
204 infname, lineno, fields[1]); | |
205 exit(1); | |
206 } | |
207 dec_frame[18] = fields[1][0] - '0'; | |
208 } | |
209 | |
210 static void | |
211 handle_ufi() | |
212 { | |
213 if (nfields != 2) { | |
214 fprintf(stderr, "%s line %d: UFI takes one argument\n", | |
215 infname, lineno); | |
216 exit(1); | |
217 } | |
218 if (fields[1][0] < '0' || fields[1][0] > '1' || fields[1][1]) { | |
219 fprintf(stderr, | |
220 "%s line %d: invalid UFI argument \"%s\" (must be 0 or 1)\n", | |
221 infname, lineno, fields[1]); | |
222 exit(1); | |
223 } | |
224 dec_frame[19] = fields[1][0] - '0'; | |
225 } | |
226 | |
227 static void | |
228 handle_sid() | |
229 { | |
230 if (nfields != 2) { | |
231 fprintf(stderr, "%s line %d: SID takes one argument\n", | |
232 infname, lineno); | |
233 exit(1); | |
234 } | |
235 if (fields[1][0] < '0' || fields[1][0] > '2' || fields[1][1]) { | |
236 fprintf(stderr, | |
237 "%s line %d: invalid SID argument \"%s\" (must be 0, 1 or 2)\n", | |
238 infname, lineno, fields[1]); | |
239 exit(1); | |
240 } | |
241 dec_frame[20] = fields[1][0] - '0'; | |
242 } | |
243 | |
244 static void | |
245 set_taf_count() | |
246 { | |
247 if (nfields != 2) { | |
248 fprintf(stderr, "%s line %d: taf-count takes one argument\n", | |
249 infname, lineno); | |
250 exit(1); | |
251 } | |
252 taf_count = atoi(fields[1]); | |
253 if (taf_count > 11) { | |
254 fprintf(stderr, | |
255 "%s line %d: taf-count argument \"%s\" is invalid\n", | |
256 infname, lineno, fields[1]); | |
257 exit(1); | |
258 } | |
259 } | |
260 | |
261 static void | |
262 emit_frame() | |
263 { | |
264 if (gsmhr_check_common_params(dec_frame) < 0) { | |
265 fprintf(stderr, | |
266 "%s line %d: one of the preceding speech parameters is out of range\n", | |
267 infname, lineno); | |
268 exit(1); | |
269 } | |
270 dec_frame[21] = (taf_count == 11); | |
271 fwrite(dec_frame, 2, GSMHR_NUM_PARAMS_DEC, outf); | |
272 taf_count++; | |
273 if (taf_count >= 12) | |
274 taf_count = 0; | |
275 } | |
276 | |
277 main(argc, argv) | |
278 char **argv; | |
279 { | |
280 int rc; | |
281 | |
282 if (argc != 3) { | |
283 fprintf(stderr, "usage: %s input.src output.dec\n", argv[0]); | |
284 exit(1); | |
285 } | |
286 infname = argv[1]; | |
287 outfname = argv[2]; | |
288 | |
289 inf = fopen(infname, "r"); | |
290 if (!inf) { | |
291 perror(infname); | |
292 exit(1); | |
293 } | |
294 outf = fopen(outfname, "w"); | |
295 if (!outf) { | |
296 perror(outfname); | |
297 exit(1); | |
298 } | |
299 | |
300 for (;;) { | |
301 rc = get_line_nonempty(); | |
302 if (rc) | |
303 break; | |
304 if (!strcasecmp(fields[0], "all-0")) | |
305 set_all_0(); | |
306 else if (!strcasecmp(fields[0], "dhf")) | |
307 set_dhf(); | |
308 else if (!strcasecmp(fields[0], "r0")) | |
309 handle_r0(); | |
310 else if (!strcasecmp(fields[0], "lpc")) | |
311 handle_lpc(); | |
312 else if (!strcasecmp(fields[0], "mode")) | |
313 handle_mode(); | |
314 else if (!strcasecmp(fields[0], "sf")) | |
315 handle_sf(); | |
316 else if (!strcasecmp(fields[0], "bfi")) | |
317 handle_bfi(); | |
318 else if (!strcasecmp(fields[0], "ufi")) | |
319 handle_ufi(); | |
320 else if (!strcasecmp(fields[0], "sid")) | |
321 handle_sid(); | |
322 else if (!strcasecmp(fields[0], "sid-cw")) | |
323 set_sid_cw(); | |
324 else if (!strcasecmp(fields[0], "taf-count")) | |
325 set_taf_count(); | |
326 else if (!strcasecmp(fields[0], "emit-frame")) | |
327 emit_frame(); | |
328 else { | |
329 fprintf(stderr, | |
330 "%s line %d: non-understood keyword \"%s\"\n", | |
331 infname, lineno, fields[0]); | |
332 exit(1); | |
333 } | |
334 } | |
335 exit(0); | |
336 } |