Commit | Line | Data |
---|---|---|
8d399b30 RK |
1 | /* |
2 | * This file is part of DisOrder | |
3 | * Copyright (C) 2007-2010 Richard Kettlewell | |
4 | * | |
5 | * This program is free software: you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation, either version 3 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 | */ | |
18 | /** @file server/decode-mp3.c | |
19 | * @brief Decode MP3 files. | |
20 | */ | |
21 | #include "decode.h" | |
22 | #include <mad.h> | |
23 | ||
24 | static struct hreader input[1]; | |
25 | ||
26 | /** @brief Dithering state | |
27 | * Filched from mpg321, which credits it to Robert Leslie */ | |
28 | struct audio_dither { | |
29 | mad_fixed_t error[3]; | |
30 | mad_fixed_t random; | |
31 | }; | |
32 | ||
33 | /** @brief 32-bit PRNG | |
34 | * Filched from mpg321, which credits it to Robert Leslie */ | |
35 | static inline unsigned long prng(unsigned long state) | |
36 | { | |
37 | return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL; | |
38 | } | |
39 | ||
40 | /** @brief Generic linear sample quantize and dither routine | |
41 | * Filched from mpg321, which credits it to Robert Leslie */ | |
42 | static long audio_linear_dither(mad_fixed_t sample, | |
43 | struct audio_dither *dither) { | |
44 | unsigned int scalebits; | |
45 | mad_fixed_t output, mask, rnd; | |
46 | const int bits = 16; | |
47 | ||
48 | enum { | |
49 | MIN = -MAD_F_ONE, | |
50 | MAX = MAD_F_ONE - 1 | |
51 | }; | |
52 | ||
53 | /* noise shape */ | |
54 | sample += dither->error[0] - dither->error[1] + dither->error[2]; | |
55 | ||
56 | dither->error[2] = dither->error[1]; | |
57 | dither->error[1] = dither->error[0] / 2; | |
58 | ||
59 | /* bias */ | |
60 | output = sample + (1L << (MAD_F_FRACBITS + 1 - bits - 1)); | |
61 | ||
62 | scalebits = MAD_F_FRACBITS + 1 - bits; | |
63 | mask = (1L << scalebits) - 1; | |
64 | ||
65 | /* dither */ | |
66 | rnd = prng(dither->random); | |
67 | output += (rnd & mask) - (dither->random & mask); | |
68 | ||
69 | dither->random = rnd; | |
70 | ||
71 | /* clip */ | |
72 | if (output > MAX) { | |
73 | output = MAX; | |
74 | ||
75 | if (sample > MAX) | |
76 | sample = MAX; | |
77 | } | |
78 | else if (output < MIN) { | |
79 | output = MIN; | |
80 | ||
81 | if (sample < MIN) | |
82 | sample = MIN; | |
83 | } | |
84 | ||
85 | /* quantize */ | |
86 | output &= ~mask; | |
87 | ||
88 | /* error feedback */ | |
89 | dither->error[0] = sample - output; | |
90 | ||
91 | /* scale */ | |
92 | return output >> scalebits; | |
93 | } | |
94 | ||
95 | /** @brief MP3 output callback */ | |
96 | static enum mad_flow mp3_output(void attribute((unused)) *data, | |
97 | struct mad_header const *header, | |
98 | struct mad_pcm *pcm) { | |
99 | size_t n = pcm->length; | |
100 | const mad_fixed_t *l = pcm->samples[0], *r = pcm->samples[1]; | |
101 | static struct audio_dither ld[1], rd[1]; | |
102 | ||
103 | output_header(header->samplerate, | |
104 | pcm->channels, | |
105 | 16, | |
106 | 2 * pcm->channels * pcm->length, | |
107 | ENDIAN_BIG); | |
108 | switch(pcm->channels) { | |
109 | case 1: | |
110 | while(n--) | |
111 | output_16(audio_linear_dither(*l++, ld)); | |
112 | break; | |
113 | case 2: | |
114 | while(n--) { | |
115 | output_16(audio_linear_dither(*l++, ld)); | |
116 | output_16(audio_linear_dither(*r++, rd)); | |
117 | } | |
118 | break; | |
119 | } | |
120 | return MAD_FLOW_CONTINUE; | |
121 | } | |
122 | ||
123 | /** @brief MP3 input callback */ | |
124 | static enum mad_flow mp3_input(void attribute((unused)) *data, | |
125 | struct mad_stream *stream) { | |
126 | int used, remain, n; | |
127 | ||
128 | /* libmad requires its caller to do ALL the buffering work, including coping | |
129 | * with partial frames. Given that it appears to be completely undocumented | |
130 | * you could perhaps be forgiven for not discovering this... */ | |
131 | if(input_count) { | |
132 | /* Compute total number of bytes consumed */ | |
133 | used = (char *)stream->next_frame - input_buffer; | |
134 | /* Compute number of bytes left to consume */ | |
135 | remain = input_count - used; | |
136 | memmove(input_buffer, input_buffer + used, remain); | |
137 | } else { | |
138 | remain = 0; | |
139 | } | |
140 | /* Read new data */ | |
141 | n = hreader_read(input, | |
142 | input_buffer + remain, | |
143 | (sizeof input_buffer) - remain); | |
144 | if(n < 0) | |
145 | disorder_fatal(errno, "reading from %s", path); | |
146 | /* Compute total number of bytes available */ | |
147 | input_count = remain + n; | |
148 | if(input_count) | |
149 | mad_stream_buffer(stream, (unsigned char *)input_buffer, input_count); | |
150 | if(n) | |
151 | return MAD_FLOW_CONTINUE; | |
152 | else | |
153 | return MAD_FLOW_STOP; | |
154 | } | |
155 | ||
156 | /** @brief MP3 error callback */ | |
157 | static enum mad_flow mp3_error(void attribute((unused)) *data, | |
158 | struct mad_stream *stream, | |
159 | struct mad_frame attribute((unused)) *frame) { | |
160 | if(0) | |
161 | /* Just generates pointless verbosity l-( */ | |
162 | disorder_error(0, "decoding %s: %s (%#04x)", | |
163 | path, mad_stream_errorstr(stream), stream->error); | |
164 | return MAD_FLOW_CONTINUE; | |
165 | } | |
166 | ||
167 | /** @brief MP3 decoder */ | |
168 | void decode_mp3(void) { | |
169 | struct mad_decoder mad[1]; | |
170 | ||
171 | if(hreader_init(path, input)) | |
172 | disorder_fatal(errno, "opening %s", path); | |
173 | mad_decoder_init(mad, 0/*data*/, mp3_input, 0/*header*/, 0/*filter*/, | |
174 | mp3_output, mp3_error, 0/*message*/); | |
175 | if(mad_decoder_run(mad, MAD_DECODER_MODE_SYNC)) | |
176 | exit(1); | |
177 | mad_decoder_finish(mad); | |
178 | } | |
179 | ||
180 | /* | |
181 | Local Variables: | |
182 | c-basic-offset:2 | |
183 | comment-column:40 | |
184 | fill-column:79 | |
185 | indent-tabs-mode:nil | |
186 | End: | |
187 | */ |