1 /*
2 out123: stream data from libmpg123 or libsyn123 to an audio output device
3
4 copyright 1995-2021 by the mpg123 project,
5 free software under the terms of the LGPL 2.1
6 see COPYING and AUTHORS files in distribution or http://mpg123.org
7
8 initially written by Thomas Orgis (extracted from mpg123.c)
9
10 This is a stripped down mpg123 that only uses libout123 to write standard
11 input to an audio device. Of course, it got some enhancements with the
12 advent of libsyn123.
13
14 Please bear in mind that the code started out as a nasty hack on a very
15 old piece made out of nasty hacks and plain ugly code. Some nastiness
16 (like lax parameter checking) even serves a purpose: Test the robustness
17 of our libraries in catching bad caller behaviour.
18
19 TODO: Add basic parsing of WAV headers to be able to pipe in WAV files, especially
20 from something like mpg123 -w -.
21
22 TODO: Add option for phase shift between channels (delaying the second one).
23 This might be useful with generated signals, to locate left/right speakers
24 or just generally enhance the experience ... compensating for speaker locations.
25 This also means the option of mixing, channel attentuation. This is not
26 too hard to implement and might be useful for debugging outputs.
27 */
28
29 #define ME "out123"
30 #include "config.h"
31 #include "compat.h"
32 #include <ctype.h>
33 #if WIN32
34 #include "win32_support.h"
35 #endif
36 #if defined(WIN32) && defined(DYNAMIC_BUILD)
37 #define LINK_MPG123_DLL
38 #endif
39 #include "out123.h"
40
41 #include "local.h"
42
43 #ifdef HAVE_SYS_WAIT_H
44 #include <sys/wait.h>
45 #endif
46 #ifdef HAVE_SYS_RESOURCE_H
47 #include <sys/resource.h>
48 #endif
49
50 #include <errno.h>
51 #include <string.h>
52 #include <time.h>
53
54 #ifdef HAVE_SCHED_H
55 #include <sched.h>
56 #endif
57
58 #include "sysutil.h"
59 #include "getlopt.h"
60
61 #include "syn123.h"
62 #include "filters.h"
63
64 #include "debug.h"
65
66 /* be paranoid about setpriority support */
67 #ifndef PRIO_PROCESS
68 #undef HAVE_SETPRIORITY
69 #endif
70
71 static int intflag = FALSE;
72
73 static void usage(int err);
74 static void want_usage(char* arg, topt *opts);
75 static void long_usage(int err);
76 static void want_long_usage(char* arg, topt *opts);
77 static void print_title(FILE* o);
78 static void give_version(char* arg, topt *opts);
79
80 static int verbose = 0;
81 static int quiet = FALSE;
82 enum runmodes
83 {
84 RUN_MAIN = 0
85 , LIST_MODULES
86 , LIST_DEVICES
87 };
88
89 static int runmode = RUN_MAIN;
90
91 int stdout_is_term = FALSE; // It's an interactive terminal.
92 int stderr_is_term = FALSE; // It's an interactive terminal.
93
94 static FILE* input = NULL;
95 static char *encoding_name = NULL;
96 static int encoding = MPG123_ENC_SIGNED_16;
97 static char *inputenc_name = NULL;
98 static int inputenc = 0;
99 static int mixenc = -1;
100 static int channels = 2;
101 static int inputch = 0;
102 static long rate = 44100;
103 static long inputrate = 0;
104 static double speed = 1.;
105 static long outputrate = 0;
106 static char *driver = NULL;
107 static char *device = NULL;
108 int also_stdout = FALSE;
109 size_t buffer_kb = 0;
110 static int realtime = FALSE;
111 #ifdef HAVE_WINDOWS_H
112 static int w32_priority = 0;
113 #endif
114 static int aggressive = FALSE;
115 static double preload = 0.2;
116 static long outflags = 0;
117 double preamp = 0.;
118 double preamp_factor = 1.;
119 double preamp_offset = 0.;
120 static const char *name = NULL; /* Let the out123 library choose "out123". */
121 static double device_buffer; /* output device buffer */
122 long timelimit_samples = -1;
123 double timelimit_seconds = -1.;
124 off_t offset = 0;
125 off_t timelimit = -1;
126 const char *clip_mode = "implicit";
127 int soft_clip = FALSE;
128 int do_clip = FALSE;
129 int do_filter = FALSE;
130 int do_preamp = FALSE;
131 int do_resample = FALSE;
132 int dither = 0;
133 double clip_limit = 1.;
134 double clip_width = 0.0234;
135
136 char *wave_patterns = NULL;
137 char *wave_freqs = NULL;
138 char *wave_phases = NULL;
139 char *wave_direction = NULL;
140 double sweep_freq = 0.;
141 double sweep_time = 0.;
142 int sweep_hard = 0;
143 long sweep_count = -1;
144 const char *sweep_type = "quad";
145 const char *signal_source = "file";
146 /* Default to around 2 MiB memory for the table. */
147 long wave_limit = 300000;
148 int pink_rows = 0;
149 double geiger_activity = 17;
150 char *resampler = "fine";
151
152 char *filter_spec = NULL;
153
154 size_t pcmblock = 1152; /* samples (pcm frames) we treat en bloc */
155 size_t resample_block = 0; /* resample that many samples in one go */
156 /* To be set after settling format. */
157 size_t pcmframe = 0; // Bytes for one PCM frame of output format.
158 size_t pcminframe = 0; // ... of input format
159 size_t mixframe = 0; // ... of mixing format
160 unsigned char *audio = NULL; // in/output buffer
161 unsigned char *inaudio = NULL; // separate input buffer
162 unsigned char *mixaudio = NULL; // separate mixing buffer
163 float *resaudio = NULL; // separate resampling buffer, always 32 bit float
164 char *mixmat_string = NULL;
165 double *mixmat = NULL;
166
167 // Option to play some oscillatory test signals.
168 // Also used for conversions.
169 syn123_handle *waver = NULL;
170 int generate = FALSE; // Wheter to use the syn123 generator.
171 // Input and output byte swappery.
172 long byte_in_flags = 0;
173 long byte_out_flags = 0;
174
175 out123_handle *ao = NULL;
176 char *cmd_name = NULL;
177 /* ThOr: pointers are not TRUE or FALSE */
178 char *equalfile = NULL;
179 int fresh = TRUE;
180
181 char *fullprogname = NULL; /* Copy of argv[0]. */
182 char *binpath; /* Path to myself. */
183
184 /* File-global storage of command line arguments.
185 They may be needed for cleanup after charset conversion. */
186 static char **argv = NULL;
187 static int argc = 0;
188
189 /* Drain output device/buffer, but still give the option to interrupt things. */
controlled_drain(void)190 static void controlled_drain(void)
191 {
192 int framesize;
193 long rate;
194 size_t drain_block;
195
196 if(intflag || !out123_buffered(ao))
197 return;
198 if(out123_getformat(ao, &rate, NULL, NULL, &framesize))
199 return;
200 drain_block = 1024*framesize;
201 if(!quiet)
202 fprintf( stderr
203 , "\n"ME": draining buffer of %.1f s (you may interrupt)\n"
204 , (double)out123_buffered(ao)/framesize/rate );
205 do {
206 out123_ndrain(ao, drain_block);
207 } while(!intflag && out123_buffered(ao));
208 }
209
safe_exit(int code)210 static void safe_exit(int code)
211 {
212 char *dummy, *dammy;
213
214 if(input && input != stdin)
215 compat_fclose(input);
216
217 if(!code)
218 controlled_drain();
219 if(intflag || code)
220 out123_drop(ao);
221 out123_del(ao);
222 #ifdef WANT_WIN32_UNICODE
223 win32_cmdline_free(argc, argv); /* This handles the premature argv == NULL, too. */
224 #endif
225 /* It's ugly... but let's just fix this still-reachable memory chunk of static char*. */
226 split_dir_file("", &dummy, &dammy);
227 if(fullprogname) free(fullprogname);
228 if(mixmat) free(mixmat);
229 if(inaudio && inaudio != audio) free(inaudio);
230 if(audio) free(audio);
231 if(mixaudio) free(mixaudio);
232 if(resaudio) free(resaudio);
233 if(waver) syn123_del(waver);
234 exit(code);
235 }
236
check_fatal_output(int code)237 static void check_fatal_output(int code)
238 {
239 if(code)
240 {
241 if(!quiet)
242 error2( "out123 error %i: %s"
243 , out123_errcode(ao), out123_strerror(ao) );
244 safe_exit(133);
245 }
246 }
247
check_fatal_syn(const char * step,int code)248 static void check_fatal_syn(const char *step, int code)
249 {
250 if(code)
251 {
252 if(!quiet)
253 merror("%s: syn123 error %i: %s", step, code, syn123_strerror(code));
254 safe_exit(132);
255 }
256 }
257
set_output_module(char * arg,topt * opts)258 static void set_output_module(char *arg, topt *opts)
259 {
260 unsigned int i;
261
262 /* Search for a colon and set the device if found */
263 for(i=0; i< strlen( arg ); i++) {
264 if (arg[i] == ':') {
265 arg[i] = 0;
266 getlopt_set_char(opts, "audiodevice", &arg[i+1]);
267 debug1("Setting output device: %s", device);
268 break;
269 }
270 }
271 /* Set the output module */
272 driver = arg;
273 debug1("Setting output module: %s", driver );
274 }
275
set_output_flag(int flag)276 static void set_output_flag(int flag)
277 {
278 if(outflags <= 0) outflags = flag;
279 else outflags |= flag;
280 }
281
set_output_h(char * a,topt * opts)282 static void set_output_h(char *a, topt *opts)
283 {
284 set_output_flag(OUT123_HEADPHONES);
285 }
286
set_output_s(char * a,topt * opts)287 static void set_output_s(char *a, topt *opts)
288 {
289 set_output_flag(OUT123_INTERNAL_SPEAKER);
290 }
291
set_output_l(char * a,topt * opts)292 static void set_output_l(char *a, topt *opts)
293 {
294 set_output_flag(OUT123_LINE_OUT);
295 }
296
set_output(char * arg,topt * opts)297 static void set_output(char *arg, topt *opts)
298 {
299 /* If single letter, it's the legacy output switch for AIX/HP/Sun.
300 If longer, it's module[:device] . If zero length, it's rubbish. */
301 if(strlen(arg) <= 1) switch(arg[0])
302 {
303 case 'h': set_output_h(arg, opts); break;
304 case 's': set_output_s(arg, opts); break;
305 case 'l': set_output_l(arg, opts); break;
306 default:
307 error1("\"%s\" is no valid output", arg);
308 safe_exit(1);
309 }
310 else set_output_module(arg, opts);
311 }
312
313 enum byteflags
314 {
315 byte_nothing = 0
316 , byte_native = 1
317 , byte_swap = 2
318 , byte_little = 4
319 , byte_big = 8
320 };
321
322 // Input has same endianess as output unless something was specified.
finish_endian(void)323 static void finish_endian(void)
324 {
325 long outbyte = byte_out_flags & (byte_big|byte_little|byte_native);
326 if(outbyte && !byte_in_flags)
327 byte_in_flags = outbyte;
328 }
329
set_endian(char * arg,long * flags)330 static void set_endian(char *arg, long *flags)
331 {
332 *flags &= ~(byte_big|byte_little|byte_native);
333 if(!strcmp(arg, "big"))
334 *flags |= byte_big;
335 else if(!strcmp(arg, "little"))
336 *flags |= byte_little;
337 else if(!strcmp(arg, "native"))
338 *flags |= byte_native;
339 else
340 merror("bad endianess choice: %s", arg);
341 }
342
set_in_endian(char * arg,topt * opts)343 static void set_in_endian(char *arg, topt *opts)
344 {
345 set_endian(arg, &byte_in_flags);
346 }
347
set_out_endian(char * arg,topt * opts)348 static void set_out_endian(char *arg, topt *opts)
349 {
350 set_endian(arg, &byte_out_flags);
351 }
352
set_byteswap(char * arg,topt * opts)353 static void set_byteswap(char *arg, topt *opts)
354 {
355 byte_out_flags |= byte_swap;
356 }
357
set_verbose(char * arg,topt * opts)358 static void set_verbose (char *arg, topt *opts)
359 {
360 verbose++;
361 }
362
set_quiet(char * arg,topt * opts)363 static void set_quiet (char *arg, topt *opts)
364 {
365 verbose=0;
366 quiet=TRUE;
367 }
368
set_out_wav(char * arg,topt * opts)369 static void set_out_wav(char *arg, topt *opts)
370 {
371 driver = "wav";
372 getlopt_set_char(opts, "audiodevice", arg);
373 }
374
set_out_cdr(char * arg,topt * opts)375 void set_out_cdr(char *arg, topt *opts)
376 {
377 driver = "cdr";
378 getlopt_set_char(opts, "audiodevice", arg);
379 }
380
set_out_au(char * arg,topt * opts)381 void set_out_au(char *arg, topt *opts)
382 {
383 driver = "au";
384 getlopt_set_char(opts, "audiodevice", arg);
385 }
386
set_out_test(char * arg,topt * opts)387 void set_out_test(char *arg, topt *opts)
388 {
389 driver = "test";
390 getlopt_set_char(opts, "audiodevice", NULL);
391 }
392
set_out_file(char * arg,topt * opts)393 static void set_out_file(char *arg, topt *opts)
394 {
395 driver = "raw";
396 getlopt_set_char(opts, "audiodevice", arg);
397 }
398
set_out_stdout(char * arg,topt * opts)399 static void set_out_stdout(char *arg, topt *opts)
400 {
401 driver = "raw";
402 getlopt_set_char(opts, "audiodevice", NULL);
403 }
404
set_out_stdout1(char * arg,topt * opts)405 static void set_out_stdout1(char *arg, topt *opts)
406 {
407 also_stdout = TRUE;
408 }
409
410 #if !defined (HAVE_SCHED_SETSCHEDULER) && !defined (HAVE_WINDOWS_H)
realtime_not_compiled(char * arg,topt * opts)411 static void realtime_not_compiled(char *arg, topt *opts)
412 {
413 fprintf(stderr, ME": Option '-T / --realtime' not compiled into this binary.\n");
414 }
415 #endif
416
list_output_modules(void)417 static void list_output_modules(void)
418 {
419 char **names = NULL;
420 char **descr = NULL;
421 int count = -1;
422 out123_handle *lao;
423
424 if((lao=out123_new()))
425 {
426 out123_param_string(lao, OUT123_BINDIR, binpath);
427 out123_param_int(lao, OUT123_VERBOSE, verbose);
428 if(quiet)
429 out123_param_int(lao, OUT123_FLAGS, OUT123_QUIET);
430 if((count=out123_drivers(lao, &names, &descr)) >= 0)
431 {
432 int i;
433 for(i=0; i<count; ++i)
434 {
435 printf( "%-15s\t%s\n", names[i], descr[i] );
436 free(names[i]);
437 free(descr[i]);
438 }
439 free(names);
440 free(descr);
441 }
442 out123_del(lao);
443 }
444 else if(!quiet)
445 error("Failed to create an out123 handle.");
446 exit(count >= 0 ? 0 : 1);
447 }
448
list_output_devices(void)449 static void list_output_devices(void)
450 {
451 int count = 0;
452 char **names = NULL;
453 char **descr = NULL;
454 out123_handle *ao = NULL;
455 ao = out123_new();
456 char *real_driver = NULL;
457 count = out123_devices(ao, driver, &names, &descr, &real_driver);
458 if(count >= 0)
459 {
460 printf("Devices for output module %s:\n", real_driver);
461 for(int i=0; i<count; ++i)
462 {
463 // Always print like it's a terminal to avoid confusion with extra line breaks.
464 print_outstr(stdout, names[i], 1, 1);
465 printf("\t");
466 print_outstr(stdout, descr[i], 1, 1);
467 printf("\n");
468 }
469 out123_stringlists_free(names, descr, count);
470 free(real_driver);
471 } else
472 {
473 merror("Failed to enumerate output devices: %s", out123_strerror(ao));
474 }
475 out123_del(ao);
476 exit(count < 0 ? 1 : 0);
477 }
478
list_encodings(char * arg,topt * opts)479 static void list_encodings(char *arg, topt *opts)
480 {
481 int i;
482 int enc_count = 0;
483 int *enc_codes = NULL;
484
485 enc_count = out123_enc_list(&enc_codes);
486 /* All of the returned encodings have to have proper names!
487 It is a libout123 bug if not, and it should be quickly caught. */
488 for(i=0;i<enc_count;++i)
489 printf( "%s:\t%s\n"
490 , out123_enc_name(enc_codes[i]), out123_enc_longname(enc_codes[i]) );
491 free(enc_codes);
492 exit(0);
493 }
494
getencs(void)495 static int getencs(void)
496 {
497 int encs = 0;
498 out123_handle *lao;
499 if(verbose)
500 fprintf( stderr
501 , ME": getting supported encodings for %li Hz, %i channels\n"
502 , rate, channels );
503 if((lao=out123_new()))
504 {
505 out123_param_int(lao, OUT123_VERBOSE, verbose);
506 if(quiet)
507 out123_param_int(lao, OUT123_FLAGS, OUT123_QUIET);
508 if(!out123_open(lao, driver, device))
509 encs = out123_encodings(lao, rate, channels);
510 else if(!quiet)
511 error1("cannot open driver: %s", out123_strerror(lao));
512 out123_del(lao);
513 }
514 else if(!quiet)
515 error("Failed to create an out123 handle.");
516 return encs;
517 }
518
test_format(char * arg,topt * opts)519 static void test_format(char *arg, topt *opts)
520 {
521 int encs;
522 encs = getencs();
523 exit((encs & encoding) ? 0 : -1);
524 }
525
test_encodings(char * arg,topt * opts)526 static void test_encodings(char *arg, topt *opts)
527 {
528 int encs, enc_count, *enc_codes, i;
529
530 encs = getencs();
531 enc_count = out123_enc_list(&enc_codes);
532 for(i=0;i<enc_count;++i)
533 {
534 if((encs & enc_codes[i]) == enc_codes[i])
535 printf("%s\n", out123_enc_name(enc_codes[i]));
536 }
537 free(enc_codes);
538 exit(!encs);
539 }
540
query_format(char * arg,topt * opts)541 static void query_format(char *arg, topt *opts)
542 {
543 out123_handle *lao;
544
545 if(verbose)
546 fprintf(stderr, ME": querying default format\n");
547 if((lao=out123_new()))
548 {
549 out123_param_int(lao, OUT123_VERBOSE, verbose);
550 if(quiet)
551 out123_param_int(lao, OUT123_FLAGS, OUT123_QUIET);
552 if(!out123_open(lao, driver, device))
553 {
554 struct mpg123_fmt *fmts = NULL;
555 int count;
556 count = out123_formats(lao, NULL, 0, 0, 0, &fmts);
557 if(count > 0 && fmts[0].encoding > 0)
558 {
559 const char *encname = out123_enc_name(fmts[0].encoding);
560 printf( "--rate %li --channels %i --encoding %s\n"
561 , fmts[0].rate, fmts[0].channels
562 , encname ? encname : "???" );
563 }
564 else
565 {
566 if(verbose)
567 fprintf(stderr, ME": no default format found\n");
568 }
569 free(fmts);
570 }
571 else if(!quiet)
572 error1("cannot open driver: %s", out123_strerror(lao));
573 out123_del(lao);
574 }
575 else if(!quiet)
576 error("Failed to create an out123 handle.");
577 exit(0);
578 }
579
set_wave_freqs(char * arg,topt * opts)580 void set_wave_freqs(char *arg, topt *opts)
581 {
582 getlopt_set_char(opts, "source", "wave");
583 wave_freqs = arg;
584 }
585
set_pink_rows(char * arg,topt * opts)586 void set_pink_rows(char *arg, topt *opts)
587 {
588 getlopt_set_char(opts, "source", "pink");
589 pink_rows = atoi(arg);
590 }
591
set_geiger_act(char * arg,topt * opts)592 void set_geiger_act(char *arg, topt *opts)
593 {
594 getlopt_set_char(opts, "source", "geiger");
595 geiger_activity = atof(arg);
596 }
597
set_sweep_freq(char * arg,topt * opts)598 void set_sweep_freq(char *arg, topt *opts)
599 {
600 getlopt_set_char(opts, "source", "sweep");
601 sweep_freq = atof(arg);
602 }
603
604 /* Please note: GLO_NUM expects point to LONG! */
605 /* ThOr:
606 * Yeah, and despite that numerous addresses to int variables were
607 passed.
608 * That's not good on my Alpha machine with int=32bit and long=64bit!
609 * Introduced GLO_INT and GLO_LONG as different bits to make that clear.
610 * GLO_NUM no longer exists.
611 */
612 topt opts[] = {
613 {'t', "test", GLO_INT, set_out_test, NULL, 0},
614 {'s', "stdout", GLO_INT, set_out_stdout, NULL, 0},
615 {'S', "STDOUT", GLO_INT, set_out_stdout1, NULL, 0},
616 {'O', "outfile", GLO_ARG | GLO_CHAR, set_out_file, NULL, 0},
617 {'v', "verbose", 0, set_verbose, 0, 0},
618 {'q', "quiet", 0, set_quiet, 0, 0},
619 {'m', "mono", GLO_INT, 0, &channels, 1},
620 {0, "stereo", GLO_INT, 0, &channels, 2},
621 {'c', "channels", GLO_ARG | GLO_INT, 0, &channels, 0},
622 {'C', "inputch", GLO_ARG | GLO_INT, 0, &inputch, 0},
623 {'M', "mix", GLO_ARG | GLO_CHAR, 0, &mixmat_string, 0},
624 {0, "filter", GLO_ARG | GLO_CHAR, 0, &filter_spec, 0},
625 {'P', "preamp", GLO_ARG | GLO_DOUBLE, 0, &preamp, 0},
626 {0, "offset", GLO_ARG | GLO_DOUBLE, 0, &preamp_offset, 0},
627 {'r', "rate", GLO_ARG | GLO_LONG, 0, &rate, 0},
628 {'R', "inputrate", GLO_ARG | GLO_LONG, 0, &inputrate, 0},
629 {0, "speed", GLO_ARG | GLO_DOUBLE, 0, &speed, 0},
630 {0, "clip", GLO_ARG | GLO_CHAR, 0, &clip_mode, 0},
631 {0, "dither", GLO_INT, 0, &dither, 1},
632 {0, "headphones", 0, set_output_h, 0,0},
633 {0, "speaker", 0, set_output_s, 0,0},
634 {0, "lineout", 0, set_output_l, 0,0},
635 {'o', "output", GLO_ARG | GLO_CHAR, set_output, 0, 0},
636 {0, "list-modules",GLO_INT, 0, &runmode, LIST_MODULES},
637 {0, "list-devices",GLO_INT, 0, &runmode, LIST_DEVICES},
638 {'a', "audiodevice", GLO_ARG | GLO_CHAR, 0, &device, 0},
639 #ifndef NOXFERMEM
640 {'b', "buffer", GLO_ARG | GLO_LONG, 0, &buffer_kb, 0},
641 {0, "preload", GLO_ARG|GLO_DOUBLE, 0, &preload, 0},
642 #endif
643 #ifdef HAVE_SETPRIORITY
644 {0, "aggressive", GLO_INT, 0, &aggressive, 2},
645 #endif
646 #if defined (HAVE_SCHED_SETSCHEDULER) || defined (HAVE_WINDOWS_H)
647 /* check why this should be a long variable instead of int! */
648 {'T', "realtime", GLO_INT, 0, &realtime, TRUE },
649 #else
650 {'T', "realtime", 0, realtime_not_compiled, 0, 0 },
651 #endif
652 #ifdef HAVE_WINDOWS_H
653 {0, "priority", GLO_ARG | GLO_INT, 0, &w32_priority, 0},
654 #endif
655 {'w', "wav", GLO_ARG | GLO_CHAR, set_out_wav, 0, 0 },
656 {0, "cdr", GLO_ARG | GLO_CHAR, set_out_cdr, 0, 0 },
657 {0, "au", GLO_ARG | GLO_CHAR, set_out_au, 0, 0 },
658 {'?', "help", 0, want_usage, 0, 0 },
659 {0 , "longhelp" , 0, want_long_usage, 0, 0 },
660 {0 , "version" , 0, give_version, 0, 0 },
661 {'e', "encoding", GLO_ARG|GLO_CHAR, 0, &encoding_name, 0},
662 {0, "endian", GLO_ARG|GLO_CHAR, set_out_endian, 0, 0},
663 {'E', "inputenc", GLO_ARG|GLO_CHAR, 0, &inputenc_name, 0},
664 {0, "inputend", GLO_ARG|GLO_CHAR, set_in_endian, 0, 0},
665 {0, "byteswap", 0, set_byteswap, 0, 0},
666 {0, "list-encodings", 0, list_encodings, 0, 0 },
667 {0, "test-format", 0, test_format, 0, 0 },
668 {0, "test-encodings", 0, test_encodings, 0, 0},
669 {0, "query-format", 0, query_format, 0, 0},
670 {0, "name", GLO_ARG|GLO_CHAR, 0, &name, 0},
671 {0, "devbuffer", GLO_ARG|GLO_DOUBLE, 0, &device_buffer, 0},
672 {0, "timelimit", GLO_ARG|GLO_LONG, 0, &timelimit_samples, 0},
673 {0, "seconds", GLO_ARG|GLO_DOUBLE, 0, &timelimit_seconds, 0},
674 {0, "source", GLO_ARG|GLO_CHAR, 0, &signal_source, 0},
675 {0, "wave-pat", GLO_ARG|GLO_CHAR, 0, &wave_patterns, 0},
676 {0, "wave-freq", GLO_ARG|GLO_CHAR, set_wave_freqs, 0, 0},
677 {0, "wave-phase", GLO_ARG|GLO_CHAR, 0, &wave_phases, 0},
678 {0, "wave-direction", GLO_ARG|GLO_CHAR, 0, &wave_direction, 0},
679 {0, "wave-limit", GLO_ARG|GLO_LONG, 0, &wave_limit, 0},
680 {0, "genbuffer", GLO_ARG|GLO_LONG, 0, &wave_limit, 0},
681 {0, "pink-rows", GLO_ARG|GLO_INT, set_pink_rows, 0, 0},
682 {0, "geiger-activity", GLO_ARG|GLO_DOUBLE, set_geiger_act, 0, 0},
683 {0, "wave-sweep", GLO_ARG|GLO_DOUBLE, set_sweep_freq, 0, 0},
684 {0, "sweep-type", GLO_ARG|GLO_CHAR, 0, &sweep_type, 0 },
685 {0, "sweep-time", GLO_ARG|GLO_DOUBLE, 0, &sweep_time, 0},
686 {0, "sweep-hard", GLO_INT, 0, &sweep_hard, TRUE},
687 {0, "sweep-count", GLO_ARG|GLO_LONG, 0, &sweep_count, 0},
688 {0, "resample", GLO_ARG|GLO_CHAR, 0, &resampler, 0},
689 {0, 0, 0, 0, 0, 0}
690 };
691
692 /* An strtok() that also returns empty tokens on multiple separators. */
693
mytok_count(const char * choppy)694 static size_t mytok_count(const char *choppy)
695 {
696 size_t count = 0;
697 if(choppy)
698 {
699 count = 1;
700 do {
701 if(*choppy == ',')
702 ++count;
703 } while(*(++choppy));
704 }
705 return count;
706 }
707
mytok(char ** choppy)708 static char *mytok(char **choppy)
709 {
710 char *tok;
711 if(!*choppy)
712 return NULL;
713 tok = *choppy;
714 while(**choppy && **choppy != ',')
715 ++(*choppy);
716 /* Another token follows if we found a separator. */
717 if(**choppy == ',')
718 {
719 *(*choppy)++ = 0;
720 while(isspace(**choppy))
721 *(*choppy)++ = 0;
722 }
723 else
724 *choppy = NULL; /* Nothing left. */
725 return tok;
726 }
727
setup_wavegen(void)728 static void setup_wavegen(void)
729 {
730 size_t count = 0;
731 size_t i;
732 double *freq = NULL;
733 double *freq_real = NULL;
734 double *phase = NULL;
735 int *backwards = NULL;
736 int *id = NULL;
737 int synerr = 0;
738 size_t common = 0;
739
740 if(!generate)
741 wave_limit = 0;
742 waver = syn123_new(inputrate, inputch, inputenc, wave_limit, &synerr);
743 check_fatal_syn("waver init", synerr);
744 check_fatal_syn("dither", syn123_dither(waver, dither, NULL));
745 if(!waver)
746 safe_exit(132);
747 if(do_resample)
748 {
749 int dirty = -1;
750 if(!strcasecmp(resampler, "fine"))
751 dirty = 0;
752 else if(!strcasecmp(resampler, "dirty"))
753 dirty = 1;
754 else
755 {
756 if(!quiet)
757 error1("Bad value for resampler type given: %s\n", resampler);
758 safe_exit(132);
759 }
760 check_fatal_syn( "resampling setup", syn123_setup_resample( waver
761 , inputrate, outputrate, channels, dirty, 0 ) );
762 }
763 if(do_filter)
764 {
765 size_t err_count = 0;
766 struct filterlist *fl = parse_filterspec(filter_spec);
767 if(!fl)
768 {
769 error1("Got no valid filter specification out of: %s", filter_spec);
770 safe_exit(135);
771 }
772 for(size_t fi=0; fi<fl->count; ++fi)
773 {
774 int err = syn123_setup_filter( waver, 1
775 , fl->f[fi].order, fl->f[fi].b, fl->f[fi].a
776 , mixenc, channels, 1 );
777 if(err)
778 {
779 merror("Cannot init filter %zu: %s", fi, syn123_strerror(err));
780 ++err_count;
781 }
782 }
783 free_filterlist(fl);
784 if(err_count)
785 {
786 merror("%zu errors during filter setup", err_count);
787 safe_exit(135);
788 }
789 }
790 // At least have waver handy for conversions.
791 if(!generate)
792 return;
793
794 if(!strcmp(signal_source, "pink"))
795 {
796 synerr = syn123_setup_pink(waver, pink_rows, 123456, &common);
797 if(synerr)
798 {
799 if(!quiet)
800 merror("setting up pink noise generator: %s\n", syn123_strerror(synerr));
801 safe_exit(132);
802 }
803 if(verbose)
804 {
805 fprintf( stderr
806 , ME ": pink noise with %i generator rows (0=internal default)\n"
807 , pink_rows );
808 }
809 goto setup_waver_end;
810 }
811 if(!strcmp(signal_source, "white"))
812 {
813 synerr = syn123_setup_white(waver, 123456, &common);
814 if(synerr)
815 {
816 if(!quiet)
817 merror("setting up white noise generator: %s\n", syn123_strerror(synerr));
818 safe_exit(132);
819 }
820 if(verbose)
821 {
822 fprintf( stderr, ME ": white noise\n" );
823 }
824 goto setup_waver_end;
825 }
826 else if(!strcmp(signal_source, "geiger"))
827 {
828 synerr = syn123_setup_geiger(waver, geiger_activity, 123456, &common);
829 if(synerr)
830 {
831 if(!quiet)
832 merror("setting up geiger generator: %s\n", syn123_strerror(synerr));
833 safe_exit(132);
834 }
835 if(verbose)
836 {
837 fprintf(stderr, ME ": geiger with actvity %g\n", geiger_activity);
838 }
839 goto setup_waver_end;
840 }
841 else if(!strcmp(signal_source, "sweep"))
842 {
843 double f1 = 0.;
844 double f2 = sweep_freq;
845 int wid = SYN123_WAVE_SINE;
846 int backwards = FALSE;
847 int sid = SYN123_SWEEP_QUAD;
848 // Yes, could overflow. You get a short time, then.
849 size_t duration = timelimit > -1 ? (size_t)timelimit : inputrate;
850 size_t period = 0;
851 double sweep_phase = 0.;
852 double endphase = -1;
853 if(sweep_type)
854 {
855 if(!strncmp("lin", sweep_type, 3))
856 sid = SYN123_SWEEP_LIN;
857 else if(!strncmp("qua", sweep_type, 3))
858 sid = SYN123_SWEEP_QUAD;
859 else if(!strncmp("exp", sweep_type, 3))
860 sid = SYN123_SWEEP_EXP;
861 else
862 {
863 if(!quiet)
864 merror("bad sweep choice: %s", sweep_type);
865 safe_exit(132);
866 }
867 }
868 if(wave_freqs)
869 {
870 char *next = wave_freqs;
871 f1 = atof(mytok(&next));
872 }
873 if(wave_patterns)
874 {
875 char *next = wave_patterns;
876 wid = syn123_wave_id(mytok(&next));
877 if(wid < 0 && !quiet)
878 fprintf(stderr, ME ": Warning: bad wave pattern: %s\n", wave_patterns);
879 }
880 if(wave_phases)
881 {
882 char *next = wave_phases;
883 sweep_phase = atof(mytok(&next));
884 if(sweep_phase < 0)
885 {
886 backwards = TRUE;
887 sweep_phase = -sweep_phase;
888 }
889 }
890 if(wave_direction)
891 {
892 char *next = wave_phases;
893 backwards = atof(mytok(&next)) < 0 ? TRUE : FALSE;
894 }
895 if(sweep_time > 0)
896 duration = (size_t)(sweep_time*inputrate);
897 synerr = syn123_setup_sweep( waver, wid, sweep_phase, backwards
898 , sid, &f1, &f2, !sweep_hard, duration, &endphase, &period, &common);
899 if(synerr)
900 {
901 if(!quiet)
902 merror("setting up sweep generator: %s\n", syn123_strerror(synerr));
903 safe_exit(132);
904 }
905 if(sweep_count > -1)
906 timelimit = sweep_count * period;
907 if(verbose)
908 {
909 fprintf( stderr, ME ": %s sweep of %zu samples (%s)\n"
910 , sweep_type
911 , (timelimit > -1 && timelimit < period) ? (size_t)timelimit : (size_t)period
912 , (timelimit > -1 && timelimit < period)
913 ? ((timelimit == duration) ? "exactly" : "cut off" )
914 : (sweep_hard ? "periodic with phase jumps" : "smoothly periodic") );
915 fprintf( stderr, ME ": from: %s @ %g Hz p %g\n"
916 , syn123_wave_name(wid), f1, sweep_phase );
917 fprintf( stderr, ME ": to: %s @ %g Hz p %g\n"
918 , syn123_wave_name(wid), f2
919 , (timelimit < 0 || timelimit >= period) ? sweep_phase : endphase );
920 }
921 goto setup_waver_end;
922 }
923 else if(strcmp(signal_source, "wave"))
924 {
925 if(!quiet)
926 merror("unknown signal source: %s", signal_source);
927 safe_exit(132);
928 }
929
930 // The big default code block is for wave setup.
931 // Exceptions jump over it.
932 if(wave_freqs)
933 {
934 char *tok;
935 char *next;
936 count = mytok_count(wave_freqs);
937 freq = malloc(sizeof(double)*count);
938 freq_real = malloc(sizeof(double)*count);
939 if(!freq || !freq_real){ error("OOM!"); safe_exit(1); }
940 next = wave_freqs;
941 for(i=0; i<count; ++i)
942 {
943 tok = mytok(&next);
944 if(tok && *tok)
945 freq[i] = atof(tok);
946 else if(i)
947 freq[i] = freq[i-1];
948 else
949 freq[i] = 0;
950 }
951 memcpy(freq_real, freq, sizeof(double)*count);
952 }
953 else if(wave_patterns || wave_phases || wave_direction)
954 {
955 if(!quiet)
956 fprintf( stderr
957 , ME ": Warning: wave setup ignored without specified frequency\n" );
958 }
959
960
961 if(count && wave_patterns)
962 {
963 char *tok;
964 char *next = wave_patterns;
965 id = malloc(sizeof(int)*count);
966 if(!id){ error("OOM!"); safe_exit(1); }
967 for(i=0; i<count; ++i)
968 {
969 tok = mytok(&next);
970 if((tok && *tok) || i==0)
971 {
972 id[i] = syn123_wave_id(tok);
973 if(id[i] < 0 && !quiet)
974 fprintf(stderr, ME ": Warning: bad wave pattern: %s\n", tok);
975 }
976 else
977 id[i] = id[i-1];
978 }
979 }
980
981 if(count && wave_phases)
982 {
983 char *tok;
984 char *next = wave_phases;
985 phase = malloc(sizeof(double)*count);
986 backwards = malloc(sizeof(int)*count);
987 if(!phase || !backwards){ error("OOM!"); safe_exit(1); }
988 for(i=0; i<count; ++i)
989 {
990 tok = mytok(&next);
991 if(tok && *tok)
992 phase[i] = atof(tok);
993 else if(i)
994 phase[i] = phase[i-1];
995 else
996 phase[i] = 0;
997 if(phase[i] < 0)
998 {
999 phase[i] *= -1;
1000 backwards[i] = TRUE;
1001 }
1002 else
1003 backwards[i] = FALSE;
1004 }
1005 }
1006
1007 if(count && wave_direction)
1008 {
1009 char *tok;
1010 char *next = wave_direction;
1011 if(!backwards)
1012 backwards = malloc(sizeof(int)*count);
1013 if(!backwards){ error("OOM!"); safe_exit(1); }
1014 for(i=0; i<count; ++i)
1015 {
1016 tok = mytok(&next);
1017 if(tok && *tok)
1018 backwards[i] = atof(tok) < 0 ? TRUE : FALSE;
1019 else if(i)
1020 backwards[i] = backwards[i-1];
1021 else
1022 backwards[i] = FALSE;
1023 }
1024 }
1025
1026 synerr = syn123_setup_waves( waver, count
1027 , id, freq_real, phase, backwards, &common );
1028 if(synerr)
1029 {
1030 if(!quiet)
1031 merror("setting up wave generator: %s\n", syn123_strerror(synerr));
1032 safe_exit(132);
1033 }
1034 if(verbose)
1035 {
1036 if(count) for(i=0; i<count; ++i)
1037 fprintf( stderr, ME ": wave %zu: %s @ %g Hz (%g Hz) p %g\n"
1038 , i
1039 , syn123_wave_name(id ? id[i] : SYN123_WAVE_SINE)
1040 , freq[i], freq_real[i]
1041 , phase ? phase[i] : 0 );
1042 else
1043 fprintf(stderr, ME ": default sine wave\n");
1044 }
1045
1046 setup_waver_end:
1047 if(verbose)
1048 {
1049 if(common)
1050 fprintf(stderr, ME ": periodic signal table of %zu samples\n", common);
1051 else
1052 fprintf(stderr, ME ": live signal generation\n");
1053 }
1054 if(phase)
1055 free(phase);
1056 if(id)
1057 free(id);
1058 if(freq)
1059 free(freq);
1060 if(freq_real)
1061 free(freq_real);
1062 }
1063
1064
push_output(unsigned char * buf,size_t samples)1065 void push_output(unsigned char *buf, size_t samples)
1066 {
1067 errno = 0;
1068 size_t bytes = samples*pcmframe;
1069
1070 if(byte_out_flags & byte_big)
1071 syn123_host2be( buf, pcmframe/channels, samples*channels);
1072 if(byte_out_flags & byte_little)
1073 syn123_host2le( buf, pcmframe/channels, samples*channels);
1074 if(byte_out_flags & byte_swap)
1075 syn123_swap_bytes(buf, pcmframe/channels, samples*channels);
1076
1077 mdebug("playing %zu bytes", bytes);
1078 check_fatal_output(out123_play(ao, buf, bytes) < (int)bytes);
1079 if(also_stdout && unintr_fwrite(buf, pcmframe, samples, stdout) < samples)
1080 {
1081 if(!quiet)
1082 error1( "failed to copy stream to stdout: %s", strerror(errno));
1083 safe_exit(133);
1084 }
1085 }
1086
1087 // Clipping helper, called with mixbuf, resampler buffer, playback buffer ...
1088 // This implies the output channel count.
clip(void * buf,int enc,size_t samples)1089 void clip(void *buf, int enc, size_t samples)
1090 {
1091 size_t clipped = soft_clip
1092 ? syn123_soft_clip( buf, enc, samples*channels
1093 , clip_limit, clip_width, waver )
1094 : syn123_clip(buf, enc, samples*channels);
1095 if(verbose > 1 && clipped)
1096 fprintf(stderr, ME ": explicitly clipped %zu samples\n", clipped);
1097 }
1098
1099 static int had_something = 0;
1100 static int just_stdin = 0;
open_next_file(int argc,char ** argv,int firstrun)1101 FILE* open_next_file(int argc, char** argv, int firstrun)
1102 {
1103 FILE *in = NULL;
1104 if(firstrun && loptind >= argc)
1105 {
1106 just_stdin = 1;
1107 had_something = 1;
1108 in = stdin;
1109 } else
1110 while(!in && loptind < argc)
1111 {
1112 char *filename = argv[loptind++];
1113 errno = 0;
1114 in = strcmp(filename, "-") ? compat_fopen(filename, "rb") : stdin;
1115 if(!in)
1116 merror( "Failed to open input file '%s' (%s), ignoring."
1117 , filename, strerror(errno) );
1118 else
1119 had_something = 1;
1120 }
1121 return in;
1122 }
1123
1124 /* return 1 on success, 0 on failure */
play_frame(void)1125 int play_frame(void)
1126 {
1127 size_t got_samples = 0;
1128 size_t get_samples = pcmblock;
1129 debug("play_frame");
1130 if(timelimit >= 0)
1131 {
1132 if(offset >= timelimit)
1133 return 0;
1134 else if(timelimit < offset+get_samples)
1135 get_samples = (off_t)timelimit-offset;
1136 }
1137 if(generate)
1138 got_samples = syn123_read(waver, inaudio, get_samples*pcminframe)
1139 / pcminframe;
1140 else
1141 got_samples = input ? fread(inaudio, pcminframe, get_samples, input) : 0;
1142 /* Play what is there to play (starting with second decode_frame call!) */
1143 if(!got_samples)
1144 return 0;
1145
1146 if(byte_in_flags & byte_big)
1147 syn123_be2host(inaudio, pcminframe/channels, got_samples*inputch);
1148 if(byte_in_flags & byte_little)
1149 syn123_le2host(inaudio, pcminframe/channels, got_samples*inputch);
1150
1151 if(mixaudio)
1152 {
1153 // All complicated cases trigger mixing/conversion into intermediate
1154 // buffer.
1155 // First either mix or convert into the mixing buffer.
1156 if(mixmat)
1157 check_fatal_syn("buffer mix", syn123_mix( mixaudio, mixenc, channels
1158 , inaudio, inputenc, inputch, mixmat, got_samples, TRUE, NULL, waver ));
1159 else
1160 check_fatal_syn("buffer conv", syn123_conv( mixaudio, mixenc, got_samples*mixframe
1161 , inaudio, inputenc, got_samples*pcminframe, NULL, NULL, waver ));
1162 // Apply filters.
1163 if(do_filter)
1164 check_fatal_syn("buffer filter", syn123_filter( waver, mixaudio, mixenc, got_samples ));
1165 // Do pre-amplification in-place.
1166 if(do_preamp)
1167 check_fatal_syn("buffer amp", syn123_amp( mixaudio, mixenc, got_samples*channels
1168 , preamp_factor, preamp_offset, NULL, NULL ));
1169 // Resampling needs another buffer.
1170 if(do_resample)
1171 {
1172 // Resampling, clipping, and conversion to end buffer in a loop
1173 // of small blocks since resampling can mean a lot of output from tiny
1174 // input.
1175 // Mixaudio has to carry 32 bit float!
1176 float * fmixaudio = (float*)mixaudio;
1177 size_t insamples = got_samples;
1178 size_t inoff = 0;
1179 while(insamples)
1180 {
1181 size_t inblock = insamples < resample_block
1182 ? insamples
1183 : resample_block;
1184 debug("resample");
1185 size_t outsamples = syn123_resample( waver
1186 , resaudio, fmixaudio+inoff*channels, inblock );
1187 debug("clip?");
1188 if(do_clip)
1189 clip(resaudio, MPG123_ENC_FLOAT_32, outsamples);
1190 // Damn, another loop inside the loop for a smaller output buffer?!
1191 // No. I will ensure pcmblock being as large as the largest to be
1192 // expected resampling block output!
1193 size_t clipped = 0;
1194 debug("conv");
1195 check_fatal_syn("buffer resample conv", syn123_conv( audio, encoding, outsamples*pcmframe
1196 , resaudio, MPG123_ENC_FLOAT_32, outsamples*sizeof(float)*channels
1197 , NULL, &clipped, waver ));
1198 if(verbose > 1 && clipped)
1199 fprintf(stderr, ME ": clipped %zu samples\n", clipped);
1200 // Finally, some output!
1201 push_output(audio, outsamples);
1202 // Advance.
1203 insamples -= inblock;
1204 inoff += inblock;
1205 if(intflag)
1206 return 1; // 1 or 0? Does it matter?
1207 }
1208 } else
1209 {
1210 // Just handle explicit clipping and do final conversion.
1211 if(do_clip)
1212 clip(mixaudio, mixenc, got_samples);
1213 // Finally, convert to output.
1214 size_t clipped = 0;
1215 check_fatal_syn("buffer conv", syn123_conv( audio, encoding, got_samples*pcmframe
1216 , mixaudio, mixenc, got_samples*mixframe, NULL, &clipped, waver ));
1217 if(verbose > 1 && clipped)
1218 fprintf(stderr, ME ": clipped %zu samples\n", clipped);
1219 }
1220 } else
1221 {
1222 size_t clipped = 0;
1223 // No separate mixing buffer, but possibly some mixing or conversion
1224 // directly into the output buffer. This path should only be taken if
1225 // there is either only one operation happening, or if the output
1226 // is in floating point encoding which makes intermediate conversions
1227 // unnecessary. The path should still be correct for other cases, just
1228 // slow and with suboptimal quality.
1229 if(inaudio != audio)
1230 {
1231 if(mixmat)
1232 {
1233 check_fatal_syn("direct mix", syn123_mix( audio, encoding, channels
1234 , inaudio, inputenc, inputch, mixmat, got_samples, TRUE, &clipped
1235 , waver ));
1236 } else
1237 {
1238 check_fatal_syn("direct conv", syn123_conv( audio, encoding, got_samples*pcmframe
1239 , inaudio, inputenc, got_samples*pcminframe, NULL, &clipped
1240 , waver ));
1241 }
1242 }
1243 if(do_preamp)
1244 {
1245 check_fatal_syn("preamp", syn123_amp (audio, encoding, got_samples*channels
1246 , preamp_factor, preamp_offset, &clipped, waver ));
1247 if(verbose > 1 && clipped)
1248 fprintf(stderr, ME ": clipped %zu samples\n", clipped);
1249 }
1250 if(do_clip)
1251 clip(audio, encoding, got_samples);
1252 }
1253
1254 // To recap: Without any conversion, the simplest code path has
1255 // optional preamp and possibly clipping, but only one of those.
1256 // The next stage is a combination, mixing or conversion before
1257 // those. If resampling is desired, the complex
1258 // code path with mixing buffer and resampling buffer is chosen, with
1259 // all the other bits. Soft clipping is probably a default with resampling,
1260 // for integer output. Also, if soft clip and preamp is desired for
1261 // integer output, this also triggers the complex code path. I rather
1262 // create separate copies than to convert from/to integers multiple
1263 // times.
1264
1265 // The resampling loop triggers its own output. All other
1266 // paths want output of the prepared data here.
1267 if(!do_resample)
1268 push_output(audio, got_samples);
1269 offset += got_samples;
1270 return 1;
1271 }
1272
1273 #if !defined(WIN32) && !defined(GENERIC)
catch_interrupt(void)1274 static void catch_interrupt(void)
1275 {
1276 intflag = TRUE;
1277 }
1278 #endif
1279
fatal_malloc(size_t bytes)1280 static void *fatal_malloc(size_t bytes)
1281 {
1282 void *buf;
1283 if(!(buf = malloc(bytes)))
1284 {
1285 if(!quiet)
1286 error("OOM");
1287 safe_exit(1);
1288 }
1289 return buf;
1290 }
1291
1292 // Prepare all the buffers and some of the flags for the processing chain.
1293 // The goal is to avoid unnecessary copies and format conversions.
1294 // If we do multiple operations on the intermediate data, it gets a separate
1295 // buffer in floating point encoding. If there is not much to do, this
1296 // intermediate copy is skipped.
setup_processing(void)1297 static void setup_processing(void)
1298 {
1299 pcminframe = out123_encsize(inputenc)*inputch;
1300 pcmframe = out123_encsize(encoding)*channels;
1301 size_t resample_out = 0;
1302
1303 unsigned int op_count = 0;
1304
1305 // Full mixing is initiated if channel counts differ or a non-empty
1306 // mixing matrix has been specified.
1307 if(inputch != channels || (mixmat_string && mixmat_string[0]))
1308 {
1309 mixmat = fatal_malloc(sizeof(double)*inputch*channels);
1310 size_t mmcount = (mixmat_string && mixmat_string[0])
1311 ? mytok_count(mixmat_string)
1312 : 0;
1313 // Special cases of trivial down/upmixing need no user input.
1314 if(mmcount == 0 && inputch == 1)
1315 {
1316 for(int oc=0; oc<channels; ++oc)
1317 mixmat[oc] = 1.;
1318 }
1319 else if(mmcount == 0 && channels == 1)
1320 {
1321 for(int ic=0; ic<inputch; ++ic)
1322 mixmat[ic] = 1./inputch;
1323 }
1324 else if(mmcount != inputch*channels)
1325 {
1326 merror( "Need %i mixing matrix entries, got %zu."
1327 , inputch*channels, mmcount );
1328 safe_exit(1);
1329 } else
1330 {
1331 char *next = mixmat_string;
1332 for(int i=0; i<inputch*channels; ++i)
1333 {
1334 char *tok = mytok(&next);
1335 mixmat[i] = tok ? atof(tok) : 0.;
1336 }
1337 }
1338 }
1339
1340 if(inputrate != outputrate)
1341 {
1342 do_resample = TRUE;
1343 ++op_count;
1344 // Buffer computations only make sense if resampling possibly can
1345 // be set up at all.
1346 if( inputrate > syn123_resample_maxrate()
1347 || outputrate > syn123_resample_maxrate() )
1348 {
1349 error("Sampling rates out of range for the resampler.");
1350 safe_exit(134);
1351 }
1352 // Settle resampling block size, which determines the resampling
1353 // buffer size.
1354 // First attempt: Try if pcmblock input yields a reasonable
1355 // number of samples/frames for the resampling output.
1356 // if it is too large, reduce until we are below a threshold.
1357 // How big should the threshold be? When I say 10 times pcmblock ...
1358 // I still to the channel count as variable ... but let's say that.
1359 // Then the baddest resampling ratio that could barely work is about
1360 // 1:10000. That's quite generous. Even fixing things at pcmblock
1361 // max in the output would still be ok for factors close to 1000.
1362 // Well, let's try this to stay reasonable: limit to 10*pcmblock
1363 // at first. If that is not enough, reduce resample_block down to
1364 // 100 samples or so, to avoid too degenerate situations. If
1365 // that lower limit of resample_block is reached and still produces
1366 // more than 10*pcmblock output, it is attempted to just allocate
1367 // that bigger buffer. If you have the memory, you can choose the
1368 // rates. Reasonable resampling tasks should be well within the
1369 // factor 10 allowed for by default.
1370 // Another question: Should I try to increase pcmblock for the case of
1371 // extreme downsampling? This is just a matter of efficiency, having
1372 // lots of code only producing a single sample now and then, the
1373 // block treatment in libsyn123 not getting active.
1374 resample_block = pcmblock;
1375 while( (resample_out = syn123_resample_count( inputrate, outputrate
1376 , resample_block )) > 10*pcmblock)
1377 resample_block /= 2;
1378 if(resample_block < 128)
1379 {
1380 resample_block = 128;
1381 resample_out = syn123_resample_count(inputrate, outputrate, resample_block);
1382 }
1383 if(verbose)
1384 fprintf( stderr, ME": resampling %zu samples @ %ld Hz"
1385 " to up to %zu samples @ %ld Hz\n", resample_block, inputrate
1386 , resample_out, outputrate );
1387 if(!resample_out)
1388 {
1389 error("Cannot compute resampler output count.");
1390 safe_exit(134);
1391 }
1392 // Now we got some number of resampler output samples.
1393 // That buffer will always be big enough when handing in resample_block.
1394 resaudio = fatal_malloc(resample_out*sizeof(float)*channels);
1395 }
1396
1397 audio = fatal_malloc((resample_out>pcmblock ? resample_out : pcmblock)*pcmframe);
1398
1399 // If converting or mixing, use separate input buffer.
1400 if(inputenc != encoding || mixmat)
1401 {
1402 inaudio = fatal_malloc(pcmblock*pcminframe);
1403 ++op_count; // conversion or mixing
1404 }
1405 else
1406 inaudio = audio;
1407
1408 if(preamp != 0. || preamp_offset != 0.)
1409 {
1410 preamp_factor = syn123_db2lin(preamp);
1411 // Store limited value for proper reporting.
1412 preamp = syn123_lin2db(preamp_factor);
1413 if(preamp_offset == 0. && mixmat)
1414 {
1415 // If we are mixing already, just include preamp in this.
1416 for(int i=0; i<inputch*channels; ++i)
1417 mixmat[i] *= preamp_factor;
1418 preamp_factor = 1.;
1419 }
1420 do_preamp = TRUE;
1421 ++op_count;
1422 }
1423
1424 do_clip = FALSE;
1425 if(!strcasecmp(clip_mode, "soft"))
1426 {
1427 do_clip = TRUE;
1428 soft_clip = TRUE;
1429 }
1430 else if(!strcasecmp(clip_mode, "hard"))
1431 {
1432 if(encoding & MPG123_ENC_FLOAT)
1433 do_clip = TRUE;
1434 soft_clip = FALSE;
1435 }
1436 else if(strcasecmp(clip_mode, "implicit"))
1437 {
1438 if(!quiet)
1439 error1("Bad value for clipping mode given: %s\n", clip_mode);
1440 safe_exit(135);
1441 }
1442 if(do_clip)
1443 ++op_count;
1444
1445 if(filter_spec && *filter_spec)
1446 {
1447 do_filter = TRUE;
1448 ++op_count;
1449 }
1450
1451 if(do_filter || do_resample || op_count > 1)
1452 {
1453 // Create a separate mixing buffer for the complicated cases.
1454 // Resampling limits quality to 32 bits float anyway, so avoid
1455 // trying to mix in double.
1456 debug("employing separate mixing buffer");
1457 mixenc = do_resample
1458 ? MPG123_ENC_FLOAT_32
1459 : syn123_mixenc(inputenc, encoding);
1460 mixframe = out123_encsize(mixenc)*channels;
1461 mixaudio = fatal_malloc(mixframe*pcmblock);
1462 }
1463 }
1464
1465
main(int sys_argc,char ** sys_argv)1466 int main(int sys_argc, char ** sys_argv)
1467 {
1468 int result;
1469 #if defined(WIN32)
1470 _setmode(STDIN_FILENO, _O_BINARY);
1471 #endif
1472 check_locale();
1473
1474 #if defined (WANT_WIN32_UNICODE)
1475 if(win32_cmdline_utf8(&argc, &argv) != 0)
1476 {
1477 error("Cannot convert command line to UTF8!");
1478 safe_exit(76);
1479 }
1480 #else
1481 argv = sys_argv;
1482 argc = sys_argc;
1483 #endif
1484
1485 if(!(fullprogname = compat_strdup(argv[0])))
1486 {
1487 error("OOM"); /* Out Of Memory. Don't waste bytes on that error. */
1488 safe_exit(1);
1489 }
1490 /* Extract binary and path, take stuff before/after last / or \ . */
1491 if( (cmd_name = strrchr(fullprogname, '/'))
1492 || (cmd_name = strrchr(fullprogname, '\\')))
1493 {
1494 /* There is some explicit path. */
1495 cmd_name[0] = 0; /* End byte for path. */
1496 cmd_name++;
1497 binpath = fullprogname;
1498 }
1499 else
1500 {
1501 cmd_name = fullprogname; /* No path separators there. */
1502 binpath = NULL; /* No path at all. */
1503 }
1504
1505 /* Get default flags. */
1506 {
1507 out123_handle *paro = out123_new();
1508 out123_getparam_int(paro, OUT123_FLAGS, &outflags);
1509 out123_del(paro);
1510 }
1511
1512 #ifdef OS2
1513 _wildcard(&argc,&argv);
1514 #endif
1515
1516 stderr_is_term = term_width(STDERR_FILENO) >= 0;
1517 stdout_is_term = term_width(STDOUT_FILENO) >= 0;
1518 while ((result = getlopt(argc, argv, opts)))
1519 switch (result) {
1520 case GLO_UNKNOWN:
1521 fprintf (stderr, ME": invalid argument: %s\n", loptarg);
1522 usage(1);
1523 case GLO_NOARG:
1524 fprintf (stderr, ME": missing argument for parameter: %s\n", loptarg);
1525 usage(1);
1526 }
1527 finish_endian();
1528 mdebug("input byte flags: %ld, output byte flags: %ld", byte_in_flags, byte_out_flags);
1529
1530 if(quiet)
1531 verbose = 0;
1532
1533 switch(runmode)
1534 {
1535 case RUN_MAIN:
1536 break;
1537 case LIST_MODULES:
1538 list_output_modules();
1539 case LIST_DEVICES:
1540 list_output_devices();
1541 default:
1542 merror("Invalid run mode %d", runmode);
1543 safe_exit(79);
1544 }
1545
1546 if(inputrate < 1)
1547 inputrate = rate;
1548 outputrate = -1;
1549 if(speed > 0)
1550 { // Compute rate from speed and safely convert to long.
1551 double outputrater = (1./speed) * rate;
1552 double limit = (double)syn123_resample_maxrate();
1553 double diff = 1;
1554 // LONG_MAX will likely be rounded in the conversion to float.
1555 // Ensure that the resulting limit is _smaller_ by subtracting
1556 // until we see a rounding step down.
1557 while((limit-diff) == limit)
1558 diff *= 2;
1559 limit -= diff;
1560 if(outputrater+0.5 > limit)
1561 outputrate = syn123_resample_maxrate();
1562 else if(outputrater > 0)
1563 outputrate = (long)(outputrater+0.5);
1564 }
1565 if(outputrate < 1)
1566 {
1567 fprintf(stderr, ME": no valid output rate with given speed and input rate\n");
1568 exit(1);
1569 }
1570 /* Ensure cleanup before we cause too much mess. */
1571 #if !defined(WIN32) && !defined(GENERIC)
1572 catchsignal(SIGINT, catch_interrupt);
1573 catchsignal(SIGTERM, catch_interrupt);
1574 #endif
1575 ao = out123_new();
1576 if(!ao){ error("Failed to allocate output."); exit(1); }
1577
1578 if
1579 ( 0
1580 || out123_param_int(ao, OUT123_FLAGS, outflags)
1581 || out123_param_float(ao, OUT123_PRELOAD, preload)
1582 || out123_param_int(ao, OUT123_VERBOSE, verbose)
1583 || out123_param_string(ao, OUT123_NAME, name)
1584 || out123_param_string(ao, OUT123_BINDIR, binpath)
1585 || out123_param_float(ao, OUT123_DEVICEBUFFER, device_buffer)
1586 )
1587 {
1588 error("Error setting output parameters. Do you need a usage reminder?");
1589 usage(1);
1590 }
1591
1592 #ifdef HAVE_SETPRIORITY
1593 if(aggressive) { /* tst */
1594 int mypid = getpid();
1595 if(!quiet) fprintf(stderr, ME": Aggressively trying to increase priority.\n");
1596 if(setpriority(PRIO_PROCESS,mypid,-20))
1597 error("Failed to aggressively increase priority.\n");
1598 }
1599 #endif
1600
1601 #if defined (HAVE_SCHED_SETSCHEDULER) && !defined (__CYGWIN__) && !defined (HAVE_WINDOWS_H)
1602 /* Cygwin --realtime seems to fail when accessing network, using win32 set priority instead */
1603 /* MinGW may have pthread installed, we prefer win32API */
1604 if(realtime)
1605 { /* Get real-time priority */
1606 struct sched_param sp;
1607 if(!quiet) fprintf(stderr, ME": Getting real-time priority\n");
1608 memset(&sp, 0, sizeof(struct sched_param));
1609 sp.sched_priority = sched_get_priority_min(SCHED_FIFO);
1610 if (sched_setscheduler(0, SCHED_RR, &sp) == -1)
1611 error("Can't get realtime priority\n");
1612 }
1613 #endif
1614
1615 /* make sure not Cygwin, it doesn't need it */
1616 #if defined(WIN32) && defined(HAVE_WINDOWS_H)
1617 /* argument "3" is equivalent to realtime priority class */
1618 win32_set_priority(realtime ? 3 : w32_priority);
1619 #endif
1620
1621 if(encoding_name)
1622 {
1623 encoding = out123_enc_byname(encoding_name);
1624 if(encoding < 0)
1625 {
1626 error1("Unknown encoding '%s' given!\n", encoding_name);
1627 safe_exit(1);
1628 }
1629 }
1630
1631 if(strcmp(signal_source, "file"))
1632 generate = TRUE;
1633 else
1634 input = open_next_file(argc, argv, 1);
1635
1636 // Genererally generate signal in floating point for later conversion
1637 // after possible additional processing.
1638 inputenc = generate && encoding != MPG123_ENC_FLOAT_64
1639 ? MPG123_ENC_FLOAT_32
1640 : encoding;
1641 // User can override.
1642 if(inputenc_name)
1643 {
1644 inputenc = out123_enc_byname(inputenc_name);
1645 if(inputenc < 0)
1646 {
1647 error1("Unknown input encoding '%s' given!\n", inputenc_name);
1648 safe_exit(1);
1649 }
1650 }
1651 if(!inputch)
1652 inputch = channels;
1653
1654 // Settle buffers and the mixing/conversion code path.
1655 setup_processing();
1656 check_fatal_output(out123_set_buffer(ao, buffer_kb*1024));
1657 check_fatal_output(out123_open(ao, driver, device));
1658
1659 if(timelimit_seconds >= 0.)
1660 timelimit = timelimit_seconds*inputrate;
1661 if(timelimit_samples >= 0)
1662 timelimit = timelimit_samples;
1663
1664 if(verbose)
1665 {
1666 long props = 0;
1667 const char *encname;
1668 char *realname = NULL;
1669 if(inaudio != audio)
1670 {
1671 encname = out123_enc_name(inputenc);
1672 fprintf( stderr, ME": input format: %li Hz, %i channels, %s\n"
1673 , inputrate, inputch, encname ? encname : "???" );
1674 encname = out123_enc_name(syn123_mixenc(inputenc, encoding));
1675 if(mixmat)
1676 {
1677 fprintf( stderr, ME": mixing in %s\n", encname ? encname : "???" );
1678 for(int oc=0; oc<channels; ++oc)
1679 {
1680 fprintf(stderr, ME": out ch %i mix:", oc);
1681 for(int ic=0; ic<inputch; ++ic)
1682 fprintf(stderr, " %6.2f", mixmat[SYN123_IOFF(oc,ic,inputch)]);
1683 fprintf(stderr, "\n");
1684 }
1685 }
1686 else
1687 fprintf( stderr, ME": converting via %s\n", encname ? encname : "???" );
1688 }
1689 if(outputrate != rate)
1690 fprintf( stderr, ME": virtual output rate %li for actual speed %g\n"
1691 , outputrate, (double)rate/outputrate );
1692 encname = out123_enc_name(encoding);
1693 fprintf(stderr, ME": format: %li Hz, %i channels, %s\n"
1694 , rate, channels, encname ? encname : "???" );
1695 if(preamp != 0.)
1696 fprintf( stderr, ME": preamp: %.1f dB%s\n", preamp
1697 , preamp_factor != 1. ? "" : " (during mixing)" );
1698 if(preamp_offset != 0.)
1699 fprintf(stderr, ME": applying scaled offset: %f\n", preamp_offset);
1700 out123_getparam_string(ao, OUT123_NAME, &realname);
1701 if(realname)
1702 fprintf(stderr, ME": output real name: %s\n", realname);
1703 out123_getparam_int(ao, OUT123_PROPFLAGS, &props);
1704 if(props & OUT123_PROP_LIVE)
1705 fprintf(stderr, ME": This is a live sink.\n");
1706 }
1707 check_fatal_output(out123_start(ao, rate, channels, encoding));
1708
1709 setup_wavegen(); // Used also for conversion/mixing.
1710
1711 do
1712 {
1713 while(play_frame() && !intflag)
1714 {
1715 /* be happy */
1716 }
1717 if(!intflag && !generate && !just_stdin)
1718 {
1719 if(input && input != stdin)
1720 compat_fclose(input);
1721 input = open_next_file(argc, argv, 0);
1722 }
1723 } while(!intflag && !generate && input && !just_stdin);
1724 if(intflag) /* Make it quick! */
1725 {
1726 if(!quiet)
1727 fprintf(stderr, ME": Interrupted. Dropping the ball.\n");
1728 out123_drop(ao);
1729 }
1730
1731 safe_exit(had_something ? 0 : 2); /* That closes output and restores terminal, too. */
1732 return 0;
1733 }
1734
output_enclist(void)1735 static char* output_enclist(void)
1736 {
1737 int i;
1738 char *list = NULL;
1739 char *pos;
1740 size_t len = 0;
1741 int enc_count = 0;
1742 int *enc_codes = NULL;
1743
1744 enc_count = out123_enc_list(&enc_codes);
1745 if(enc_count < 0 || !enc_codes)
1746 return NULL;
1747 for(i=0;i<enc_count;++i)
1748 len += strlen(out123_enc_name(enc_codes[i]));
1749 len += enc_count;
1750
1751 if((pos = list = malloc(len))) for(i=0;i<enc_count;++i)
1752 {
1753 const char *name = out123_enc_name(enc_codes[i]);
1754 if(i>0)
1755 *(pos++) = ' ';
1756 strcpy(pos, name);
1757 pos+=strlen(name);
1758 }
1759 free(enc_codes);
1760 return list;
1761 }
1762
print_title(FILE * o)1763 static void print_title(FILE *o)
1764 {
1765 fprintf(o, "Simple audio output with raw PCM input\n");
1766 fprintf(o, "\tversion %s; derived from mpg123 by Michael Hipp and others\n", PACKAGE_VERSION);
1767 fprintf(o, "\tfree software (LGPL) without any warranty but with best wishes\n");
1768 }
1769
usage(int err)1770 static void usage(int err) /* print syntax & exit */
1771 {
1772 FILE* o = stdout;
1773 if(err)
1774 {
1775 o = stderr;
1776 fprintf(o, ME": You made some mistake in program usage... let me briefly remind you:\n\n");
1777 }
1778 print_title(o);
1779 fprintf(o,"\nusage: %s [option(s)] [file(s) | URL(s) | -]\n", cmd_name);
1780 fprintf(o,"supported options [defaults in brackets]:\n");
1781 fprintf(o," -v increase verbosity level -q quiet (only print errors)\n");
1782 fprintf(o," -t testmode (no output) -s write to stdout\n");
1783 fprintf(o," -w f write output as WAV file\n");
1784 fprintf(o," -b n output buffer: n Kbytes [0] \n");
1785 fprintf(o," -r n set samplerate [44100]\n");
1786 fprintf(o," -o m select output module -a d set audio device\n");
1787 fprintf(o," -m single-channel (mono) instead of stereo\n");
1788 #ifdef HAVE_SCHED_SETSCHEDULER
1789 fprintf(o," -T get realtime priority\n");
1790 #endif
1791 fprintf(o," -? this help --version print name + version\n");
1792 fprintf(o,"See the manpage out123(1) or call %s with --longhelp for more parameters and information.\n", cmd_name);
1793 safe_exit(err);
1794 }
1795
want_usage(char * arg,topt * opts)1796 static void want_usage(char* arg, topt *opts)
1797 {
1798 usage(0);
1799 }
1800
long_usage(int err)1801 static void long_usage(int err)
1802 {
1803 char *enclist;
1804 FILE* o = stdout;
1805 if(err)
1806 {
1807 o = stderr;
1808 fprintf(o, "You made some mistake in program usage... let me remind you:\n\n");
1809 }
1810 enclist = output_enclist();
1811 print_title(o);
1812 fprintf(o,"\nusage: %s [option(s)] [file(s) | -]\n", cmd_name);
1813
1814 fprintf(o," --name <n> set instance name (p.ex. JACK client)\n");
1815 fprintf(o," -o <o> --output <o> select audio output module\n");
1816 fprintf(o," --list-modules list the available modules\n");
1817 fprintf(o," --list-devices list the available output devices for given output module\n");
1818 fprintf(o," -a <d> --audiodevice <d> select audio device (for files, empty or - is stdout)\n");
1819 fprintf(o," -s --stdout write raw audio to stdout (-o raw -a -)\n");
1820 fprintf(o," -S --STDOUT play AND output stream to stdout\n");
1821 fprintf(o," -O <f> --outfile <f> raw output to given file (-o raw -a <f>)\n");
1822 fprintf(o," -w <f> --wav <f> write samples as WAV file in <f> (-o wav -a <f>)\n");
1823 fprintf(o," --au <f> write samples as Sun AU file in <f> (-o au -a <f>)\n");
1824 fprintf(o," --cdr <f> write samples as raw CD audio file in <f> (-o cdr -a <f>)\n");
1825 fprintf(o," -r <r> --rate <r> set the audio output rate in Hz (default 44100)\n");
1826 fprintf(o," -R <r> --inputrate <r> set intput rate in Hz for conversion (if > 0)\n"
1827 " (always last operation before output)\n");
1828 fprintf(o," --speed <f> play at given speed factor by resampling\n");
1829 fprintf(o," --resample <s> set resampler method (fine (default) or dirty)\n");
1830 fprintf(o," -c <n> --channels <n> set channel count to <n>\n");
1831 fprintf(o," -m --mono set output channel count to 1\n");
1832 fprintf(o," --stereo set output channel count to 2 (default)\n");
1833 fprintf(o," -C <n> --inputch <n> set input channel count for conversion\n");
1834 fprintf(o," -e <c> --encoding <c> set output encoding (%s)\n"
1835 , enclist != NULL ? enclist : "OOM!");
1836 fprintf(o," --endian <s> set output endianess: big, little, native (default)\n");
1837 fprintf(o," -E <c> --inputenc <c> set input encoding for conversion\n");
1838 fprintf(o," --inputend <s> set input endianess: big, little, or native\n");
1839 fprintf(o," (default being same as output endianess)\n");
1840 fprintf(o," --byteswap swap byte order at end (possibly again)\n");
1841 fprintf(o," --list-encodings list of encoding short and long names\n");
1842 fprintf(o," --mix <m> mixing matrix <m> between input and output channels\n");
1843 fprintf(o," as linear factors, comma separated list for output\n");
1844 fprintf(o," channel 1, then 2, ... default unity if channel counts\n");
1845 fprintf(o," match, 0.5,0.5 for stereo to mono, 1,1 for the other way\n");
1846 fprintf(o," --filter <coeff> apply filter(s) before preamp stage, with coeff as\n");
1847 fprintf(o," b_0,...,b_N,a_0,...,a_N (a_0=1 is mandatory) and\n");
1848 fprintf(o," multiple filters separated by ':'.\n");
1849 fprintf(o," -P <p> --preamp <p> amplify signal with <p> dB before output\n");
1850 fprintf(o," --offset <o> apply PCM offset (floating point scaled in [-1:1]");
1851 fprintf(o," --clip <s> select clipping mode: soft or hard for forced\n"
1852 " clipping also for floating point output, implicit\n"
1853 " (default) for implied clipping during conversion\n" );
1854 fprintf(o," --dither enable dithering for conversions to integer\n");
1855 fprintf(o," --test-format return 0 if audio format set by preceeding options is supported\n");
1856 fprintf(o," --test-encodings print out possible encodings with given channels/rate\n");
1857 fprintf(o," --query-format print out default format for given device, if any\n");
1858 fprintf(o," -o h --headphones (aix/hp/sun) output on headphones\n");
1859 fprintf(o," -o s --speaker (aix/hp/sun) output on speaker\n");
1860 fprintf(o," -o l --lineout (aix/hp/sun) output to lineout\n");
1861 #ifndef NOXFERMEM
1862 fprintf(o," -b <n> --buffer <n> set play buffer (\"output cache\")\n");
1863 fprintf(o," --preload <value> fraction of buffer to fill before playback\n");
1864 #endif
1865 fprintf(o," --devbuffer <s> set device buffer in seconds; <= 0 means default\n");
1866 fprintf(o," --timelimit <s> set time limit in PCM samples if >= 0\n");
1867 fprintf(o," --seconds <s> set time limit in seconds if >= 0\n");
1868 fprintf(o," --source <s> choose signal source: file (default),\n");
1869 fprintf(o," wave, sweep, pink, geiger (implied by\n");
1870 fprintf(o," --wave-freq, --wave-sweep,\n");
1871 fprintf(o," --pink-rows, --geiger-activity), or white for\n");
1872 fprintf(o," white noise\n");
1873 fprintf(o," --wave-freq <f> set wave generator frequency or list of those\n");
1874 fprintf(o," with comma separation for enabling a generated\n");
1875 fprintf(o," test signal instead of standard input,\n");
1876 fprintf(o," empty value repeating the previous\n");
1877 fprintf(o," --wave-pat <p> set wave pattern(s) (out of those:\n");
1878 {
1879 int i=0;
1880 const char* wn;
1881 while((wn=syn123_wave_name(i++)) && wn[0] != '?')
1882 fprintf(o, " %s\n", wn);
1883 }
1884 fprintf(o," ),\n");
1885 fprintf(o," empty value repeating the previous\n");
1886 fprintf(o," --wave-phase <p> set wave phase shift(s), negative values\n");
1887 fprintf(o," inverting the pattern in time and\n");
1888 fprintf(o," empty value repeating the previous,\n");
1889 fprintf(o," --wave-direction overriding the negative bit\n");
1890 fprintf(o," --wave-direction <d> set direction explicitly (the sign counts)\n");
1891 fprintf(o," --wave-sweep <f> sweep a generated wave to frequency f, from\n");
1892 fprintf(o," first one specified for --wave-freq, using the\n");
1893 fprintf(o," first wave pattern and direction, too\n");
1894 fprintf(o," --sweep-time <s> set frequency sweep duration to s seconds if > 0\n");
1895 fprintf(o," (defaulting to timelimit if set, otherwise one second)\n");
1896 fprintf(o," --sweep-count <c> set timelimit to exactly produce that many\n");
1897 fprintf(o," (smooth) sweeps\n");
1898 fprintf(o," --sweep-type <t> set sweep type: lin(ear), qua(d) (default),\n");
1899 fprintf(o," exp(onential)\n");
1900 fprintf(o," --sweep-hard disable post-sweep smoothing for periodicity\n");
1901 fprintf(o," --genbuffer <b> buffer size (limit) for signal generators,\n");
1902 fprintf(o," if > 0 (default), this enforces a periodic\n");
1903 fprintf(o," buffer also for non-periodic signals, benefit:\n");
1904 fprintf(o," less runtime CPU overhead\n");
1905 fprintf(o," --wave-limit <l> alias for --genbuffer\n");
1906 fprintf(o," --pink-rows <r> activate pink noise source and choose rows for\n");
1907 fprintf(o," ` the algorithm (<1 chooses default)\n");
1908 fprintf(o," --geiger-activity <a> a Geiger-Mueller counter as source, with\n");
1909 fprintf(o," <a> average events per second\n");
1910 fprintf(o," -t --test no output, just read and discard data (-o test)\n");
1911 fprintf(o," -v[*] --verbose increase verboselevel\n");
1912 #ifdef HAVE_SETPRIORITY
1913 fprintf(o," --aggressive tries to get higher priority (nice)\n");
1914 #endif
1915 #if defined (HAVE_SCHED_SETSCHEDULER) || defined (HAVE_WINDOWS_H)
1916 fprintf(o," -T --realtime tries to get realtime priority\n");
1917 #endif
1918 #ifdef HAVE_WINDOWS_H
1919 fprintf(o," --priority <n> use specified process priority\n");
1920 fprintf(o," accepts -2 to 3 as integer arguments\n");
1921 fprintf(o," -2 as idle, 0 as normal and 3 as realtime.\n");
1922 #endif
1923 fprintf(o," -? --help give compact help\n");
1924 fprintf(o," --longhelp give this long help listing\n");
1925 fprintf(o," --version give name / version string\n");
1926
1927 fprintf(o,"\nSee the manpage out123(1) for more information. Also, note that\n");
1928 fprintf(o,"any numeric arguments are parsed in C locale (pi is 3.14, not 3,14).\n");
1929 free(enclist);
1930 safe_exit(err);
1931 }
1932
want_long_usage(char * arg,topt * opts)1933 static void want_long_usage(char* arg, topt *opts)
1934 {
1935 long_usage(0);
1936 }
1937
give_version(char * arg,topt * opts)1938 static void give_version(char* arg, topt *opts)
1939 {
1940 fprintf(stdout, "out123 "PACKAGE_VERSION"\n");
1941 safe_exit(0);
1942 }
1943