chiark / gitweb /
Consistency check for finished tracks.
[disorder] / server / decode-mp3.c
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 */