FreeCalypso > hg > gsm-net-reveng
comparison trau-decode/extr-main.c @ 9:0565aaa84b17
trau-decode: implement trau-extr program
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 24 May 2024 19:44:14 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
8:85662304252e | 9:0565aaa84b17 |
---|---|
1 /* | |
2 * This program reads a 64 kbit/s timeslot recording file with a focus | |
3 * on a single sub-timeslot just like trau-parse, but it needs to be | |
4 * invoked with a starting and ending offset for the frame-aligned | |
5 * portion of interest (found with trau-parse), and it saves (converts) | |
6 * the selected stream of TRAU-UL frames to a Themyscira gsmx file. | |
7 */ | |
8 | |
9 #include <sys/types.h> | |
10 #include <stdio.h> | |
11 #include <stdint.h> | |
12 #include <stdlib.h> | |
13 #include <string.h> | |
14 #include <strings.h> | |
15 | |
16 static void | |
17 reduce_to_subslot(buf, right_shift) | |
18 uint8_t *buf; | |
19 { | |
20 unsigned n; | |
21 | |
22 for (n = 0; n < 160; n++) { | |
23 buf[n] >>= right_shift; | |
24 buf[n] &= 3; | |
25 } | |
26 } | |
27 | |
28 static void | |
29 unpack_dibits(dibits, frame_bits) | |
30 uint8_t *dibits, *frame_bits; | |
31 { | |
32 int i, inb; | |
33 uint8_t *op; | |
34 | |
35 op = frame_bits; | |
36 for (i = 0; i < 160; i++) { | |
37 inb = dibits[i]; | |
38 if (inb & 2) | |
39 *op++ = 1; | |
40 else | |
41 *op++ = 0; | |
42 if (inb & 1) | |
43 *op++ = 1; | |
44 else | |
45 *op++ = 0; | |
46 } | |
47 } | |
48 | |
49 static unsigned | |
50 bits_to_num(bits, nbits) | |
51 uint8_t *bits; | |
52 unsigned nbits; | |
53 { | |
54 unsigned accum; | |
55 unsigned n; | |
56 | |
57 accum = 0; | |
58 for (n = 0; n < nbits; n++) { | |
59 accum <<= 1; | |
60 if (*bits) | |
61 accum |= 1; | |
62 bits++; | |
63 } | |
64 return accum; | |
65 } | |
66 | |
67 static void | |
68 collect_d_bits(frame_bits, d_bits) | |
69 uint8_t *frame_bits, *d_bits; | |
70 { | |
71 bcopy(frame_bits + 33, d_bits, 15); | |
72 bcopy(frame_bits + 49, d_bits + 15, 15); | |
73 bcopy(frame_bits + 65, d_bits + 30, 15); | |
74 bcopy(frame_bits + 81, d_bits + 45, 15); | |
75 bcopy(frame_bits + 97, d_bits + 60, 15); | |
76 bcopy(frame_bits + 113, d_bits + 75, 15); | |
77 bcopy(frame_bits + 129, d_bits + 90, 15); | |
78 bcopy(frame_bits + 145, d_bits + 105, 15); | |
79 bcopy(frame_bits + 161, d_bits + 120, 15); | |
80 bcopy(frame_bits + 177, d_bits + 135, 15); | |
81 bcopy(frame_bits + 193, d_bits + 150, 15); | |
82 bcopy(frame_bits + 209, d_bits + 165, 15); | |
83 bcopy(frame_bits + 225, d_bits + 180, 15); | |
84 bcopy(frame_bits + 241, d_bits + 195, 15); | |
85 bcopy(frame_bits + 257, d_bits + 210, 15); | |
86 bcopy(frame_bits + 273, d_bits + 225, 15); | |
87 bcopy(frame_bits + 289, d_bits + 240, 15); | |
88 bcopy(frame_bits + 305, d_bits + 255, 5); | |
89 } | |
90 | |
91 static void | |
92 process_frame(cur_offset, dibits, outf) | |
93 u_long cur_offset; | |
94 uint8_t *dibits; | |
95 FILE *outf; | |
96 { | |
97 uint8_t frame_bits[320], d_bits[260]; | |
98 unsigned c1_5; | |
99 | |
100 unpack_dibits(dibits, frame_bits); | |
101 if (frame_bits[28]) { /* C12 aka BFI */ | |
102 putc(0xBF, outf); | |
103 putc(frame_bits[31], outf); /* C15 aka TAF */ | |
104 return; | |
105 } | |
106 collect_d_bits(frame_bits, d_bits); | |
107 c1_5 = bits_to_num(frame_bits + 17, 5); | |
108 switch (c1_5) { | |
109 case 0x02: | |
110 convert_fr_frame(d_bits, outf); | |
111 break; | |
112 case 0x1A: | |
113 convert_efr_frame(d_bits, outf); | |
114 break; | |
115 default: | |
116 fprintf(stderr, | |
117 "error: unknown frame type 0x%x at file offset 0x%lx\n", | |
118 c1_5, cur_offset); | |
119 exit(1); | |
120 } | |
121 } | |
122 | |
123 main(argc, argv) | |
124 char **argv; | |
125 { | |
126 FILE *inf, *outf; | |
127 int subslot, right_shift; | |
128 u_long start_offset, end_offset, cur_offset; | |
129 uint8_t readbuf[160]; | |
130 int cc; | |
131 | |
132 if (argc != 6) { | |
133 fprintf(stderr, "usage: %s binfile subslot start end outfile\n", | |
134 argv[0]); | |
135 exit(1); | |
136 } | |
137 inf = fopen(argv[1], "r"); | |
138 if (!inf) { | |
139 perror(argv[1]); | |
140 exit(1); | |
141 } | |
142 subslot = atoi(argv[2]); | |
143 if (subslot < 0 || subslot > 3) { | |
144 fprintf(stderr, "error: invalid subslot argument\n"); | |
145 exit(1); | |
146 } | |
147 right_shift = (3 - subslot) * 2; | |
148 start_offset = strtoul(argv[3], 0, 0); | |
149 fseek(inf, start_offset, SEEK_SET); | |
150 end_offset = strtoul(argv[4], 0, 0); | |
151 outf = fopen(argv[5], "w"); | |
152 if (!outf) { | |
153 perror(argv[5]); | |
154 exit(1); | |
155 } | |
156 for (cur_offset = start_offset; ; cur_offset += 160) { | |
157 if (end_offset && cur_offset >= end_offset) | |
158 break; | |
159 cc = fread(readbuf, 1, 160, inf); | |
160 if (cc < 160) | |
161 break; | |
162 reduce_to_subslot(readbuf, right_shift); | |
163 process_frame(cur_offset, readbuf, outf); | |
164 } | |
165 exit(0); | |
166 } |