1 /*
2  * madplay - MPEG audio decoder and player
3  * Copyright (C) 2000-2004 Robert Leslie
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,
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, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * $Id: audio.c,v 1.36 2004/01/23 09:41:31 rob Exp $
20  */
21 
22 # ifdef HAVE_CONFIG_H
23 #  include "config.h"
24 # endif
25 
26 # include "global.h"
27 
28 # include <string.h>
29 # include <mad.h>
30 
31 # include "audio.h"
32 
33 char const *audio_error;
34 
35 static struct audio_dither left_dither, right_dither;
36 
37 # if defined(_MSC_VER)
38 #  pragma warning(disable: 4550)  /* expression evaluates to a function which
39 				     is missing an argument list */
40 # endif
41 
42 /*
43  * NAME:	audio_output()
44  * DESCRIPTION: choose an audio output module from a specifier pathname
45  */
audio_output(char const ** path)46 audio_ctlfunc_t *audio_output(char const **path)
47 {
48   char const *ext;
49   int i;
50 
51   struct map {
52     char const *name;
53     audio_ctlfunc_t *module;
54   };
55 
56   struct map const prefixes[] = {
57     { "cdda", audio_cdda },
58     { "aiff", audio_aiff },
59     { "wave", audio_wave },
60     { "wav",  audio_wave },
61     { "snd",  audio_snd  },
62     { "au",   audio_snd  },
63     { "raw",  audio_raw  },
64     { "pcm",  audio_raw  },
65     { "hex",  audio_hex  },
66 # if defined(HAVE_LIBESD)
67     { "esd",  audio_esd  },
68 # endif
69 # if defined(HAVE_LIBAUDIO)
70     { "nas",  audio_nas  },
71 # endif
72     { "null", audio_null },
73     { "nul",  audio_null }
74   };
75 
76   struct map const extensions[] = {
77     { "cdr",  audio_cdda },
78     { "cda",  audio_cdda },
79     { "cdda", audio_cdda },
80     { "aif",  audio_aiff },
81     { "aiff", audio_aiff },
82     { "wav",  audio_wave },
83     { "snd",  audio_snd  },
84     { "au",   audio_snd  },
85     { "raw",  audio_raw  },
86     { "pcm",  audio_raw  },
87     { "out",  audio_raw  },
88     { "bin",  audio_raw  },
89     { "hex",  audio_hex  },
90     { "txt",  audio_hex  }
91   };
92 
93   if (path == 0)
94     return AUDIO_DEFAULT;
95 
96   /* check for prefix specifier */
97 
98   ext = strchr(*path, ':');
99   if (ext) {
100     char const *type;
101 
102     type  = *path;
103     *path = ext + 1;
104 
105     for (i = 0; i < sizeof(prefixes) / sizeof(prefixes[0]); ++i) {
106       if (strncasecmp(type, prefixes[i].name, ext - type) == 0 &&
107 	  strlen(prefixes[i].name) == ext - type)
108 	return prefixes[i].module;
109     }
110 
111     *path = type;
112     return 0;
113   }
114 
115   if (strcmp(*path, "/dev/null") == 0)
116     return audio_null;
117 
118   if (strncmp(*path, "/dev/", 5) == 0)
119     return AUDIO_DEFAULT;
120 
121   /* check for file extension specifier */
122 
123   ext = strrchr(*path, '.');
124   if (ext) {
125     ++ext;
126 
127     for (i = 0; i < sizeof(extensions) / sizeof(extensions[0]); ++i) {
128       if (strcasecmp(ext, extensions[i].name) == 0)
129 	return extensions[i].module;
130     }
131   }
132 
133   return 0;
134 }
135 
136 /*
137  * NAME:	audio_control_init()
138  * DESCRIPTION:	initialize an audio control structure
139  */
audio_control_init(union audio_control * control,enum audio_command command)140 void audio_control_init(union audio_control *control,
141 			enum audio_command command)
142 {
143   switch (control->command = command) {
144   case AUDIO_COMMAND_INIT:
145     control->init.path = 0;
146     break;
147 
148   case AUDIO_COMMAND_CONFIG:
149     control->config.channels  = 0;
150     control->config.speed     = 0;
151     control->config.precision = 0;
152     break;
153 
154   case AUDIO_COMMAND_PLAY:
155     control->play.nsamples   = 0;
156     control->play.samples[0] = 0;
157     control->play.samples[1] = 0;
158     control->play.mode       = AUDIO_MODE_DITHER;
159     control->play.stats      = 0;
160     break;
161 
162   case AUDIO_COMMAND_STOP:
163     control->stop.flush = 0;
164     break;
165 
166   case AUDIO_COMMAND_FINISH:
167     break;
168   }
169 }
170 
171 /*
172  * NAME:	clip()
173  * DESCRIPTION:	gather signal statistics while clipping
174  */
175 static inline
clip(mad_fixed_t * sample,struct audio_stats * stats)176 void clip(mad_fixed_t *sample, struct audio_stats *stats)
177 {
178   enum {
179     MIN = -MAD_F_ONE,
180     MAX =  MAD_F_ONE - 1
181   };
182 
183   if (*sample >= stats->peak_sample) {
184     if (*sample > MAX) {
185       ++stats->clipped_samples;
186       if (*sample - MAX > stats->peak_clipping)
187 	stats->peak_clipping = *sample - MAX;
188 
189       *sample = MAX;
190     }
191     stats->peak_sample = *sample;
192   }
193   else if (*sample < -stats->peak_sample) {
194     if (*sample < MIN) {
195       ++stats->clipped_samples;
196       if (MIN - *sample > stats->peak_clipping)
197 	stats->peak_clipping = MIN - *sample;
198 
199       *sample = MIN;
200     }
201     stats->peak_sample = -*sample;
202   }
203 }
204 
205 /*
206  * NAME:	audio_linear_round()
207  * DESCRIPTION:	generic linear sample quantize routine
208  */
209 # if defined(_MSC_VER)
210 extern  /* needed to satisfy bizarre MSVC++ interaction with inline */
211 # endif
212 inline
audio_linear_round(unsigned int bits,mad_fixed_t sample,struct audio_stats * stats)213 signed long audio_linear_round(unsigned int bits, mad_fixed_t sample,
214 			       struct audio_stats *stats)
215 {
216   /* round */
217   sample += (1L << (MAD_F_FRACBITS - bits));
218 
219   /* clip */
220   clip(&sample, stats);
221 
222   /* quantize and scale */
223   return sample >> (MAD_F_FRACBITS + 1 - bits);
224 }
225 
226 /*
227  * NAME:	prng()
228  * DESCRIPTION:	32-bit pseudo-random number generator
229  */
230 static inline
prng(unsigned long state)231 unsigned long prng(unsigned long state)
232 {
233   return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
234 }
235 
236 /*
237  * NAME:	audio_linear_dither()
238  * DESCRIPTION:	generic linear sample quantize and dither routine
239  */
240 # if defined(_MSC_VER)
241 extern  /* needed to satisfy bizarre MSVC++ interaction with inline */
242 # endif
243 inline
audio_linear_dither(unsigned int bits,mad_fixed_t sample,struct audio_dither * dither,struct audio_stats * stats)244 signed long audio_linear_dither(unsigned int bits, mad_fixed_t sample,
245 				struct audio_dither *dither,
246 				struct audio_stats *stats)
247 {
248   unsigned int scalebits;
249   mad_fixed_t output, mask, random;
250 
251   enum {
252     MIN = -MAD_F_ONE,
253     MAX =  MAD_F_ONE - 1
254   };
255 
256   /* noise shape */
257   sample += dither->error[0] - dither->error[1] + dither->error[2];
258 
259   dither->error[2] = dither->error[1];
260   dither->error[1] = dither->error[0] / 2;
261 
262   /* bias */
263   output = sample + (1L << (MAD_F_FRACBITS + 1 - bits - 1));
264 
265   scalebits = MAD_F_FRACBITS + 1 - bits;
266   mask = (1L << scalebits) - 1;
267 
268   /* dither */
269   random  = prng(dither->random);
270   output += (random & mask) - (dither->random & mask);
271 
272   dither->random = random;
273 
274   /* clip */
275   if (output >= stats->peak_sample) {
276     if (output > MAX) {
277       ++stats->clipped_samples;
278       if (output - MAX > stats->peak_clipping)
279 	stats->peak_clipping = output - MAX;
280 
281       output = MAX;
282 
283       if (sample > MAX)
284 	sample = MAX;
285     }
286     stats->peak_sample = output;
287   }
288   else if (output < -stats->peak_sample) {
289     if (output < MIN) {
290       ++stats->clipped_samples;
291       if (MIN - output > stats->peak_clipping)
292 	stats->peak_clipping = MIN - output;
293 
294       output = MIN;
295 
296       if (sample < MIN)
297 	sample = MIN;
298     }
299     stats->peak_sample = -output;
300   }
301 
302   /* quantize */
303   output &= ~mask;
304 
305   /* error feedback */
306   dither->error[0] = sample - output;
307 
308   /* scale */
309   return output >> scalebits;
310 }
311 
312 /*
313  * NAME:	audio_pcm_u8()
314  * DESCRIPTION:	write a block of unsigned 8-bit PCM samples
315  */
audio_pcm_u8(unsigned char * data,unsigned int nsamples,mad_fixed_t const * left,mad_fixed_t const * right,enum audio_mode mode,struct audio_stats * stats)316 unsigned int audio_pcm_u8(unsigned char *data, unsigned int nsamples,
317 			  mad_fixed_t const *left, mad_fixed_t const *right,
318 			  enum audio_mode mode, struct audio_stats *stats)
319 {
320   unsigned int len;
321 
322   len = nsamples;
323 
324   if (right) {  /* stereo */
325     switch (mode) {
326     case AUDIO_MODE_ROUND:
327       while (len--) {
328 	data[0] = audio_linear_round(8, *left++,  stats) ^ 0x80;
329 	data[1] = audio_linear_round(8, *right++, stats) ^ 0x80;
330 
331 	data += 2;
332       }
333       break;
334 
335     case AUDIO_MODE_DITHER:
336       while (len--) {
337 	data[0] = audio_linear_dither(8, *left++,
338 				      &left_dither,  stats) ^ 0x80;
339 	data[1] = audio_linear_dither(8, *right++,
340 				      &right_dither, stats) ^ 0x80;
341 
342 	data += 2;
343       }
344       break;
345 
346     default:
347       return 0;
348     }
349 
350     return nsamples * 2;
351   }
352   else {  /* mono */
353     switch (mode) {
354     case AUDIO_MODE_ROUND:
355       while (len--)
356 	*data++ = audio_linear_round(8, *left++, stats) ^ 0x80;
357       break;
358 
359     case AUDIO_MODE_DITHER:
360       while (len--)
361 	*data++ = audio_linear_dither(8, *left++, &left_dither, stats) ^ 0x80;
362       break;
363 
364     default:
365       return 0;
366     }
367 
368     return nsamples;
369   }
370 }
371 
372 /*
373  * NAME:	audio_pcm_s8()
374  * DESCRIPTION:	write a block of signed 8-bit PCM samples
375  */
audio_pcm_s8(unsigned char * data,unsigned int nsamples,mad_fixed_t const * left,mad_fixed_t const * right,enum audio_mode mode,struct audio_stats * stats)376 unsigned int audio_pcm_s8(unsigned char *data, unsigned int nsamples,
377 			  mad_fixed_t const *left, mad_fixed_t const *right,
378 			  enum audio_mode mode, struct audio_stats *stats)
379 {
380   unsigned int len;
381 
382   len = nsamples;
383 
384   if (right) {  /* stereo */
385     switch (mode) {
386     case AUDIO_MODE_ROUND:
387       while (len--) {
388 	data[0] = audio_linear_round(8, *left++,  stats);
389 	data[1] = audio_linear_round(8, *right++, stats);
390 
391 	data += 2;
392       }
393       break;
394 
395     case AUDIO_MODE_DITHER:
396       while (len--) {
397 	data[0] = audio_linear_dither(8, *left++,
398 				      &left_dither,  stats);
399 	data[1] = audio_linear_dither(8, *right++,
400 				      &right_dither, stats);
401 
402 	data += 2;
403       }
404       break;
405 
406     default:
407       return 0;
408     }
409 
410     return nsamples * 2;
411   }
412   else {  /* mono */
413     switch (mode) {
414     case AUDIO_MODE_ROUND:
415       while (len--)
416 	*data++ = audio_linear_round(8, *left++, stats);
417       break;
418 
419     case AUDIO_MODE_DITHER:
420       while (len--)
421 	*data++ = audio_linear_dither(8, *left++, &left_dither, stats);
422       break;
423 
424     default:
425       return 0;
426     }
427 
428     return nsamples;
429   }
430 }
431 
432 /*
433  * NAME:	audio_pcm_s16le()
434  * DESCRIPTION:	write a block of signed 16-bit little-endian PCM samples
435  */
audio_pcm_s16le(unsigned char * data,unsigned int nsamples,mad_fixed_t const * left,mad_fixed_t const * right,enum audio_mode mode,struct audio_stats * stats)436 unsigned int audio_pcm_s16le(unsigned char *data, unsigned int nsamples,
437 			     mad_fixed_t const *left, mad_fixed_t const *right,
438 			     enum audio_mode mode, struct audio_stats *stats)
439 {
440   unsigned int len;
441   register signed int sample0, sample1;
442 
443   len = nsamples;
444 
445   if (right) {  /* stereo */
446     switch (mode) {
447     case AUDIO_MODE_ROUND:
448       while (len--) {
449 	sample0 = audio_linear_round(16, *left++,  stats);
450 	sample1 = audio_linear_round(16, *right++, stats);
451 
452 	data[0] = sample0 >> 0;
453 	data[1] = sample0 >> 8;
454 	data[2] = sample1 >> 0;
455 	data[3] = sample1 >> 8;
456 
457 	data += 4;
458       }
459       break;
460 
461     case AUDIO_MODE_DITHER:
462       while (len--) {
463 	sample0 = audio_linear_dither(16, *left++,  &left_dither,  stats);
464 	sample1 = audio_linear_dither(16, *right++, &right_dither, stats);
465 
466 	data[0] = sample0 >> 0;
467 	data[1] = sample0 >> 8;
468 	data[2] = sample1 >> 0;
469 	data[3] = sample1 >> 8;
470 
471 	data += 4;
472       }
473       break;
474 
475     default:
476       return 0;
477     }
478 
479     return nsamples * 2 * 2;
480   }
481   else {  /* mono */
482     switch (mode) {
483     case AUDIO_MODE_ROUND:
484       while (len--) {
485 	sample0 = audio_linear_round(16, *left++, stats);
486 
487 	data[0] = sample0 >> 0;
488 	data[1] = sample0 >> 8;
489 
490 	data += 2;
491       }
492       break;
493 
494     case AUDIO_MODE_DITHER:
495       while (len--) {
496 	sample0 = audio_linear_dither(16, *left++, &left_dither, stats);
497 
498 	data[0] = sample0 >> 0;
499 	data[1] = sample0 >> 8;
500 
501 	data += 2;
502       }
503       break;
504 
505     default:
506       return 0;
507     }
508 
509     return nsamples * 2;
510   }
511 }
512 
513 /*
514  * NAME:	audio_pcm_s16be()
515  * DESCRIPTION:	write a block of signed 16-bit big-endian PCM samples
516  */
audio_pcm_s16be(unsigned char * data,unsigned int nsamples,mad_fixed_t const * left,mad_fixed_t const * right,enum audio_mode mode,struct audio_stats * stats)517 unsigned int audio_pcm_s16be(unsigned char *data, unsigned int nsamples,
518 			     mad_fixed_t const *left, mad_fixed_t const *right,
519 			     enum audio_mode mode, struct audio_stats *stats)
520 {
521   unsigned int len;
522   register signed int sample0, sample1;
523 
524   len = nsamples;
525 
526   if (right) {  /* stereo */
527     switch (mode) {
528     case AUDIO_MODE_ROUND:
529       while (len--) {
530 	sample0 = audio_linear_round(16, *left++,  stats);
531 	sample1 = audio_linear_round(16, *right++, stats);
532 
533 	data[0] = sample0 >> 8;
534 	data[1] = sample0 >> 0;
535 	data[2] = sample1 >> 8;
536 	data[3] = sample1 >> 0;
537 
538 	data += 4;
539       }
540       break;
541 
542     case AUDIO_MODE_DITHER:
543       while (len--) {
544 	sample0 = audio_linear_dither(16, *left++,  &left_dither,  stats);
545 	sample1 = audio_linear_dither(16, *right++, &right_dither, stats);
546 
547 	data[0] = sample0 >> 8;
548 	data[1] = sample0 >> 0;
549 	data[2] = sample1 >> 8;
550 	data[3] = sample1 >> 0;
551 
552 	data += 4;
553       }
554       break;
555 
556     default:
557       return 0;
558     }
559 
560     return nsamples * 2 * 2;
561   }
562   else {  /* mono */
563     switch (mode) {
564     case AUDIO_MODE_ROUND:
565       while (len--) {
566 	sample0 = audio_linear_round(16, *left++, stats);
567 
568 	data[0] = sample0 >> 8;
569 	data[1] = sample0 >> 0;
570 
571 	data += 2;
572       }
573       break;
574 
575     case AUDIO_MODE_DITHER:
576       while (len--) {
577 	sample0 = audio_linear_dither(16, *left++, &left_dither, stats);
578 
579 	data[0] = sample0 >> 8;
580 	data[1] = sample0 >> 0;
581 
582 	data += 2;
583       }
584       break;
585 
586     default:
587       return 0;
588     }
589 
590     return nsamples * 2;
591   }
592 }
593 
594 /*
595  * NAME:	audio_pcm_s24le()
596  * DESCRIPTION:	write a block of signed 24-bit little-endian PCM samples
597  */
audio_pcm_s24le(unsigned char * data,unsigned int nsamples,mad_fixed_t const * left,mad_fixed_t const * right,enum audio_mode mode,struct audio_stats * stats)598 unsigned int audio_pcm_s24le(unsigned char *data, unsigned int nsamples,
599 			     mad_fixed_t const *left, mad_fixed_t const *right,
600 			     enum audio_mode mode, struct audio_stats *stats)
601 {
602   unsigned int len;
603   register signed long sample0, sample1;
604 
605   len = nsamples;
606 
607   if (right) {  /* stereo */
608     switch (mode) {
609     case AUDIO_MODE_ROUND:
610       while (len--) {
611 	sample0 = audio_linear_round(24, *left++,  stats);
612 	sample1 = audio_linear_round(24, *right++, stats);
613 
614 	data[0] = sample0 >>  0;
615 	data[1] = sample0 >>  8;
616 	data[2] = sample0 >> 16;
617 
618 	data[3] = sample1 >>  0;
619 	data[4] = sample1 >>  8;
620 	data[5] = sample1 >> 16;
621 
622 	data += 6;
623       }
624       break;
625 
626     case AUDIO_MODE_DITHER:
627       while (len--) {
628 	sample0 = audio_linear_dither(24, *left++,  &left_dither,  stats);
629 	sample1 = audio_linear_dither(24, *right++, &right_dither, stats);
630 
631 	data[0] = sample0 >>  0;
632 	data[1] = sample0 >>  8;
633 	data[2] = sample0 >> 16;
634 
635 	data[3] = sample1 >>  0;
636 	data[4] = sample1 >>  8;
637 	data[5] = sample1 >> 16;
638 
639 	data += 6;
640       }
641       break;
642 
643     default:
644       return 0;
645     }
646 
647     return nsamples * 3 * 2;
648   }
649   else {  /* mono */
650     switch (mode) {
651     case AUDIO_MODE_ROUND:
652       while (len--) {
653 	sample0 = audio_linear_round(24, *left++, stats);
654 
655 	data[0] = sample0 >>  0;
656 	data[1] = sample0 >>  8;
657 	data[2] = sample0 >> 16;
658 
659 	data += 3;
660       }
661       break;
662 
663     case AUDIO_MODE_DITHER:
664       while (len--) {
665 	sample0 = audio_linear_dither(24, *left++, &left_dither, stats);
666 
667 	data[0] = sample0 >>  0;
668 	data[1] = sample0 >>  8;
669 	data[2] = sample0 >> 16;
670 
671 	data += 3;
672       }
673       break;
674 
675     default:
676       return 0;
677     }
678 
679     return nsamples * 3;
680   }
681 }
682 
683 /*
684  * NAME:	audio_pcm_s24be()
685  * DESCRIPTION:	write a block of signed 24-bit big-endian PCM samples
686  */
audio_pcm_s24be(unsigned char * data,unsigned int nsamples,mad_fixed_t const * left,mad_fixed_t const * right,enum audio_mode mode,struct audio_stats * stats)687 unsigned int audio_pcm_s24be(unsigned char *data, unsigned int nsamples,
688 			     mad_fixed_t const *left, mad_fixed_t const *right,
689 			     enum audio_mode mode, struct audio_stats *stats)
690 {
691   unsigned int len;
692   register signed long sample0, sample1;
693 
694   len = nsamples;
695 
696   if (right) {  /* stereo */
697     switch (mode) {
698     case AUDIO_MODE_ROUND:
699       while (len--) {
700 	sample0 = audio_linear_round(24, *left++,  stats);
701 	sample1 = audio_linear_round(24, *right++, stats);
702 
703 	data[0] = sample0 >> 16;
704 	data[1] = sample0 >>  8;
705 	data[2] = sample0 >>  0;
706 
707 	data[3] = sample1 >> 16;
708 	data[4] = sample1 >>  8;
709 	data[5] = sample1 >>  0;
710 
711 	data += 6;
712       }
713       break;
714 
715     case AUDIO_MODE_DITHER:
716       while (len--) {
717 	sample0 = audio_linear_dither(24, *left++,  &left_dither,  stats);
718 	sample1 = audio_linear_dither(24, *right++, &right_dither, stats);
719 
720 	data[0] = sample0 >> 16;
721 	data[1] = sample0 >>  8;
722 	data[2] = sample0 >>  0;
723 
724 	data[3] = sample1 >> 16;
725 	data[4] = sample1 >>  8;
726 	data[5] = sample1 >>  0;
727 
728 	data += 6;
729       }
730       break;
731 
732     default:
733       return 0;
734     }
735 
736     return nsamples * 3 * 2;
737   }
738   else {  /* mono */
739     switch (mode) {
740     case AUDIO_MODE_ROUND:
741       while (len--) {
742 	sample0 = audio_linear_round(24, *left++, stats);
743 
744 	data[0] = sample0 >> 16;
745 	data[1] = sample0 >>  8;
746 	data[2] = sample0 >>  0;
747 
748 	data += 3;
749       }
750       break;
751 
752     case AUDIO_MODE_DITHER:
753       while (len--) {
754 	sample1 = audio_linear_dither(24, *left++, &left_dither, stats);
755 
756 	data[0] = sample1 >> 16;
757 	data[1] = sample1 >>  8;
758 	data[2] = sample1 >>  0;
759 
760 	data += 3;
761       }
762       break;
763 
764     default:
765       return 0;
766     }
767 
768     return nsamples * 3;
769   }
770 }
771 
772 /*
773  * NAME:	audio_pcm_s32le()
774  * DESCRIPTION:	write a block of signed 32-bit little-endian PCM samples
775  */
audio_pcm_s32le(unsigned char * data,unsigned int nsamples,mad_fixed_t const * left,mad_fixed_t const * right,enum audio_mode mode,struct audio_stats * stats)776 unsigned int audio_pcm_s32le(unsigned char *data, unsigned int nsamples,
777 			     mad_fixed_t const *left, mad_fixed_t const *right,
778 			     enum audio_mode mode, struct audio_stats *stats)
779 {
780   unsigned int len;
781   register signed long sample0, sample1;
782 
783   len = nsamples;
784 
785   if (right) {  /* stereo */
786     switch (mode) {
787     case AUDIO_MODE_ROUND:
788       while (len--) {
789 	sample0 = audio_linear_round(24, *left++,  stats);
790 	sample1 = audio_linear_round(24, *right++, stats);
791 
792 	data[0] = 0;
793 	data[1] = sample0 >>  0;
794 	data[2] = sample0 >>  8;
795 	data[3] = sample0 >> 16;
796 
797 	data[4] = 0;
798 	data[5] = sample1 >>  0;
799 	data[6] = sample1 >>  8;
800 	data[7] = sample1 >> 16;
801 
802 	data += 8;
803       }
804       break;
805 
806     case AUDIO_MODE_DITHER:
807       while (len--) {
808 	sample0 = audio_linear_dither(24, *left++,  &left_dither,  stats);
809 	sample1 = audio_linear_dither(24, *right++, &right_dither, stats);
810 
811 	data[0] = 0;
812 	data[1] = sample0 >>  0;
813 	data[2] = sample0 >>  8;
814 	data[3] = sample0 >> 16;
815 
816 	data[4] = 0;
817 	data[5] = sample1 >>  0;
818 	data[6] = sample1 >>  8;
819 	data[7] = sample1 >> 16;
820 
821 	data += 8;
822       }
823       break;
824 
825     default:
826       return 0;
827     }
828 
829     return nsamples * 4 * 2;
830   }
831   else {  /* mono */
832     switch (mode) {
833     case AUDIO_MODE_ROUND:
834       while (len--) {
835 	sample0 = audio_linear_round(24, *left++, stats);
836 
837 	data[0] = 0;
838 	data[1] = sample0 >>  0;
839 	data[2] = sample0 >>  8;
840 	data[3] = sample0 >> 16;
841 
842 	data += 4;
843       }
844       break;
845 
846     case AUDIO_MODE_DITHER:
847       while (len--) {
848 	sample0 = audio_linear_dither(24, *left++, &left_dither, stats);
849 
850 	data[0] = 0;
851 	data[1] = sample0 >>  0;
852 	data[2] = sample0 >>  8;
853 	data[3] = sample0 >> 16;
854 
855 	data += 4;
856       }
857       break;
858 
859     default:
860       return 0;
861     }
862 
863     return nsamples * 4;
864   }
865 }
866 
867 /*
868  * NAME:	audio_pcm_s32be()
869  * DESCRIPTION:	write a block of signed 32-bit big-endian PCM samples
870  */
audio_pcm_s32be(unsigned char * data,unsigned int nsamples,mad_fixed_t const * left,mad_fixed_t const * right,enum audio_mode mode,struct audio_stats * stats)871 unsigned int audio_pcm_s32be(unsigned char *data, unsigned int nsamples,
872 			     mad_fixed_t const *left, mad_fixed_t const *right,
873 			     enum audio_mode mode, struct audio_stats *stats)
874 {
875   unsigned int len;
876   register signed long sample0, sample1;
877 
878   len = nsamples;
879 
880   if (right) {  /* stereo */
881     switch (mode) {
882     case AUDIO_MODE_ROUND:
883       while (len--) {
884 	sample0 = audio_linear_round(24, *left++,  stats);
885 	sample1 = audio_linear_round(24, *right++, stats);
886 
887 	data[0] = sample0 >> 16;
888 	data[1] = sample0 >>  8;
889 	data[2] = sample0 >>  0;
890 	data[3] = 0;
891 
892 	data[4] = sample1 >> 16;
893 	data[5] = sample1 >>  8;
894 	data[6] = sample1 >>  0;
895 	data[7] = 0;
896 
897 	data += 8;
898       }
899       break;
900 
901     case AUDIO_MODE_DITHER:
902       while (len--) {
903 	sample0 = audio_linear_dither(24, *left++,  &left_dither,  stats);
904 	sample1 = audio_linear_dither(24, *right++, &right_dither, stats);
905 
906 	data[0] = sample0 >> 16;
907 	data[1] = sample0 >>  8;
908 	data[2] = sample0 >>  0;
909 	data[3] = 0;
910 
911 	data[4] = sample1 >> 16;
912 	data[5] = sample1 >>  8;
913 	data[6] = sample1 >>  0;
914 	data[7] = 0;
915 
916 	data += 8;
917       }
918       break;
919 
920     default:
921       return 0;
922     }
923 
924     return nsamples * 4 * 2;
925   }
926   else {  /* mono */
927     switch (mode) {
928     case AUDIO_MODE_ROUND:
929       while (len--) {
930 	sample0 = audio_linear_round(24, *left++, stats);
931 
932 	data[0] = sample0 >> 16;
933 	data[1] = sample0 >>  8;
934 	data[2] = sample0 >>  0;
935 	data[3] = 0;
936 
937 	data += 4;
938       }
939       break;
940 
941     case AUDIO_MODE_DITHER:
942       while (len--) {
943 	sample0 = audio_linear_dither(24, *left++, &left_dither, stats);
944 
945 	data[0] = sample0 >> 16;
946 	data[1] = sample0 >>  8;
947 	data[2] = sample0 >>  0;
948 	data[3] = 0;
949 
950 	data += 4;
951       }
952       break;
953 
954     default:
955       return 0;
956     }
957 
958     return nsamples * 4;
959   }
960 }
961 
962 static
linear2mulaw(mad_fixed_t sample)963 unsigned char linear2mulaw(mad_fixed_t sample)
964 {
965   unsigned int sign, mulaw;
966 
967   enum {
968     BIAS = (mad_fixed_t) ((0x10 << 1) + 1) << (MAD_F_FRACBITS - 13)
969   };
970 
971   if (sample < 0) {
972     sample = BIAS - sample;
973     sign   = 0x7f;
974   }
975   else {
976     sample = BIAS + sample;
977     sign   = 0xff;
978   }
979 
980   mulaw = 0x7f;
981   if (sample < MAD_F_ONE) {
982     unsigned int segment;
983     unsigned long mask;
984 
985     segment = 7;
986     for (mask = 1L << (MAD_F_FRACBITS - 1); !(sample & mask); mask >>= 1)
987       --segment;
988 
989     mulaw = ((segment << 4) |
990 	     ((sample >> (MAD_F_FRACBITS - 1 - (7 - segment) - 4)) & 0x0f));
991   }
992 
993   mulaw ^= sign;
994 
995 # if 0
996   if (mulaw == 0x00)
997     mulaw = 0x02;
998 # endif
999 
1000   return mulaw;
1001 }
1002 
1003 static
mulaw2linear(unsigned char mulaw)1004 mad_fixed_t mulaw2linear(unsigned char mulaw)
1005 {
1006   int sign, segment, mantissa, value;
1007 
1008   enum {
1009     BIAS = (0x10 << 1) + 1
1010   };
1011 
1012   mulaw    = ~mulaw;
1013   sign     = (mulaw >> 7) & 0x01;
1014   segment  = (mulaw >> 4) & 0x07;
1015   mantissa = (mulaw >> 0) & 0x0f;
1016 
1017   value = ((0x21 | (mantissa << 1)) << segment) - BIAS;
1018   if (sign)
1019     value = -value;
1020 
1021   return (mad_fixed_t) value << (MAD_F_FRACBITS - 13);
1022 }
1023 
1024 /*
1025  * NAME:	audio_mulaw_round()
1026  * DESCRIPTION:	convert a linear PCM value to 8-bit ISDN mu-law
1027  */
1028 inline
audio_mulaw_round(mad_fixed_t sample,struct audio_stats * stats)1029 unsigned char audio_mulaw_round(mad_fixed_t sample, struct audio_stats *stats)
1030 {
1031   clip(&sample, stats);
1032 
1033   return linear2mulaw(sample);
1034 }
1035 
1036 /*
1037  * NAME:	audio_mulaw_dither()
1038  * DESCRIPTION:	convert a linear PCM value to dithered 8-bit ISDN mu-law
1039  */
1040 inline
audio_mulaw_dither(mad_fixed_t sample,struct audio_dither * dither,struct audio_stats * stats)1041 unsigned char audio_mulaw_dither(mad_fixed_t sample,
1042 				 struct audio_dither *dither,
1043 				 struct audio_stats *stats)
1044 {
1045   unsigned char mulaw;
1046 
1047   /* noise shape */
1048   sample += dither->error[0];
1049 
1050   clip(&sample, stats);
1051 
1052   mulaw = linear2mulaw(sample);
1053 
1054   /* error feedback */
1055   dither->error[0] = sample - mulaw2linear(mulaw);
1056 
1057   return mulaw;
1058 }
1059 
1060 /*
1061  * NAME:	audio_pcm_mulaw()
1062  * DESCRIPTION:	write a block of 8-bit mu-law encoded samples
1063  */
audio_pcm_mulaw(unsigned char * data,unsigned int nsamples,mad_fixed_t const * left,mad_fixed_t const * right,enum audio_mode mode,struct audio_stats * stats)1064 unsigned int audio_pcm_mulaw(unsigned char *data, unsigned int nsamples,
1065 			     mad_fixed_t const *left, mad_fixed_t const *right,
1066 			     enum audio_mode mode, struct audio_stats *stats)
1067 {
1068   unsigned int len;
1069 
1070   len = nsamples;
1071 
1072   if (right) {  /* stereo */
1073     switch (mode) {
1074     case AUDIO_MODE_ROUND:
1075       while (len--) {
1076 	data[0] = audio_mulaw_round(*left++,  stats);
1077 	data[1] = audio_mulaw_round(*right++, stats);
1078 
1079 	data += 2;
1080       }
1081       break;
1082 
1083     case AUDIO_MODE_DITHER:
1084       while (len--) {
1085 	data[0] = audio_mulaw_dither(*left++,  &left_dither,  stats);
1086 	data[1] = audio_mulaw_dither(*right++, &right_dither, stats);
1087 
1088 	data += 2;
1089       }
1090       break;
1091 
1092     default:
1093       return 0;
1094     }
1095 
1096     return nsamples * 2;
1097   }
1098   else {  /* mono */
1099     switch (mode) {
1100     case AUDIO_MODE_ROUND:
1101       while (len--)
1102 	*data++ = audio_mulaw_round(*left++, stats);
1103       break;
1104 
1105     case AUDIO_MODE_DITHER:
1106       while (len--)
1107 	*data++ = audio_mulaw_dither(*left++, &left_dither, stats);
1108       break;
1109 
1110     default:
1111       return 0;
1112     }
1113 
1114     return nsamples;
1115   }
1116 }
1117