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 } |
