vadpcm_dec.c (8673B)
1 #include <unistd.h> 2 #include <assert.h> 3 #include <string.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <signal.h> 7 #include <fcntl.h> 8 #include "vadpcm.h" 9 10 static void int_handler(s32 sig) 11 { 12 s32 flags; 13 14 flags = fcntl(STDIN_FILENO, F_GETFL, 0); 15 flags &= ~FNDELAY; 16 fcntl(STDIN_FILENO, F_SETFL, flags); 17 exit(0); 18 } 19 20 static char usage[] = "bitfile"; 21 22 #ifdef __sgi 23 24 // Declaring a sigaction like this is wildly unportable; you're supposed to 25 // assign members one by one in code. We do that in the non-SGI case. 26 static struct sigaction int_act = { 27 /* sa_flags = */ SA_RESTART, 28 /* sa_handler = */ &int_handler, 29 /* sa_mask = */ 0, 30 }; 31 32 #endif 33 34 s32 main(s32 argc, char **argv) 35 { 36 s32 c; 37 u8 cc; 38 u8 doloop = 0; 39 s16 order; 40 s16 version; 41 s16 nloops; 42 s16 npredictors; 43 s32 flags; 44 s32 ***coefTable = NULL; 45 s32 i; 46 s32 j; 47 s32 *outp; 48 s32 *state; 49 s32 done = 0; 50 s32 num; 51 u32 ts; 52 s32 soundPointer; 53 s32 cType; 54 s32 offset; 55 s32 currPos = 0; 56 s32 nSamples; 57 s32 framePos; 58 s32 loopBegin; 59 s32 left; 60 ALADPCMloop *aloops; 61 Chunk FormChunk; 62 ChunkHeader Header; 63 CommonChunk CommChunk; 64 SoundDataChunk SndDChunk; 65 char *ChunkName; 66 FILE *ifile; 67 char *progname = argv[0]; 68 69 #ifndef __sgi 70 nloops = 0; 71 #endif 72 73 if (argc < 2) 74 { 75 fprintf(stderr, "%s %s\n", progname, usage); 76 exit(1); 77 } 78 79 while ((c = getopt(argc, argv, "l")) != -1) 80 { 81 switch (c) 82 { 83 case 'l': 84 doloop = 1; 85 break; 86 } 87 } 88 89 argv += optind - 1; 90 if ((ifile = fopen(argv[1], MODE_READ)) == NULL) 91 { 92 fprintf(stderr, "%s: bitstream file [%s] could not be opened\n", progname, argv[1]); 93 exit(1); 94 } 95 96 state = malloc(16 * sizeof(int)); 97 for (i = 0; i < 16; i++) 98 { 99 state[i] = 0; 100 } 101 102 fread(&FormChunk, sizeof(FormChunk), 1, ifile); 103 BSWAP32(FormChunk.ckID) 104 BSWAP32(FormChunk.formType) 105 if ((FormChunk.ckID != 0x464f524d) || (FormChunk.formType != 0x41494643)) // FORM, AIFC 106 { 107 fprintf(stderr, "%s: [%s] is not an AIFF-C File\n", progname, argv[1]); 108 exit(1); 109 } 110 111 while (!done) 112 { 113 num = fread(&Header, sizeof(Header), 1, ifile); 114 if (num <= 0) 115 { 116 done = 1; 117 break; 118 } 119 BSWAP32(Header.ckID) 120 BSWAP32(Header.ckSize) 121 122 Header.ckSize++, Header.ckSize &= ~1; 123 switch (Header.ckID) 124 { 125 case 0x434f4d4d: // COMM 126 offset = ftell(ifile); 127 num = fread(&CommChunk, sizeof(CommChunk), 1, ifile); 128 if (num <= 0) 129 { 130 fprintf(stderr, "%s: error parsing file [%s]\n", progname, argv[1]); 131 done = 1; 132 } 133 BSWAP16(CommChunk.numChannels) 134 BSWAP16(CommChunk.numFramesH) 135 BSWAP16(CommChunk.numFramesL) 136 BSWAP16(CommChunk.sampleSize) 137 BSWAP16(CommChunk.compressionTypeH) 138 BSWAP16(CommChunk.compressionTypeL) 139 cType = (CommChunk.compressionTypeH << 16) + CommChunk.compressionTypeL; 140 if (cType != 0x56415043) // VAPC 141 { 142 fprintf(stderr, "%s: file [%s] is of the wrong compression type.\n", progname, argv[1]); 143 exit(1); 144 } 145 if (CommChunk.numChannels != 1) 146 { 147 fprintf(stderr, "%s: file [%s] contains %ld channels, only 1 channel supported.\n", progname, argv[1], (long) CommChunk.numChannels); 148 exit(1); 149 } 150 if (CommChunk.sampleSize != 16) 151 { 152 fprintf(stderr, "%s: file [%s] contains %ld bit samples, only 16 bit samples supported.\n", progname, argv[1], (long) CommChunk.sampleSize); 153 exit(1); 154 } 155 nSamples = (CommChunk.numFramesH << 16) + CommChunk.numFramesL; 156 fseek(ifile, offset + Header.ckSize, SEEK_SET); 157 break; 158 159 case 0x53534e44: // SSND 160 offset = ftell(ifile); 161 fread(&SndDChunk, sizeof(SndDChunk), 1, ifile); 162 BSWAP32(SndDChunk.offset) 163 BSWAP32(SndDChunk.blockSize) 164 // The assert error messages specify line numbers 165/166. Match 165 // that using a #line directive. 166 #ifdef __sgi 167 # line 164 168 #endif 169 assert(SndDChunk.offset == 0); 170 assert(SndDChunk.blockSize == 0); 171 soundPointer = ftell(ifile); 172 fseek(ifile, offset + Header.ckSize, SEEK_SET); 173 break; 174 175 case 0x4150504c: // APPL 176 offset = ftell(ifile); 177 fread(&ts, sizeof(u32), 1, ifile); 178 BSWAP32(ts) 179 if (ts == 0x73746f63) // stoc 180 { 181 ChunkName = ReadPString(ifile); 182 if (strcmp("VADPCMCODES", ChunkName) == 0) 183 { 184 fread(&version, sizeof(s16), 1, ifile); 185 BSWAP16(version) 186 if (version != 1) 187 { 188 fprintf(stderr, "Non-identical codebook chunk versions\n"); 189 } 190 readaifccodebook(ifile, &coefTable, &order, &npredictors); 191 } 192 else if (strcmp("VADPCMLOOPS", ChunkName) == 0) 193 { 194 fread(&version, sizeof(s16), 1, ifile); 195 BSWAP16(version) 196 if (version != 1) 197 { 198 fprintf(stderr, "Non-identical loop chunk versions\n"); 199 } 200 aloops = readlooppoints(ifile, &nloops); 201 } 202 } 203 fseek(ifile, offset + Header.ckSize, SEEK_SET); 204 break; 205 206 default: 207 // We don't understand this chunk. Skip it. 208 fseek(ifile, Header.ckSize, SEEK_CUR); 209 break; 210 } 211 } 212 213 if (coefTable == NULL) 214 { 215 // @bug should use progname; argv[0] may be an option 216 fprintf(stderr, "%s: Codebook missing from bitstream [%s]\n", argv[0], argv[1]); 217 exit(1); 218 } 219 220 outp = malloc(16 * sizeof(s32)); 221 for (i = 0; i < order; i++) 222 { 223 outp[15 - i] = 0; 224 } 225 226 fseek(ifile, soundPointer, SEEK_SET); 227 if (doloop && nloops > 0) 228 { 229 #ifndef __sgi 230 struct sigaction int_act; 231 int_act.sa_flags = SA_RESTART; 232 int_act.sa_handler = int_handler; 233 sigemptyset(&int_act.sa_mask); 234 #endif 235 236 sigaction(SIGINT, &int_act, NULL); 237 flags = fcntl(STDIN_FILENO, F_GETFL, 0); 238 flags |= FNDELAY; 239 fcntl(STDIN_FILENO, F_SETFL, flags); 240 for (i = 0; i < nloops; i++) 241 { 242 while (currPos < aloops[i].end) 243 { 244 left = aloops[i].end - currPos; 245 vdecodeframe(ifile, outp, order, coefTable); 246 writeout(stdout, left < 16 ? left : 16, outp, outp, 1); 247 currPos += 16; 248 } 249 250 while (read(STDIN_FILENO, &cc, 1) == 0) 251 { 252 framePos = (aloops[i].start >> 4) + 1; 253 fseek(ifile, (framePos * 9) + soundPointer, SEEK_SET); 254 for (j = 0; j < 16; j++) 255 { 256 outp[j] = aloops[i].state[j]; 257 } 258 loopBegin = aloops[i].start & 0xf; 259 writeout(stdout, 16 - loopBegin, outp + loopBegin, outp + loopBegin, 1); 260 currPos = framePos * 16; 261 while (currPos < aloops[i].end) 262 { 263 left = aloops[i].end - currPos; 264 vdecodeframe(ifile, outp, order, coefTable); 265 writeout(stdout, left < 16 ? left : 16, outp, outp, 1); 266 currPos += 16; 267 } 268 } 269 270 left = 16 - left; 271 if (left != 0) 272 { 273 writeout(stdout, left, &outp[left], &outp[left], 1); 274 } 275 276 while (currPos < nSamples) 277 { 278 vdecodeframe(ifile, outp, order, coefTable); 279 left = nSamples - currPos; 280 writeout(stdout, left < 16 ? left : 16, outp, outp, 1); 281 currPos += 16; 282 } 283 284 flags = fcntl(STDIN_FILENO, F_GETFL, 0); 285 flags &= ~FNDELAY; 286 fcntl(STDIN_FILENO, F_SETFL, flags); 287 } 288 } 289 else 290 { 291 while (currPos < nSamples) 292 { 293 vdecodeframe(ifile, outp, order, coefTable); 294 writeout(stdout, 16, outp, outp, 1); 295 currPos += 16; 296 } 297 } 298 299 fclose(ifile); 300 return 0; 301 }