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