16298
|
1 /**
|
|
2 * convert D-Cinema Audio (probably SMPTE 302M) to a
|
|
3 * wav file that MPlayer can play.
|
|
4 * Usage: 302m_convert <infile> <outfile>
|
|
5 */
|
|
6 #include <stdlib.h>
|
|
7 #include <stdio.h>
|
|
8 #include <inttypes.h>
|
|
9 #include <byteswap.h>
|
|
10 #define le2me_32(x) (x)
|
|
11 #define le2me_16(x) (x)
|
|
12 #define be2me_16(x) bswap_16(x)
|
|
13
|
|
14 // From MPlayer libao/ao_pcm.c
|
|
15 #define WAV_ID_RIFF 0x46464952 /* "RIFF" */
|
|
16 #define WAV_ID_WAVE 0x45564157 /* "WAVE" */
|
|
17 #define WAV_ID_FMT 0x20746d66 /* "fmt " */
|
|
18 #define WAV_ID_DATA 0x61746164 /* "data" */
|
|
19 #define WAV_ID_PCM 0x0001
|
|
20
|
|
21 struct WaveHeader {
|
|
22 uint32_t riff;
|
|
23 uint32_t file_length;
|
|
24 uint32_t wave;
|
|
25 uint32_t fmt;
|
|
26 uint32_t fmt_length;
|
|
27 uint16_t fmt_tag;
|
|
28 uint16_t channels;
|
|
29 uint32_t sample_rate;
|
|
30 uint32_t bytes_per_second;
|
|
31 uint16_t block_align;
|
|
32 uint16_t bits;
|
|
33 uint32_t data;
|
|
34 uint32_t data_length;
|
|
35 };
|
|
36
|
|
37 static struct WaveHeader wavhdr = {
|
|
38 le2me_32(WAV_ID_RIFF),
|
|
39 le2me_32(0x7fffffff),
|
|
40 le2me_32(WAV_ID_WAVE),
|
|
41 le2me_32(WAV_ID_FMT),
|
|
42 le2me_32(16),
|
|
43 le2me_16(WAV_ID_PCM),
|
|
44 le2me_16(6),
|
|
45 le2me_32(96000),
|
|
46 le2me_32(1728000),
|
|
47 le2me_16(18),
|
|
48 le2me_16(24),
|
|
49 le2me_32(WAV_ID_DATA),
|
|
50 le2me_32(0x7fffffff),
|
|
51 };
|
|
52
|
|
53 // this format is completely braindead, and this bitorder
|
|
54 // is the result of pure guesswork (counting how often
|
|
55 // the bits flip), so it might be wrong.
|
|
56 void fixup(unsigned char *in_, unsigned char *out) {
|
|
57 int i;
|
|
58 unsigned char in[3] = {in_[0], in_[1], in_[2]};
|
|
59 unsigned char sync = in[2] & 0x0f; // sync flags
|
|
60 in[2] >>= 4;
|
|
61 out[2] = 0;
|
|
62 for (i = 0; i < 4; i++) {
|
|
63 out[2] <<= 1;
|
|
64 out[2] |= in[2] & 1;
|
|
65 in[2] >>= 1;
|
|
66 }
|
|
67 for (i = 0; i < 4; i++) {
|
|
68 out[2] <<= 1;
|
|
69 out[2] |= in[1] & 1;
|
|
70 in[1] >>= 1;
|
|
71 }
|
|
72 out[1] = 0;
|
|
73 for (i = 0; i < 4; i++) {
|
|
74 out[1] <<= 1;
|
|
75 out[1] |= in[1] & 1;
|
|
76 in[1] >>= 1;
|
|
77 }
|
|
78 for (i = 0; i < 4; i++) {
|
|
79 out[1] <<= 1;
|
|
80 out[1] |= in[0] & 1;
|
|
81 in[0] >>= 1;
|
|
82 }
|
|
83 out[0] = 0;
|
|
84 for (i = 0; i < 4; i++) {
|
|
85 out[0] <<= 1;
|
|
86 out[0] |= in[0] & 1;
|
|
87 in[0] >>= 1;
|
|
88 }
|
|
89 out[0] <<= 4;
|
|
90 out[0] |= sync; // sync flags go into lowest bits
|
|
91 // it seems those might also contain audio data,
|
|
92 // don't know if this is the right order then
|
|
93 // these might be also useful to detect the number
|
|
94 // of channels in case there are files with != 6 channels
|
|
95 }
|
|
96
|
|
97 int main(int argc, char *argv[]) {
|
|
98 FILE *in = fopen(argv[1], "r");
|
|
99 FILE *out = fopen(argv[2], "w");
|
|
100 int i;
|
|
101 uint16_t blocklen, unknown;
|
|
102 unsigned char *block;
|
|
103 if (!in) {
|
|
104 printf("Could not open %s for reading\n", argv[1]);
|
|
105 return EXIT_FAILURE;
|
|
106 }
|
|
107 if (!out) {
|
|
108 printf("Could not open %s for writing\n", argv[2]);
|
|
109 return EXIT_FAILURE;
|
|
110 }
|
|
111 fwrite(&wavhdr, 1, sizeof(wavhdr), out);
|
|
112 do {
|
|
113 fread(&blocklen, 2, 1, in);
|
|
114 blocklen = be2me_16(blocklen);
|
|
115 fread(&unknown, 2, 1, in);
|
|
116 block = malloc(blocklen);
|
|
117 blocklen = fread(block, 1, blocklen, in);
|
|
118 for (i = 0; i < blocklen; i += 3)
|
|
119 fixup(&block[i], &block[i]);
|
|
120 fwrite(block, 1, blocklen, out);
|
|
121 free(block);
|
|
122 } while (!feof(in));
|
|
123 return EXIT_SUCCESS;
|
|
124 }
|
|
125
|