chiark / gitweb /
update debian build/run deps
[disorder] / server / decode.c
1 /*
2  * This file is part of DisOrder
3  * Copyright (C) 2007 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 2 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, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * 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, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA
19  */
20 /** @file server/decode.c
21  * @brief General-purpose decoder for use by speaker process
22  */
23
24 #include <config.h>
25 #include "types.h"
26
27 #include <getopt.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <errno.h>
31 #include <stdlib.h>
32 #include <locale.h>
33 #include <assert.h>
34 #include <fnmatch.h>
35 #include <mad.h>
36 #include <vorbis/vorbisfile.h>
37
38 #include "log.h"
39 #include "syscalls.h"
40 #include "defs.h"
41 #include "wav.h"
42 #include "speaker-protocol.h"
43
44 /** @brief Encoding lookup table type */
45 struct decoder {
46   /** @brief Glob pattern matching file */
47   const char *pattern;
48   /** @brief Decoder function */
49   void (*decode)(void);
50 };
51
52 /** @brief Input file */
53 static int inputfd;
54
55 /** @brief Output file */
56 static FILE *outputfp;
57
58 /** @brief Filename */
59 static const char *path;
60
61 /** @brief Input buffer */
62 static char buffer[1048576];
63
64 /** @brief Open the input file */
65 static void open_input(void) {
66   if((inputfd = open(path, O_RDONLY)) < 0)
67     fatal(errno, "opening %s", path);
68 }
69
70 /** @brief Fill the buffer
71  * @return Number of bytes read
72  */
73 static size_t fill(void) {
74   int n = read(inputfd, buffer, sizeof buffer);
75
76   if(n < 0)
77     fatal(errno, "reading from %s", path);
78   return n;
79 }
80
81 /** @brief Write a 16-bit word in bigendian format */
82 static inline void output_16(uint16_t n) {
83   if(putc(n >> 8, outputfp) < 0
84      || putc(n & 0xFF, outputfp) < 0)
85     fatal(errno, "decoding %s: output error", path);
86 }
87
88 /** @brief Write the header
89  * If called more than once, either does nothing (if you kept the same
90  * output encoding) or fails (if you changed it).
91  */
92 static void output_header(int rate,
93                           int channels,
94                           int bits,
95                           int nbytes,
96                           int endian) {
97   struct stream_header header;
98
99   header.rate = rate;
100   header.bits = bits;
101   header.channels = channels;
102   header.endian = endian;
103   header.nbytes = nbytes;
104   if(fwrite(&header, sizeof header, 1, outputfp) < 1)
105     fatal(errno, "decoding %s: writing format header", path);
106 }
107
108 /** @brief Dithering state
109  * Filched from mpg321, which credits it to Robert Leslie */
110 struct audio_dither {
111   mad_fixed_t error[3];
112   mad_fixed_t random;
113 };
114
115 /** @brief 32-bit PRNG
116  * Filched from mpg321, which credits it to Robert Leslie */
117 static inline unsigned long prng(unsigned long state)
118 {
119   return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
120 }
121
122 /** @brief Generic linear sample quantize and dither routine
123  * Filched from mpg321, which credits it to Robert Leslie */
124 #define bits 16
125 static long audio_linear_dither(mad_fixed_t sample,
126                                 struct audio_dither *dither) {
127   unsigned int scalebits;
128   mad_fixed_t output, mask, rnd;
129
130   enum {
131     MIN = -MAD_F_ONE,
132     MAX =  MAD_F_ONE - 1
133   };
134
135   /* noise shape */
136   sample += dither->error[0] - dither->error[1] + dither->error[2];
137
138   dither->error[2] = dither->error[1];
139   dither->error[1] = dither->error[0] / 2;
140
141   /* bias */
142   output = sample + (1L << (MAD_F_FRACBITS + 1 - bits - 1));
143
144   scalebits = MAD_F_FRACBITS + 1 - bits;
145   mask = (1L << scalebits) - 1;
146
147   /* dither */
148   rnd  = prng(dither->random);
149   output += (rnd & mask) - (dither->random & mask);
150
151   dither->random = rnd;
152
153   /* clip */
154   if (output > MAX) {
155     output = MAX;
156
157     if (sample > MAX)
158       sample = MAX;
159   }
160   else if (output < MIN) {
161     output = MIN;
162
163     if (sample < MIN)
164       sample = MIN;
165   }
166
167   /* quantize */
168   output &= ~mask;
169
170   /* error feedback */
171   dither->error[0] = sample - output;
172
173   /* scale */
174   return output >> scalebits;
175 }
176 #undef bits
177
178 /** @brief MP3 output callback */
179 static enum mad_flow mp3_output(void attribute((unused)) *data,
180                                 struct mad_header const *header,
181                                 struct mad_pcm *pcm) {
182   size_t n = pcm->length;
183   const mad_fixed_t *l = pcm->samples[0], *r = pcm->samples[1];
184   static struct audio_dither ld[1], rd[1];
185
186   output_header(header->samplerate,
187                 pcm->channels,
188                 16,
189                 2 * pcm->channels * pcm->length,
190                 ENDIAN_BIG);
191   switch(pcm->channels) {
192   case 1:
193     while(n--)
194       output_16(audio_linear_dither(*l++, ld));
195     break;
196   case 2:
197     while(n--) {
198       output_16(audio_linear_dither(*l++, ld));
199       output_16(audio_linear_dither(*r++, rd));
200     }
201     break;
202   default:
203     fatal(0, "decoding %s: unsupported channel count %d", path, pcm->channels);
204   }
205   return MAD_FLOW_CONTINUE;
206 }
207
208 /** @brief MP3 input callback */
209 static enum mad_flow mp3_input(void attribute((unused)) *data,
210                                struct mad_stream *stream) {
211   const size_t n = fill();
212
213   if(!n)
214     return MAD_FLOW_STOP;
215   mad_stream_buffer(stream, (unsigned char *)buffer, n);
216   return MAD_FLOW_CONTINUE;
217 }
218
219
220 /** @brief MP3 error callback */
221 static enum mad_flow mp3_error(void attribute((unused)) *data,
222                                struct mad_stream *stream,
223                                struct mad_frame attribute((unused)) *frame) {
224   if(0)
225     /* Just generates pointless verbosity l-( */
226     error(0, "decoding %s: %s (%#04x)",
227           path, mad_stream_errorstr(stream), stream->error);
228   return MAD_FLOW_CONTINUE;
229 }
230
231 /** @brief MP3 decoder */
232 static void decode_mp3(void) {
233   struct mad_decoder mad[1];
234
235   open_input();
236   mad_decoder_init(mad, 0/*data*/, mp3_input, 0/*header*/, 0/*filter*/,
237                    mp3_output, mp3_error, 0/*message*/);
238   if(mad_decoder_run(mad, MAD_DECODER_MODE_SYNC))
239     exit(1);
240   mad_decoder_finish(mad);
241 }
242
243 /** @brief OGG decoder */
244 static void decode_ogg(void) {
245   FILE *fp;
246   OggVorbis_File vf[1];
247   int err;
248   long n;
249   int bitstream;
250   vorbis_info *vi;
251
252   if(!(fp = fopen(path, "rb")))
253     fatal(errno, "cannot open %s", path);
254   /* There doesn't seem to be any standard function for mapping the error codes
255    * to strings l-( */
256   if((err = ov_open(fp, vf, 0/*initial*/, 0/*ibytes*/)))
257     fatal(0, "ov_fopen %s: %d", path, err);
258   if(!(vi = ov_info(vf, 0/*link*/)))
259     fatal(0, "ov_info %s: failed", path);
260   while((n = ov_read(vf, buffer, sizeof buffer, 1/*bigendianp*/,
261                      2/*bytes/word*/, 1/*signed*/, &bitstream))) {
262     if(n < 0)
263       fatal(0, "ov_read %s: %ld", path, n);
264     if(bitstream > 0)
265       fatal(0, "only single-bitstream ogg files are supported");
266     output_header(vi->rate, vi->channels, 16/*bits*/, n, ENDIAN_BIG);
267     if(fwrite(buffer, 1, n, outputfp) < (size_t)n)
268       fatal(errno, "decoding %s: writing sample data", path);
269   }
270 }
271
272 /** @brief Sample data callback used by decode_wav() */
273 static int wav_write(struct wavfile attribute((unused)) *f,
274                      const char *data,
275                      size_t nbytes,
276                      void attribute((unused)) *u) {
277   if(fwrite(data, 1, nbytes, outputfp) < nbytes)
278     fatal(errno, "decoding %s: writing sample data", path);
279   return 0;
280 }
281
282 /** @brief WAV file decoder */
283 static void decode_wav(void) {
284   struct wavfile f[1];
285   int err;
286
287   if((err = wav_init(f, path)))
288     fatal(err, "opening %s", path);
289   if(f->bits % 8)
290     fatal(err, "%s: unsupported byte size %d", path, f->bits);
291   output_header(f->rate, f->channels, f->bits, f->datasize, ENDIAN_LITTLE);
292   if((err = wav_data(f, wav_write, 0)))
293     fatal(err, "error decoding %s", path);
294 }
295
296 /** @brief Lookup table of decoders */
297 static const struct decoder decoders[] = {
298   { "*.mp3", decode_mp3 },
299   { "*.MP3", decode_mp3 },
300   { "*.ogg", decode_ogg },
301   { "*.OGG", decode_ogg },
302   { "*.wav", decode_wav },
303   { "*.WAV", decode_wav },
304   { 0, 0 }
305 };
306
307 static const struct option options[] = {
308   { "help", no_argument, 0, 'h' },
309   { "version", no_argument, 0, 'V' },
310   { 0, 0, 0, 0 }
311 };
312
313 /* Display usage message and terminate. */
314 static void help(void) {
315   xprintf("Usage:\n"
316           "  disorder-decode [OPTIONS] PATH\n"
317           "Options:\n"
318           "  --help, -h              Display usage message\n"
319           "  --version, -V           Display version number\n"
320           "\n"
321           "Audio decoder for DisOrder.  Only intended to be used by speaker\n"
322           "process, not for normal users.\n");
323   xfclose(stdout);
324   exit(0);
325 }
326
327 /* Display version number and terminate. */
328 static void version(void) {
329   xprintf("disorder-decode version %s\n", disorder_version_string);
330   xfclose(stdout);
331   exit(0);
332 }
333
334 int main(int argc, char **argv) {
335   int n;
336   const char *e;
337
338   set_progname(argv);
339   if(!setlocale(LC_CTYPE, "")) fatal(errno, "calling setlocale");
340   while((n = getopt_long(argc, argv, "hV", options, 0)) >= 0) {
341     switch(n) {
342     case 'h': help();
343     case 'V': version();
344     default: fatal(0, "invalid option");
345     }
346   }
347   if(optind >= argc)
348     fatal(0, "missing filename");
349   if(optind + 1 < argc)
350     fatal(0, "excess arguments");
351   if((e = getenv("DISORDER_RAW_FD"))) {
352     if(!(outputfp = fdopen(atoi(e), "wb")))
353       fatal(errno, "fdopen");
354   } else
355     outputfp = stdout;
356   path = argv[optind];
357   for(n = 0;
358       decoders[n].pattern
359         && fnmatch(decoders[n].pattern, path, 0) != 0;
360       ++n)
361     ;
362   if(!decoders[n].pattern)
363     fatal(0, "cannot determine file type for %s", path);
364   decoders[n].decode();
365   xfclose(outputfp);
366   return 0;
367 }
368
369 /*
370 Local Variables:
371 c-basic-offset:2
372 comment-column:40
373 fill-column:79
374 indent-tabs-mode:nil
375 End:
376 */