FreeCalypso > hg > gsm-codec-lib
comparison hrutil/cod-craft.c @ 570:b4c4ed4b1b91
hrutil: new program gsmhr-cod-craft
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 12 Feb 2025 04:53:08 +0000 |
parents | hrutil/dec-craft.c@0d05892150cf |
children | 5452d6cd64b1 |
comparison
equal
deleted
inserted
replaced
569:0d05892150cf | 570:b4c4ed4b1b91 |
---|---|
1 /* | |
2 * This program facilitates hand-crafting HRv1 encoder output files (*.cod). | |
3 * It reads a line-based ASCII source and compiles it into binary *.cod 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 enc_frame[GSMHR_NUM_PARAMS_ENC]; | |
26 | |
27 static void | |
28 set_all_0() | |
29 { | |
30 bzero(enc_frame, sizeof(int16_t) * GSMHR_NUM_PARAMS); | |
31 } | |
32 | |
33 static void | |
34 set_dhf() | |
35 { | |
36 bcopy(gsmhr_dhf_params, enc_frame, sizeof(int16_t) * GSMHR_NUM_PARAMS); | |
37 } | |
38 | |
39 static void | |
40 set_sid_cw() | |
41 { | |
42 /* Int_LPC and Mode */ | |
43 enc_frame[4] = 1; | |
44 enc_frame[5] = 3; | |
45 /* subframe 1 */ | |
46 enc_frame[6] = 0xFF; | |
47 enc_frame[7] = 0x1FF; | |
48 enc_frame[8] = 0x1F; | |
49 /* subframe 2 */ | |
50 enc_frame[9] = 0xF; | |
51 enc_frame[10] = 0x1FF; | |
52 enc_frame[11] = 0x1F; | |
53 /* subframe 3 */ | |
54 enc_frame[12] = 0xF; | |
55 enc_frame[13] = 0x1FF; | |
56 enc_frame[14] = 0x1F; | |
57 /* subframe 4 */ | |
58 enc_frame[15] = 0xF; | |
59 enc_frame[16] = 0x1FF; | |
60 enc_frame[17] = 0x1F; | |
61 } | |
62 | |
63 static int | |
64 get_line() | |
65 { | |
66 char *cp; | |
67 | |
68 if (!fgets(linebuf, sizeof linebuf, inf)) | |
69 return 1; | |
70 lineno++; | |
71 if (!index(linebuf, '\n')) { | |
72 fprintf(stderr, "%s line %d: too long or missing newline\n", | |
73 infname, lineno); | |
74 exit(1); | |
75 } | |
76 nfields = 0; | |
77 for (cp = linebuf; ; ) { | |
78 while (isspace(*cp)) | |
79 cp++; | |
80 if (*cp == '\0' || *cp == '#') | |
81 break; | |
82 if (nfields >= MAX_FIELDS) { | |
83 fprintf(stderr, "%s line %d: too many fields\n", | |
84 infname, lineno); | |
85 exit(1); | |
86 } | |
87 fields[nfields++] = cp; | |
88 while (*cp && !isspace(*cp)) | |
89 cp++; | |
90 if (*cp) | |
91 *cp++ = '\0'; | |
92 } | |
93 return 0; | |
94 } | |
95 | |
96 static int | |
97 get_line_nonempty() | |
98 { | |
99 int rc; | |
100 | |
101 for (;;) { | |
102 rc = get_line(); | |
103 if (rc) | |
104 return rc; | |
105 if (nfields) | |
106 return 0; | |
107 } | |
108 } | |
109 | |
110 static void | |
111 set_speech_params(start_param, start_arg) | |
112 unsigned start_param, start_arg; | |
113 { | |
114 unsigned ni, no; | |
115 u_long val; | |
116 char *cp; | |
117 | |
118 no = start_param; | |
119 for (ni = start_arg; ni < nfields; ni++) { | |
120 if (!isxdigit(fields[ni][0])) { | |
121 inv_number: fprintf(stderr, | |
122 "%s line %d: field \"%s\" is not a valid number\n", | |
123 infname, lineno, fields[ni]); | |
124 exit(1); | |
125 } | |
126 val = strtoul(fields[ni], &cp, 16); | |
127 if (*cp) | |
128 goto inv_number; | |
129 if (val > 0x7FF) { | |
130 fprintf(stderr, | |
131 "%s line %d: number \"%s\" is too large for a speech parameter\n", | |
132 infname, lineno, fields[ni]); | |
133 exit(1); | |
134 } | |
135 enc_frame[no++] = val; | |
136 } | |
137 } | |
138 | |
139 static void | |
140 handle_r0() | |
141 { | |
142 if (nfields != 2) { | |
143 fprintf(stderr, "%s line %d: R0 takes one argument\n", | |
144 infname, lineno); | |
145 exit(1); | |
146 } | |
147 set_speech_params(0, 1); | |
148 } | |
149 | |
150 static void | |
151 handle_lpc() | |
152 { | |
153 if (nfields != 5) { | |
154 fprintf(stderr, "%s line %d: LPC takes 4 arguments\n", | |
155 infname, lineno); | |
156 exit(1); | |
157 } | |
158 set_speech_params(1, 1); | |
159 } | |
160 | |
161 static void | |
162 handle_mode() | |
163 { | |
164 if (nfields != 2) { | |
165 fprintf(stderr, "%s line %d: Mode takes one argument\n", | |
166 infname, lineno); | |
167 exit(1); | |
168 } | |
169 set_speech_params(5, 1); | |
170 } | |
171 | |
172 static void | |
173 handle_sf() | |
174 { | |
175 unsigned sf_0_based; | |
176 | |
177 if (nfields != 5) { | |
178 fprintf(stderr, "%s line %d: sf takes 4 arguments\n", | |
179 infname, lineno); | |
180 exit(1); | |
181 } | |
182 if (fields[1][0] < '1' || fields[1][0] > '4' || fields[1][1]) { | |
183 fprintf(stderr, | |
184 "%s line %d: first argument to sf must be in range [1,4]\n", | |
185 infname, lineno); | |
186 exit(1); | |
187 } | |
188 sf_0_based = fields[1][0] - '1'; | |
189 set_speech_params(6 + sf_0_based * 3, 2); | |
190 } | |
191 | |
192 static void | |
193 set_vad_sp() | |
194 { | |
195 if (nfields != 3) { | |
196 fprintf(stderr, "%s line %d: vad-sp takes 2 arguments\n", | |
197 infname, lineno); | |
198 exit(1); | |
199 } | |
200 if (fields[1][0] < '0' || fields[1][0] > '1' || fields[1][1]) { | |
201 fprintf(stderr, | |
202 "%s line %d: invalid VAD argument \"%s\" (must be 0 or 1)\n", | |
203 infname, lineno, fields[1]); | |
204 exit(1); | |
205 } | |
206 enc_frame[18] = fields[1][0] - '0'; | |
207 if (fields[2][0] < '0' || fields[2][0] > '1' || fields[2][1]) { | |
208 fprintf(stderr, | |
209 "%s line %d: invalid SP argument \"%s\" (must be 0 or 1)\n", | |
210 infname, lineno, fields[2]); | |
211 exit(1); | |
212 } | |
213 enc_frame[19] = fields[2][0] - '0'; | |
214 if (enc_frame[18] && !enc_frame[19]) { | |
215 fprintf(stderr, | |
216 "%s line %d: combination VAD=1 SP=0 is invalid\n", | |
217 infname, lineno); | |
218 exit(1); | |
219 } | |
220 } | |
221 | |
222 static void | |
223 emit_frame() | |
224 { | |
225 if (gsmhr_check_common_params(enc_frame) < 0) { | |
226 fprintf(stderr, | |
227 "%s line %d: one of the preceding speech parameters is out of range\n", | |
228 infname, lineno); | |
229 exit(1); | |
230 } | |
231 fwrite(enc_frame, 2, GSMHR_NUM_PARAMS_ENC, outf); | |
232 } | |
233 | |
234 main(argc, argv) | |
235 char **argv; | |
236 { | |
237 int rc; | |
238 | |
239 if (argc != 3) { | |
240 fprintf(stderr, "usage: %s input.src output.cod\n", argv[0]); | |
241 exit(1); | |
242 } | |
243 infname = argv[1]; | |
244 outfname = argv[2]; | |
245 | |
246 inf = fopen(infname, "r"); | |
247 if (!inf) { | |
248 perror(infname); | |
249 exit(1); | |
250 } | |
251 outf = fopen(outfname, "w"); | |
252 if (!outf) { | |
253 perror(outfname); | |
254 exit(1); | |
255 } | |
256 | |
257 for (;;) { | |
258 rc = get_line_nonempty(); | |
259 if (rc) | |
260 break; | |
261 if (!strcasecmp(fields[0], "all-0")) | |
262 set_all_0(); | |
263 else if (!strcasecmp(fields[0], "dhf")) | |
264 set_dhf(); | |
265 else if (!strcasecmp(fields[0], "r0")) | |
266 handle_r0(); | |
267 else if (!strcasecmp(fields[0], "lpc")) | |
268 handle_lpc(); | |
269 else if (!strcasecmp(fields[0], "mode")) | |
270 handle_mode(); | |
271 else if (!strcasecmp(fields[0], "sf")) | |
272 handle_sf(); | |
273 else if (!strcasecmp(fields[0], "sid-cw")) | |
274 set_sid_cw(); | |
275 else if (!strcasecmp(fields[0], "vad-sp")) | |
276 set_vad_sp(); | |
277 else if (!strcasecmp(fields[0], "emit-frame")) | |
278 emit_frame(); | |
279 else { | |
280 fprintf(stderr, | |
281 "%s line %d: non-understood keyword \"%s\"\n", | |
282 infname, lineno, fields[0]); | |
283 exit(1); | |
284 } | |
285 } | |
286 exit(0); | |
287 } |