Cosmetics
[dormin.git] / adpcm.c
blobeef11e5fd5ae660b524795109c799e4dff05da31
1 /* Based on:
3 PSX VAG-Packer, hacked by bITmASTER@bigfoot.com
5 v0.1
6 */
8 /* Block interleave figured out by Antti Huovilainen. */
10 /* Usage:
11 $ cc -o adpcm adpcm.c
12 $ dd if=/path/to/sotc/dvd/XAD \
13 | ./adpcm | sox -t raw -r 22050 -s -w -c 2 - -t ossdsp /dev/dsp
16 #include <stdio.h>
17 #include <stdlib.h>
19 static const double f[5][2] = { { 0.0, 0.0 },
20 { 60.0 / 64.0, 0.0 },
21 { 115.0 / 64.0, -52.0 / 64.0 },
22 { 98.0 / 64.0, -55.0 / 64.0 },
23 { 122.0 / 64.0, -60.0 / 64.0 } };
25 int main (void)
27 int predict_nr, shift_factor, flags;
28 int i, block = 0;
29 unsigned int d;
30 int s;
31 struct {
32 double s_1;
33 double s_2;
34 double s_11;
35 double s_21;
36 } ctxs[2] = {0}, *ctx = ctxs;
37 signed short int left[28*64], right[28*64];
38 signed short int *chan = left;
39 double samples[28];
41 for (;;) {
42 signed char data[16];
44 if (fread (data, 16, 1, stdin) != 1) {
45 perror ("fread");
46 exit (EXIT_FAILURE);
49 if (data[1] == 7) break;
51 predict_nr = data[0];
52 shift_factor = predict_nr & 0xf;
53 predict_nr >>= 4;
55 for (i = 0; i < 28; i += 2) {
56 d = data[i / 2 + 2];
57 s = (d & 0xf) << 12;
58 if (s & 0x8000)
59 s |= 0xffff0000;
60 samples[i] = (double) (s >> shift_factor);
61 s = (d & 0xf0) << 8;
62 if (s & 0x8000)
63 s |= 0xffff0000;
64 samples[i+1] = (double) (s >> shift_factor);
67 for (i = 0; i < 28; i++) {
68 samples[i] += ctx->s_1 * f[predict_nr][0] + ctx->s_2 * f[predict_nr][1];
69 ctx->s_2 = ctx->s_1;
70 ctx->s_1 = samples[i];
71 d = (int) (samples[i] + 0.5);
72 chan[i + block*28] = d;
75 block++;
76 if (block == 64) {
77 if (chan == left) {
78 chan = right;
79 ctx = &ctxs[1];
81 else {
82 chan = left;
83 ctx = &ctxs[0];
85 for (i = 0; i < 28*64; ++i) {
86 fputc (left[i] >> 8, stdout);
87 fputc (left[i], stdout);
88 fputc (right[i] >> 8, stdout);
89 fputc (right[i], stdout);
92 block = 0;
95 return 0;