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_hex.c,v 1.23 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 <stdio.h>
29 # include <string.h>
30 # include <mad.h>
31 
32 # include "audio.h"
33 
34 static FILE *outfile;
35 static unsigned int bitdepth;
36 static char format_str[7];
37 
38 static
init(struct audio_init * init)39 int init(struct audio_init *init)
40 {
41   if (init->path && strcmp(init->path, "-") != 0) {
42     outfile = fopen(init->path, "w");
43     if (outfile == 0) {
44       audio_error = ":";
45       return -1;
46     }
47   }
48   else
49     outfile = stdout;
50 
51   return 0;
52 }
53 
54 static
config(struct audio_config * config)55 int config(struct audio_config *config)
56 {
57   bitdepth = config->precision & ~3;
58   if (bitdepth == 0 || bitdepth > 24)
59     bitdepth = 24;
60 
61   config->precision = bitdepth;
62 
63   sprintf(format_str, "%%0%1ulX\n", bitdepth / 4);
64 
65   fprintf(outfile, "# %u channel%s, %u Hz, %u-bit samples\n",
66 	  config->channels, config->channels == 1 ? "" : "s",
67 	  config->speed, config->precision);
68 
69   return 0;
70 }
71 
72 static
play(struct audio_play * play)73 int play(struct audio_play *play)
74 {
75   unsigned int len;
76   mad_fixed_t const *left, *right;
77   unsigned long mask;
78 
79   len   = play->nsamples;
80   left  = play->samples[0];
81   right = play->samples[1];
82 
83   mask = (1L << bitdepth) - 1;
84 
85   switch (play->mode) {
86   case AUDIO_MODE_ROUND:
87     while (len--) {
88       fprintf(outfile, format_str,
89 	      audio_linear_round(bitdepth, *left++, play->stats) & mask);
90 
91       if (right) {
92 	fprintf(outfile, format_str,
93 		audio_linear_round(bitdepth, *right++, play->stats) & mask);
94       }
95     }
96     break;
97 
98   case AUDIO_MODE_DITHER:
99     {
100       static struct audio_dither left_dither, right_dither;
101 
102       while (len--) {
103 	fprintf(outfile, format_str,
104 		audio_linear_dither(bitdepth, *left++, &left_dither,
105 				    play->stats) & mask);
106 
107 	if (right) {
108 	  fprintf(outfile, format_str,
109 		  audio_linear_dither(bitdepth, *right++, &right_dither,
110 				      play->stats) & mask);
111 	}
112       }
113     }
114     break;
115   }
116 
117   return 0;
118 }
119 
120 static
stop(struct audio_stop * stop)121 int stop(struct audio_stop *stop)
122 {
123   return 0;
124 }
125 
126 static
finish(struct audio_finish * finish)127 int finish(struct audio_finish *finish)
128 {
129   if (outfile != stdout &&
130       fclose(outfile) == EOF) {
131     audio_error = ":fclose";
132     return -1;
133   }
134 
135   return 0;
136 }
137 
audio_hex(union audio_control * control)138 int audio_hex(union audio_control *control)
139 {
140   audio_error = 0;
141 
142   switch (control->command) {
143   case AUDIO_COMMAND_INIT:
144     return init(&control->init);
145 
146   case AUDIO_COMMAND_CONFIG:
147     return config(&control->config);
148 
149   case AUDIO_COMMAND_PLAY:
150     return play(&control->play);
151 
152   case AUDIO_COMMAND_STOP:
153     return stop(&control->stop);
154 
155   case AUDIO_COMMAND_FINISH:
156     return finish(&control->finish);
157   }
158 
159   return 0;
160 }
161