diff options
Diffstat (limited to 'apps/codecs/dumb/examples/dumbout.c')
-rw-r--r-- | apps/codecs/dumb/examples/dumbout.c | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/apps/codecs/dumb/examples/dumbout.c b/apps/codecs/dumb/examples/dumbout.c new file mode 100644 index 0000000000..b0ead3dd5e --- /dev/null +++ b/apps/codecs/dumb/examples/dumbout.c | |||
@@ -0,0 +1,335 @@ | |||
1 | /* _______ ____ __ ___ ___ | ||
2 | * \ _ \ \ / \ / \ \ / / ' ' ' | ||
3 | * | | \ \ | | || | \/ | . . | ||
4 | * | | | | | | || ||\ /| | | ||
5 | * | | | | | | || || \/ | | ' ' ' | ||
6 | * | | | | | | || || | | . . | ||
7 | * | |_/ / \ \__// || | | | ||
8 | * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque | ||
9 | * / \ | ||
10 | * / . \ | ||
11 | * dumbout.c - Utility to stream music to a file. / / \ \ | ||
12 | * | < / \_ | ||
13 | * By entheh. | \/ /\ / | ||
14 | * \_ / > / | ||
15 | * | \ / / | ||
16 | * | ' / | ||
17 | * \__/ | ||
18 | */ | ||
19 | |||
20 | #include <time.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <stdio.h> | ||
23 | #include <ctype.h> | ||
24 | #include <math.h> | ||
25 | #include <string.h> | ||
26 | #include <dumb.h> | ||
27 | |||
28 | |||
29 | union { | ||
30 | short s16[8192]; | ||
31 | char s8[16384]; | ||
32 | } buffer; | ||
33 | |||
34 | |||
35 | int main(int argc, const char *const *argv) /* I'm const-crazy! */ | ||
36 | { | ||
37 | DUH *duh; | ||
38 | DUH_SIGRENDERER *sr; | ||
39 | |||
40 | const char *fn = NULL; | ||
41 | const char *fn_out = NULL; | ||
42 | FILE *outf; | ||
43 | |||
44 | int depth = 16; | ||
45 | int bigendian = 0; | ||
46 | int unsign = 0; | ||
47 | int freq = 44100; | ||
48 | int n_channels = 2; | ||
49 | float volume = 1.0f; | ||
50 | float delay = 0.0f; | ||
51 | float delta; | ||
52 | int bufsize; | ||
53 | clock_t start, end; | ||
54 | |||
55 | int i = 1; | ||
56 | |||
57 | LONG_LONG length; | ||
58 | LONG_LONG done; | ||
59 | int dots; | ||
60 | |||
61 | while (i < argc) { | ||
62 | const char *arg = argv[i++]; | ||
63 | if (*arg != '-') { | ||
64 | if (fn) { | ||
65 | fprintf(stderr, | ||
66 | "Cannot specify multiple filenames!\n" | ||
67 | "Second filename found: \"%s\"\n", arg); | ||
68 | return 1; | ||
69 | } | ||
70 | fn = arg; | ||
71 | continue; | ||
72 | } | ||
73 | arg++; | ||
74 | while (*arg) { | ||
75 | char *endptr; | ||
76 | switch (*arg++) { | ||
77 | case 'o': | ||
78 | case 'O': | ||
79 | if (i >= argc) { | ||
80 | fprintf(stderr, "Out of arguments; output filename expected!\n"); | ||
81 | return 1; | ||
82 | } | ||
83 | fn_out = argv[i++]; | ||
84 | break; | ||
85 | case 'd': | ||
86 | case 'D': | ||
87 | if (i >= argc) { | ||
88 | fprintf(stderr, "Out of arguments; delay expected!\n"); | ||
89 | return 1; | ||
90 | } | ||
91 | delay = (float)strtod(argv[i++], &endptr); | ||
92 | if (*endptr != 0 || delay < 0.0f || delay > 64.0f) { | ||
93 | fprintf(stderr, "Invalid delay!\n"); | ||
94 | return 1; | ||
95 | } | ||
96 | break; | ||
97 | case 'v': | ||
98 | case 'V': | ||
99 | if (i >= argc) { | ||
100 | fprintf(stderr, "Out of arguments; volume expected!\n"); | ||
101 | return 1; | ||
102 | } | ||
103 | volume = (float)strtod(argv[i++], &endptr); | ||
104 | if (*endptr != 0 || volume < -8.0f || volume > 8.0f) { | ||
105 | fprintf(stderr, "Invalid volume!\n"); | ||
106 | return 1; | ||
107 | } | ||
108 | break; | ||
109 | case 's': | ||
110 | case 'S': | ||
111 | if (i >= argc) { | ||
112 | fprintf(stderr, "Out of arguments; sampling rate expected!\n"); | ||
113 | return 1; | ||
114 | } | ||
115 | freq = strtol(argv[i++], &endptr, 10); | ||
116 | if (*endptr != 0 || freq < 1 || freq > 960000) { | ||
117 | fprintf(stderr, "Invalid sampling rate!\n"); | ||
118 | return 1; | ||
119 | } | ||
120 | break; | ||
121 | case '8': | ||
122 | depth = 8; | ||
123 | break; | ||
124 | case 'b': | ||
125 | case 'B': | ||
126 | bigendian = 1; | ||
127 | break; | ||
128 | case 'm': | ||
129 | case 'M': | ||
130 | n_channels = 1; | ||
131 | break; | ||
132 | case 'u': | ||
133 | case 'U': | ||
134 | unsign = 1; | ||
135 | break; | ||
136 | case 'r': | ||
137 | case 'R': | ||
138 | if (i >= argc) { | ||
139 | fprintf(stderr, "Out of arguments; resampling quality expected!\n"); | ||
140 | return 1; | ||
141 | } | ||
142 | dumb_resampling_quality = strtol(argv[i++], &endptr, 10); | ||
143 | if (*endptr != 0 || dumb_resampling_quality < 0 || dumb_resampling_quality > 2) { | ||
144 | fprintf(stderr, "Invalid resampling quality!\n"); | ||
145 | return 1; | ||
146 | } | ||
147 | break; | ||
148 | default: | ||
149 | fprintf(stderr, "Invalid switch - '%c'!\n", isprint(arg[-1]) ? arg[-1] : '?'); | ||
150 | return 1; | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | |||
155 | if (!fn) { | ||
156 | fprintf(stderr, | ||
157 | "Usage: dumbout [options] module [more-options]\n" | ||
158 | "\n" | ||
159 | "The module can be any IT, XM, S3M or MOD file. It will be rendered to a .pcm\n" | ||
160 | "file of the same name, unless you specify otherwise with the -o option.\n" | ||
161 | "\n" | ||
162 | "The valid options are:\n" | ||
163 | "-o <file> specify the output filename (defaults to the input filename with\n" | ||
164 | " the extension replaced with .pcm); use - to write to standard\n" | ||
165 | " output or . to write nowhere (useful for measuring DUMB's\n" | ||
166 | " performance, and DOS and Windows don't have /dev/null!)\n" | ||
167 | "-d <delay> set the initial delay, in seconds (default 0.0)\n" | ||
168 | "-v <volume> adjust the volume (default 1.0)\n" | ||
169 | "-s <freq> set the sampling rate in Hz (default 44100)\n" | ||
170 | "-8 generate 8-bit instead of 16-bit\n" | ||
171 | "-b generate big-endian data instead of little-endian (meaningless when\n" | ||
172 | " using -8)\n" | ||
173 | "-m generate mono output instead of stereo left/right pairs\n" | ||
174 | "-u generated unsigned output instead of signed\n" | ||
175 | "-r <value> specify the resampling quality to use\n"); | ||
176 | return 1; | ||
177 | } | ||
178 | |||
179 | atexit(&dumb_exit); | ||
180 | dumb_register_stdfiles(); | ||
181 | |||
182 | dumb_it_max_to_mix = 256; | ||
183 | |||
184 | duh = load_duh(fn); | ||
185 | if (!duh) { | ||
186 | duh = dumb_load_it(fn); | ||
187 | if (!duh) { | ||
188 | duh = dumb_load_xm(fn); | ||
189 | if (!duh) { | ||
190 | duh = dumb_load_s3m(fn); | ||
191 | if (!duh) { | ||
192 | duh = dumb_load_mod(fn); | ||
193 | if (!duh) { | ||
194 | fprintf(stderr, "Unable to open %s!\n", fn); | ||
195 | return 1; | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | } | ||
200 | } | ||
201 | |||
202 | sr = duh_start_sigrenderer(duh, 0, n_channels, 0); | ||
203 | if (!sr) { | ||
204 | unload_duh(duh); | ||
205 | fprintf(stderr, "Unable to play file!\n"); | ||
206 | return 1; | ||
207 | } | ||
208 | |||
209 | if (fn_out) { | ||
210 | if (fn_out[0] == '-' && fn_out[1] == 0) | ||
211 | outf = stdout; | ||
212 | else if (fn_out[0] == '.' && fn_out[1] == 0) | ||
213 | outf = NULL; | ||
214 | else { | ||
215 | outf = fopen(fn_out, "wb"); | ||
216 | if (!outf) { | ||
217 | fprintf(stderr, "Unable to open %s for writing!\n", fn_out); | ||
218 | duh_end_sigrenderer(sr); | ||
219 | unload_duh(duh); | ||
220 | return 1; | ||
221 | } | ||
222 | } | ||
223 | } else { | ||
224 | char *extptr = NULL, *p; | ||
225 | char *fn_out = malloc(strlen(fn)+5); | ||
226 | if (!fn_out) { | ||
227 | fprintf(stderr, "Out of memory!\n"); | ||
228 | duh_end_sigrenderer(sr); | ||
229 | unload_duh(duh); | ||
230 | return 1; | ||
231 | } | ||
232 | strcpy(fn_out, fn); | ||
233 | for (p = fn_out; *p; p++) | ||
234 | if (*p == '.') extptr = p; | ||
235 | if (!extptr) extptr = p; | ||
236 | strcpy(extptr, ".pcm"); | ||
237 | outf = fopen(fn_out, "wb"); | ||
238 | if (!outf) { | ||
239 | fprintf(stderr, "Unable to open %s for writing!\n", fn_out); | ||
240 | free(fn_out); | ||
241 | duh_end_sigrenderer(sr); | ||
242 | unload_duh(duh); | ||
243 | return 1; | ||
244 | } | ||
245 | free(fn_out); | ||
246 | } | ||
247 | |||
248 | { | ||
249 | DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer(sr); | ||
250 | dumb_it_set_loop_callback(itsr, &dumb_it_callback_terminate, NULL); | ||
251 | dumb_it_set_xm_speed_zero_callback(itsr, &dumb_it_callback_terminate, NULL); | ||
252 | } | ||
253 | |||
254 | length = (LONG_LONG)duh_get_length(duh) * freq >> 16; | ||
255 | done = 0; | ||
256 | dots = 0; | ||
257 | delta = 65536.0f / freq; | ||
258 | bufsize = depth == 16 ? 8192 : 16384; | ||
259 | bufsize /= n_channels; | ||
260 | |||
261 | { | ||
262 | long l = (long)floor(delay * freq + 0.5f); | ||
263 | l *= n_channels * (depth >> 3); | ||
264 | if (l) { | ||
265 | if (unsign) { | ||
266 | if (depth == 16) { | ||
267 | if (bigendian) { | ||
268 | for (i = 0; i < 8192; i++) { | ||
269 | buffer.s8[i*2] = 0x80; | ||
270 | buffer.s8[i*2+1] = 0x00; | ||
271 | } | ||
272 | } else { | ||
273 | for (i = 0; i < 8192; i++) { | ||
274 | buffer.s8[i*2] = 0x00; | ||
275 | buffer.s8[i*2+1] = 0x80; | ||
276 | } | ||
277 | } | ||
278 | } else | ||
279 | memset(buffer.s8, 0x80, 16384); | ||
280 | } else | ||
281 | memset(buffer.s8, 0, 16384); | ||
282 | while (l >= 16384) { | ||
283 | if (outf) fwrite(buffer.s8, 1, 16384, outf); | ||
284 | l -= 16384; | ||
285 | } | ||
286 | if (l && outf) fwrite(buffer.s8, 1, l, outf); | ||
287 | } | ||
288 | } | ||
289 | |||
290 | start = clock(); | ||
291 | |||
292 | fprintf(stderr, "................................................................\n"); | ||
293 | for (;;) { | ||
294 | int l = duh_render(sr, depth, unsign, volume, delta, bufsize, &buffer); | ||
295 | if (depth == 16) { | ||
296 | if (bigendian) { | ||
297 | for (i = 0; i < l * n_channels; i++) { | ||
298 | short val = buffer.s16[i]; | ||
299 | buffer.s8[i*2] = val >> 8; | ||
300 | buffer.s8[i*2+1] = val; | ||
301 | } | ||
302 | } else { | ||
303 | for (i = 0; i < l * n_channels; i++) { | ||
304 | short val = buffer.s16[i]; | ||
305 | buffer.s8[i*2] = val; | ||
306 | buffer.s8[i*2+1] = val >> 8; | ||
307 | } | ||
308 | } | ||
309 | } | ||
310 | if (outf) fwrite(buffer.s8, 1, l * n_channels * (depth >> 3), outf); | ||
311 | if (l < bufsize) break; | ||
312 | done += l; | ||
313 | l = done * 64 / length; | ||
314 | while (dots < 64 && l > dots) { | ||
315 | fprintf(stderr, "|"); | ||
316 | dots++; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | while (64 > dots) { | ||
321 | fprintf(stderr, "|"); | ||
322 | dots++; | ||
323 | } | ||
324 | fprintf(stderr, "\n"); | ||
325 | |||
326 | end = clock(); | ||
327 | |||
328 | duh_end_sigrenderer(sr); | ||
329 | unload_duh(duh); | ||
330 | if (outf && outf != stdout) fclose(outf); | ||
331 | |||
332 | fprintf(stderr, "Elapsed time: %f seconds\n", (end - start) / (float)CLOCKS_PER_SEC); | ||
333 | |||
334 | return 0; | ||
335 | } | ||