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