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