FreeCalypso > hg > freecalypso-tools
comparison tchtools/fc-vm2gsmx.c @ 905:546bf873ccc8
tchtools: new program fc-vm2gsmx
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 28 Dec 2022 09:08:50 +0000 |
parents | tchtools/fc-vm2hex.c@5041bcb8140f |
children |
comparison
equal
deleted
inserted
replaced
904:5041bcb8140f | 905:546bf873ccc8 |
---|---|
1 /* | |
2 * This utility converts old-fashioned (non-AMR) TCS211 voice memo files | |
3 * read out of FFS into Themyscira Wireless gsmx (extended-libgsm) format, | |
4 * allowing further decoding into playable speech with gsmfr-decode. | |
5 */ | |
6 | |
7 #include <sys/types.h> | |
8 #include <stdio.h> | |
9 #include <stdlib.h> | |
10 | |
11 static char *infname; | |
12 static FILE *inf, *outf; | |
13 static u_long file_offset; | |
14 | |
15 static const u_char bfi_marker[2] = {0xBF, 0x00}; | |
16 | |
17 static unsigned | |
18 get_word() | |
19 { | |
20 u_char b[2]; | |
21 int i, c; | |
22 | |
23 for (i = 0; i < 2; i++) { | |
24 c = getc(inf); | |
25 if (c < 0) { | |
26 fprintf(stderr, "error: premature EOF in %s\n", | |
27 infname); | |
28 exit(1); | |
29 } | |
30 b[i] = c; | |
31 file_offset++; | |
32 } | |
33 return((b[1] << 8) | b[0]); | |
34 } | |
35 | |
36 static void | |
37 read_dsp_bytes(bytes) | |
38 u_char *bytes; | |
39 { | |
40 int i, dp; | |
41 unsigned word; | |
42 | |
43 dp = 0; | |
44 for (i = 0; i < 17; i++) { | |
45 word = get_word(); | |
46 bytes[dp++] = word >> 8; | |
47 bytes[dp++] = word; | |
48 } | |
49 } | |
50 | |
51 static void | |
52 convert_speech_sample() | |
53 { | |
54 u_char tidsp_bytes[34], libgsm_bytes[33]; | |
55 | |
56 read_dsp_bytes(tidsp_bytes); | |
57 gsm0610_tidsp_to_libgsm(tidsp_bytes, libgsm_bytes); | |
58 fwrite(libgsm_bytes, 1, 33, outf); | |
59 } | |
60 | |
61 main(argc, argv) | |
62 char **argv; | |
63 { | |
64 unsigned first_word; | |
65 | |
66 if (argc != 3) { | |
67 fprintf(stderr, "usage: %s infile outfile\n", argv[0]); | |
68 exit(1); | |
69 } | |
70 infname = argv[1]; | |
71 inf = fopen(infname, "r"); | |
72 if (!inf) { | |
73 perror(infname); | |
74 exit(1); | |
75 } | |
76 outf = fopen(argv[2], "w"); | |
77 if (!outf) { | |
78 perror(argv[2]); | |
79 exit(1); | |
80 } | |
81 for (;;) { | |
82 first_word = get_word(); | |
83 if (first_word == 0xFBFF) /* SC_VM_END_MASK */ | |
84 break; | |
85 if ((first_word & 0xB7FF) == 0x8400) { | |
86 /* skip dummy header words 1 and 2 */ | |
87 get_word(); | |
88 get_word(); | |
89 /* process the actual speech or SID frame */ | |
90 convert_speech_sample(); | |
91 } else if (first_word == 0x0400) { | |
92 /* it's a skipped frame, aka BFI */ | |
93 fwrite(bfi_marker, 1, 2, outf); | |
94 } else { | |
95 fprintf(stderr, | |
96 "error in %s at offset 0x%lx: invalid frame header word 0x%04X\n", | |
97 infname, file_offset, first_word); | |
98 exit(1); | |
99 } | |
100 } | |
101 fclose(outf); | |
102 exit(0); | |
103 } |