1 /*
2  * Schism Tracker - a cross-platform Impulse Tracker clone
3  * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
4  * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
5  * copyright (c) 2009 Storlek & Mrs. Brisby
6  * copyright (c) 2010-2012 Storlek
7  * URL: http://schismtracker.org/
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include "headers.h"
25 
26 #include "it.h"
27 #include "page.h"
28 #include "cmixer.h"
29 #include "sndfile.h"
30 #include "song.h"
31 #include "slurp.h"
32 #include "config-parser.h"
33 
34 #include "disko.h"
35 #include "event.h"
36 
37 #include <assert.h>
38 
39 #include <stdio.h>
40 #include <string.h>
41 #include <errno.h>
42 #include <math.h>
43 
log_cb(const rd_kafka_t * rk,int level,const char * fac,const char * buf)44 #include "sdlmain.h"
45 
46 #include "midi.h"
47 
48 #include "snd_fm.h"
49 #include "snd_gm.h"
50 
51 // Default audio configuration
52 // (XXX: Can DEF_SAMPLE_RATE be defined to 48000 everywhere?
53 // Does any sound card NOT support 48khz decently nowadays?)
54 #ifdef GEKKO
55 # define DEF_SAMPLE_RATE 48000
56 #else
57 # define DEF_SAMPLE_RATE 44100
58 #endif
59 #ifdef WIN32
60 # define DEF_BUFFER_SIZE 2048
61 #else
62 # define DEF_BUFFER_SIZE 1024
63 #endif
64 #define DEF_CHANNEL_LIMIT 128
65 
66 static int midi_playing;
67 // ------------------------------------------------------------------------
68 
69 #define SMP_INIT (UINT_MAX - 1) /* for a click noise on init */
70 
71 unsigned int samples_played = 0;
72 unsigned int max_channels_used = 0;
73 
74 signed short *audio_buffer = NULL;
75 unsigned int audio_buffer_samples = 0; /* multiply by audio_sample_size to get bytes */
76 
77 unsigned int audio_output_channels = 2;
78 unsigned int audio_output_bits = 16;
79 
80 static unsigned int audio_sample_size;
81 static int audio_buffers_per_second = 0;
82 static int audio_writeout_count = 0;
83 
84 struct audio_settings audio_settings;
85 
86 static void _schism_midi_out_note(int chan, const song_note_t *m);
87 static void _schism_midi_out_raw(const unsigned char *data, unsigned int len, unsigned int delay);
88 
89 /* Audio driver related stuff */
90 
91 /* The (short) name of the SDL driver in use, e.g. "alsa" */
92 static char driver_name[256];
93 
94 /* This is the full driver spec for whatever device was successfully init'ed when audio was set up.
95 When reinitializing the audio, this can be used to reacquire the same device. Hopefully. */
96 static char active_audio_driver[256];
97 
98 /* Whatever was in the config file. This is used if no driver is given to audio_setup. */
99 static char cfg_audio_driver[256];
100 
101 // ------------------------------------------------------------------------
102 // playback
103 
104 extern int midi_bend_hit[64], midi_last_bend_hit[64];
105 extern void vis_work_16s(short *in, int inlen);
106 extern void vis_work_16m(short *in, int inlen);
107 extern void vis_work_8s(char *in, int inlen);
108 extern void vis_work_8m(char *in, int inlen);
109 
110 // this gets called from sdl
111 static void audio_callback(UNUSED void *qq, uint8_t * stream, int len)
112 {
113 	unsigned int wasrow = current_song->row;
114 	unsigned int waspat = current_song->current_order;
115 	int i, n;
116 
117 	if (!stream || !len || !current_song) {
118 		if (status.current_page == PAGE_WATERFALL || status.vis_style == VIS_FFT) {
119 			vis_work_8m(NULL, 0);
120 		}
121 		song_stop_unlocked(0);
122 		goto POST_EVENT;
123 	}
124 
125 	if (samples_played >= SMP_INIT) {
126 		memset(stream, 0x80, len);
127 		samples_played++; // will loop back to 0
128 		return;
129 	}
130 
131 	if (current_song->flags & SONG_ENDREACHED) {
132 		n = 0;
133 	} else {
134 		n = csf_read(current_song, stream, len);
135 		if (!n) {
136 			if (status.current_page == PAGE_WATERFALL
137 			|| status.vis_style == VIS_FFT) {
138 				vis_work_8m(NULL, 0);
139 			}
140 			song_stop_unlocked(0);
141 			goto POST_EVENT;
142 		}
143 		samples_played += n;
144 	}
145 
146 	memcpy(audio_buffer, stream, n * audio_sample_size);
147 
148 	if (audio_output_bits == 8) {
149 		/* libmodplug emits unsigned 8bit output...
150 		*/
151 		stream = (uint8_t *) audio_buffer;
152 		n *= audio_output_channels;
153 		for (i = 0; i < n; i++) {
154 			stream[i] ^= 128;
155 		}
156 		if (status.current_page == PAGE_WATERFALL
157 		|| status.vis_style == VIS_FFT) {
158 			if (audio_output_channels == 2) {
159 				vis_work_8s((char*)stream, n/2);
160 			} else {
161 				vis_work_8m((char*)stream, n);
162 			}
163 		}
164 	} else if (status.current_page == PAGE_WATERFALL
165 				|| status.vis_style == VIS_FFT) {
166 		if (audio_output_channels == 2) {
167 			vis_work_16s((short*)stream, n);
168 		} else {
169 			vis_work_16m((short*)stream, n);
170 		}
171 	}
172 
173 	if (current_song->num_voices > max_channels_used)
174 		max_channels_used = MIN(current_song->num_voices, max_voices);
175 POST_EVENT:
176 	audio_writeout_count++;
177 	if (audio_writeout_count > audio_buffers_per_second) {
178 		audio_writeout_count = 0;
179 	} else if (waspat == current_song->current_order && wasrow == current_song->row
180 			&& !midi_need_flush()) {
181 		/* skip it */
182 		return;
183 	}
184 
185 	/* send at end */
186 	SDL_Event e;
187 	e.user.type = SCHISM_EVENT_PLAYBACK;
188 	e.user.code = 0;
189 	e.user.data1 = NULL;
190 	e.user.data2 = NULL;
191 	SDL_PushEvent(&e);
192 }
193 
194 // ------------------------------------------------------------------------------------------------------------
195 // note playing
196 
197 /* this should be in page.c; the audio handling code doesn't need to know what
198    a page is, much less be talking to them */
199 static void main_song_mode_changed_cb(void)
200 {
201 	int n;
202 	for (n = 0; n < PAGE_MAX; n++) {
203 		if (pages[n].song_mode_changed_cb)
204 			pages[n].song_mode_changed_cb();
205 	}
206 }
207 
208 
209 static int current_play_channel = 1;
210 static int multichannel_mode = 0;
211 
212 int song_get_current_play_channel(void)
213 {
214 	return current_play_channel;
215 }
216 
217 void song_change_current_play_channel(int relative, int wraparound)
218 {
219 	current_play_channel += relative;
220 	if (wraparound) {
221 		if (current_play_channel < 1)
222 			current_play_channel = 64;
223 		else if (current_play_channel > 64)
224 			current_play_channel = 1;
225 	} else {
226 		current_play_channel = CLAMP(current_play_channel, 1, 64);
227 	}
228 	status_text_flash("Using channel %d for playback", current_play_channel);
229 }
230 
231 void song_toggle_multichannel_mode(void)
232 {
233 	multichannel_mode = !multichannel_mode;
234 	status_text_flash("Multichannel playback %s", (multichannel_mode ? "enabled" : "disabled"));
235 }
236 
237 int song_is_multichannel_mode(void)
238 {
239 	return multichannel_mode;
240 }
241 
242 
243 /* Channel corresponding to each note played.
244 That is, keydown_channels[66] will indicate in which channel F-5 was played most recently.
245 This will break if the same note was keydown'd twice without a keyup, but I think that's a
246 fairly unlikely scenario that you'd have to TRY to bring about. */
247 static int keyjazz_channels[128];
248 
249 /* **** chan ranges from 1 to 64   */
250 static int song_keydown_ex(int samp, int ins, int note, int vol, int chan, int effect, int param)
251 {
252 	int ins_mode;
253 	int midi_note = note; /* note gets overwritten, possibly NOTE_NONE */
254 	song_voice_t *c;
255 	song_note_t mc;
256 	song_sample_t *s = NULL;
257 	song_instrument_t *i = NULL;
258 
259 	if (chan == KEYJAZZ_CHAN_CURRENT) {
260 		chan = current_play_channel;
261 		if (multichannel_mode)
262 			song_change_current_play_channel(1, 1);
263 	}
264     // back to the 0..63 range
265     int chan_internal = chan -1;
266 
267 	song_lock_audio();
268 
269 	c = current_song->voices + chan_internal;
270 
271 	ins_mode = song_is_instrument_mode();
272 
273 	if (NOTE_IS_NOTE(note)) {
274 		// keep track of what channel this note was played in so we can note-off properly later
275 		keyjazz_channels[note] = chan;
276 
277 		// handle blank instrument values and "fake" sample #0 (used by sample loader)
278 		if (samp == 0)
279 			samp = c->last_instrument;
280 		else if (samp == KEYJAZZ_INST_FAKE)
281 			samp = 0; // dumb hack
282 		if (ins == 0)
283 			ins = c->last_instrument;
284 		else if (ins == KEYJAZZ_INST_FAKE)
285 			ins = 0; // dumb hack
286 		c->last_instrument = ins_mode ? ins : samp;
287 
288 		// give the channel a sample, and maybe an instrument
289 		s = (samp == KEYJAZZ_NOINST) ? NULL : current_song->samples + samp;
290 		i = (ins == KEYJAZZ_NOINST) ? NULL : song_get_instrument(ins); // blah
291 
292 		if (i && samp == KEYJAZZ_NOINST) {
293 			// we're playing an instrument and don't know what sample! WHAT WILL WE EVER DO?!
294 			// well, look it up in the note translation table, silly.
295 			// the weirdness here the default value here is to mimic IT behavior: we want to use
296 			// the sample corresponding to the instrument number if in sample mode and no sample
297 			// is defined for the note in the instrument's note map.
298 			s = csf_translate_keyboard(current_song, i, note, ins_mode ? NULL : (current_song->samples + ins));
299 		}
300 	}
301 
302 	c->row_effect = effect;
303 	c->row_param = param;
304 
305 	// now do a rough equivalent of csf_instrument_change and csf_note_change
306 	if (i)
307 		csf_check_nna(current_song, chan_internal, ins, note, 0);
308 	if (s) {
309 		if (c->flags & CHN_ADLIB) {
310 			OPL_NoteOff(chan_internal);
311 			OPL_Patch(chan_internal, s->adlib_bytes);
312 		}
313 
314 		c->flags = (s->flags & CHN_SAMPLE_FLAGS) | (c->flags & CHN_MUTE);
315 		if (c->flags & CHN_MUTE) {
316 			c->flags |= CHN_NNAMUTE;
317 		}
318 
319 		c->cutoff = 0x7f;
320 		c->resonance = 0;
321 		if (i) {
322 			c->ptr_instrument = i;
323 
324 			if (!(i->flags & ENV_VOLCARRY)) c->vol_env_position = 0;
325 			if (!(i->flags & ENV_PANCARRY)) c->pan_env_position = 0;
326 			if (!(i->flags & ENV_PITCHCARRY)) c->pitch_env_position = 0;
327 			if (i->flags & ENV_VOLUME) c->flags |= CHN_VOLENV;
328 			if (i->flags & ENV_PANNING) c->flags |= CHN_PANENV;
329 			if (i->flags & ENV_PITCH) c->flags |= CHN_PITCHENV;
330 
331 			i->played = 1;
332 
333 			if ((status.flags & MIDI_LIKE_TRACKER) && i) {
334 				if (i->midi_channel_mask) {
335 					GM_KeyOff(chan_internal);
336 					GM_DPatch(chan_internal, i->midi_program, i->midi_bank, i->midi_channel_mask);
337 				}
338 			}
339 
340 			if (i->ifc & 0x80)
341 				c->cutoff = i->ifc & 0x7f;
342 			if (i->ifr & 0x80)
343 				c->resonance = i->ifr & 0x7f;
344 			//?
345 			c->vol_swing = i->vol_swing;
346 			c->pan_swing = i->pan_swing;
347 			c->nna = i->nna;
348 		} else {
349 			c->ptr_instrument = NULL;
350 			c->cutoff = 0x7f;
351 			c->resonance = 0;
352 		}
353 
354 		c->master_channel = 0; // indicates foreground channel.
355 		//c->flags &= ~(CHN_PINGPONGFLAG);
356 
357 		// ?
358 		//c->autovib_depth = 0;
359 		//c->autovib_position = 0;
360 
361 		// csf_note_change copies stuff from c->ptr_sample as long as c->length is zero
362 		// and if period != 0 (ie. sample not playing at a stupid rate)
363 		c->ptr_sample = s;
364 		c->length = 0;
365 		// ... but it doesn't copy the volumes, for somewhat obvious reasons.
366 		c->volume = (vol == KEYJAZZ_DEFAULTVOL) ? s->volume : (((unsigned) vol) << 2);
367 		c->instrument_volume = s->global_volume;
368 		if (i)
369 			c->instrument_volume = (c->instrument_volume * i->global_volume) >> 7;
370 		c->global_volume = 64;
371 		// gotta set these by hand, too
372 		c->c5speed = s->c5speed;
373 		c->new_note = note;
374 		s->played = 1;
375 	} else if (NOTE_IS_NOTE(note)) {
376 		// Note given with no sample number. This might happen if on the instrument list and playing
377 		// an instrument that has no sample mapped for the given note. In this case, ignore the note.
378 		note = NOTE_NONE;
379 	}
380 	if (c->increment < 0)
381 		c->increment = -c->increment; // lousy hack
382 	csf_note_change(current_song, chan_internal, note, 0, 0, 1);
383 
384 	if (!(status.flags & MIDI_LIKE_TRACKER) && i) {
385 		/* midi keyjazz shouldn't require a sample */
386 		mc.note = note ? note : midi_note;
387 
388 		mc.instrument = ins;
389 		mc.voleffect = VOLFX_VOLUME;
390 		mc.volparam = vol;
391 		mc.effect = effect;
392 		mc.param = param;
393 		_schism_midi_out_note(chan_internal, &mc);
394 	}
395 
396 	/*
397 	TODO:
398 	- If this is the ONLY channel playing, and the song is stopped, always reset the tick count
399 	  (will fix the "random" behavior for most effects)
400 	- If other channels are playing, don't reset the tick count, but do process first-tick effects
401 	  for this note *right now* (this will fix keyjamming with effects like Oxx and SCx)
402 	- Need to handle volume column effects with this function...
403 	*/
404 	if (current_song->flags & SONG_ENDREACHED) {
405 		current_song->flags &= ~SONG_ENDREACHED;
406 		current_song->flags |= SONG_PAUSED;
407 	}
408 
409 	song_unlock_audio();
410 
411 	return chan;
412 }
413 
414 int song_keydown(int samp, int ins, int note, int vol, int chan)
415 {
416 	return song_keydown_ex(samp, ins, note, vol, chan, FX_PANNING, 0x80);
417 }
418 
419 int song_keyrecord(int samp, int ins, int note, int vol, int chan, int effect, int param)
420 {
421 	return song_keydown_ex(samp, ins, note, vol, chan, effect, param);
422 }
423 
424 int song_keyup(int samp, int ins, int note)
425 {
426 	return song_keydown_ex(samp, ins, NOTE_OFF, KEYJAZZ_DEFAULTVOL, keyjazz_channels[note], 0, 0);
427 }
428 
429 void song_single_step(int patno, int row)
430 {
431 	int total_rows;
432 	int i, vol, smp, ins;
433 	song_note_t *pattern, *cur_note;
434 	song_voice_t *cx;
435 
436 	total_rows = song_get_pattern(patno, &pattern);
437 	if (!pattern || row >= total_rows) return;
438 
439 	cur_note = pattern + 64 * row;
440 	cx = song_get_mix_channel(0);
441 	for (i = 1; i <= 64; i++, cx++, cur_note++) {
442 		if (cx && (cx->flags & CHN_MUTE)) continue; /* ick */
443 		if (cur_note->voleffect == VOLFX_VOLUME) {
444 			vol = cur_note->volparam;
445 		} else {
446 			vol = KEYJAZZ_DEFAULTVOL;
447 		}
448 
449 		// look familiar? this is modified slightly from pattern_editor_insert
450 		// (and it is wrong for the same reason as described there)
451 		smp = ins = cur_note->instrument;
452 		if (song_is_instrument_mode()) {
453 			if (ins < 1)
454 				ins = KEYJAZZ_NOINST;
455 			smp = -1;
456 		} else {
457 			if (smp < 1)
458 				smp = KEYJAZZ_NOINST;
459 			ins = -1;
460 		}
461 
462 		song_keyrecord(smp, ins, cur_note->note,
463 			vol, i, cur_note->effect, cur_note->param);
464 	}
465 }
466 
467 // ------------------------------------------------------------------------------------------------------------
468 
469 // this should be called with the audio LOCKED
470 static void song_reset_play_state(void)
471 {
472 	memset(midi_bend_hit, 0, sizeof(midi_bend_hit));
473 	memset(midi_last_bend_hit, 0, sizeof(midi_last_bend_hit));
474 	memset(keyjazz_channels, 0, sizeof(keyjazz_channels));
475 
476 	// turn this crap off
477 	current_song->mix_flags &= ~(SNDMIX_NOBACKWARDJUMPS | SNDMIX_DIRECTTODISK);
478 
479 	OPL_Reset(); /* gruh? */
480 
481 	csf_set_current_order(current_song, 0);
482 
483 	current_song->repeat_count = 0;
484 	current_song->buffer_count = 0;
485 	current_song->flags &= ~(SONG_PAUSED | SONG_PATTERNLOOP | SONG_ENDREACHED);
486 
487 	current_song->stop_at_order = -1;
488 	current_song->stop_at_row = -1;
489 	samples_played = 0;
490 }
491 
492 void song_start_once(void)
493 {
494 	song_lock_audio();
495 
496 	song_reset_play_state();
497 	current_song->mix_flags |= SNDMIX_NOBACKWARDJUMPS;
498 	max_channels_used = 0;
499 	current_song->repeat_count = -1; // FIXME do this right
500 
501 	GM_SendSongStartCode();
502 	song_unlock_audio();
503 	main_song_mode_changed_cb();
504 
505 	csf_reset_playmarks(current_song);
506 }
507 
508 void song_start(void)
509 {
510 	song_lock_audio();
511 
512 	song_reset_play_state();
513 	max_channels_used = 0;
514 
515 	GM_SendSongStartCode();
516 	song_unlock_audio();
517 	main_song_mode_changed_cb();
518 
519 	csf_reset_playmarks(current_song);
520 }
521 
522 void song_pause(void)
523 {
524 	song_lock_audio();
525 	// Highly unintuitive, but SONG_PAUSED has nothing to do with pause.
526 	if (!(current_song->flags & SONG_PAUSED))
527 		current_song->flags ^= SONG_ENDREACHED;
528 	song_unlock_audio();
529 	main_song_mode_changed_cb();
530 }
531 
532 void song_stop(void)
533 {
534 	song_lock_audio();
535 	song_stop_unlocked(0);
536 	song_unlock_audio();
537 	main_song_mode_changed_cb();
538 }
539 
540 /* for midi translation */
541 static int note_tracker[64];
542 static int vol_tracker[64];
543 static int ins_tracker[64];
544 static int was_program[16];
545 static int was_banklo[16];
546 static int was_bankhi[16];
547 
548 static const song_note_t *last_row[64];
549 static int last_row_number = -1;
550 
551 void song_stop_unlocked(int quitting)
552 {
553 	if (!current_song) return;
554 
555 	if (midi_playing) {
556 		unsigned char moff[4];
557 
558 		/* shut off everything; not IT like, but less annoying */
559 		for (int chan = 0; chan < 64; chan++) {
560 			if (note_tracker[chan] != 0) {
561 				for (int j = 0; j < 16; j++) {
562 					csf_process_midi_macro(current_song, chan,
563 						current_song->midi_config.note_off,
564 						0, note_tracker[chan], 0, j);
565 				}
566 				moff[0] = 0x80 + chan;
567 				moff[1] = note_tracker[chan];
568 				csf_midi_send(current_song, (unsigned char *) moff, 2, 0, 0);
569 			}
570 		}
571 		for (int j = 0; j < 16; j++) {
572 			moff[0] = 0xe0 + j;
573 			moff[1] = 0;
574 			csf_midi_send(current_song, (unsigned char *) moff, 2, 0, 0);
575 
576 			moff[0] = 0xb0 + j;	/* channel mode message */
577 			moff[1] = 0x78;		/* all sound off */
578 			moff[2] = 0;
579 			csf_midi_send(current_song, (unsigned char *) moff, 3, 0, 0);
580 
581 			moff[1] = 0x79;		/* reset all controllers */
582 			csf_midi_send(current_song, (unsigned char *) moff, 3, 0, 0);
583 
584 			moff[1] = 0x7b;		/* all notes off */
585 			csf_midi_send(current_song, (unsigned char *) moff, 3, 0, 0);
586 		}
587 
588 		csf_process_midi_macro(current_song, 0, current_song->midi_config.stop, 0, 0, 0, 0); // STOP!
589 		midi_send_flush(); // NOW!
590 
591 		midi_playing = 0;
592 	}
593 
594 	OPL_Reset(); /* Also stop all OPL sounds */
595 	GM_Reset(quitting);
596 	GM_SendSongStopCode();
597 
598 	memset(last_row,0,sizeof(last_row));
599 	last_row_number = -1;
600 
601 	memset(note_tracker,0,sizeof(note_tracker));
602 	memset(vol_tracker,0,sizeof(vol_tracker));
603 	memset(ins_tracker,0,sizeof(ins_tracker));
604 	memset(was_program,0,sizeof(was_program));
605 	memset(was_banklo,0,sizeof(was_banklo));
606 	memset(was_bankhi,0,sizeof(was_bankhi));
607 
608 	playback_tracing = midi_playback_tracing;
609 
610 	song_reset_play_state();
611 	// Modplug doesn't actually have a "stop" mode, but if SONG_ENDREACHED is set, current_song->Read just returns.
612 	current_song->flags |= SONG_PAUSED | SONG_ENDREACHED;
613 
614 	global_vu_left = 0;
615 	global_vu_right = 0;
616 	memset(audio_buffer, 0, audio_buffer_samples * audio_sample_size);
617 }
618 
619 
620 
621 
622 void song_loop_pattern(int pattern, int row)
623 {
624 	song_lock_audio();
625 
626 	song_reset_play_state();
627 
628 	max_channels_used = 0;
629 	csf_loop_pattern(current_song, pattern, row);
630 
631 	GM_SendSongStartCode();
632 
633 	song_unlock_audio();
634 	main_song_mode_changed_cb();
635 
636 	csf_reset_playmarks(current_song);
637 }
638 
639 void song_start_at_order(int order, int row)
640 {
641 	song_lock_audio();
642 
643 	song_reset_play_state();
644 
645 	csf_set_current_order(current_song, order);
646 	current_song->break_row = row;
647 	max_channels_used = 0;
648 
649 	GM_SendSongStartCode();
650 	/* TODO: GM_SendSongPositionCode(calculate the number of 1/16 notes) */
651 	song_unlock_audio();
652 	main_song_mode_changed_cb();
653 
654 	csf_reset_playmarks(current_song);
655 }
656 
657 void song_start_at_pattern(int pattern, int row)
658 {
659 	if (pattern < 0 || pattern > 199)
660 		return;
661 
662 	int n = song_next_order_for_pattern(pattern);
663 
664 	if (n > -1) {
665 		song_start_at_order(n, row);
666 		return;
667 	}
668 
669 	song_loop_pattern(pattern, row);
670 }
671 
672 // ------------------------------------------------------------------------
673 // info on what's playing
674 
675 enum song_mode song_get_mode(void)
676 {
677 	if ((current_song->flags & (SONG_ENDREACHED | SONG_PAUSED)) == (SONG_ENDREACHED | SONG_PAUSED))
678 		return MODE_STOPPED;
679 	if (current_song->flags & SONG_PAUSED)
680 		return MODE_SINGLE_STEP;
681 	if (current_song->flags & SONG_PATTERNPLAYBACK)
682 		return MODE_PATTERN_LOOP;
683 	return MODE_PLAYING;
684 }
685 
686 // returned value is in seconds
687 unsigned int song_get_current_time(void)
688 {
689 	return samples_played / current_song->mix_frequency;
690 }
691 
692 int song_get_current_tick(void)
693 {
694 	return current_song->tick_count % current_song->current_speed;
695 }
696 int song_get_current_speed(void)
697 {
698 	return current_song->current_speed;
699 }
700 
701 void song_set_current_tempo(int new_tempo)
702 {
703 	song_lock_audio();
704 	current_song->current_tempo = CLAMP(new_tempo, 31, 255);
705 	song_unlock_audio();
706 }
707 int song_get_current_tempo(void)
708 {
709 	return current_song->current_tempo;
710 }
711 
712 int song_get_current_global_volume(void)
713 {
714 	return current_song->current_global_volume;
715 }
716 
717 int song_get_current_order(void)
718 {
719 	return current_song->current_order;
720 }
721 
722 int song_get_playing_pattern(void)
723 {
724 	return current_song->current_pattern;
725 }
726 
727 int song_get_current_row(void)
728 {
729 	return current_song->row;
730 }
731 
732 int song_get_playing_channels(void)
733 {
734 	return MIN(current_song->num_voices, max_voices);
735 }
736 
737 int song_get_max_channels(void)
738 {
739 	return max_channels_used;
740 }
741 // Returns the max value in dBs, scaled as 0 = -40dB and 128 = 0dB.
742 void song_get_vu_meter(int *left, int *right)
743 {
744 	*left = dB_s(40, global_vu_left/256.f, 0.f);
745 	*right = dB_s(40, global_vu_right/256.f, 0.f);
746 }
747 
748 void song_update_playing_instrument(int i_changed)
749 {
750 	song_voice_t *channel;
751 	song_instrument_t *inst;
752 
753 	song_lock_audio();
754 	int n = MIN(current_song->num_voices, max_voices);
755 	while (n--) {
756 		channel = current_song->voices + current_song->voice_mix[n];
757 		if (channel->ptr_instrument && channel->ptr_instrument == current_song->instruments[i_changed]) {
758 			csf_instrument_change(current_song, channel, i_changed, 1, 0);
759 			inst = channel->ptr_instrument;
760 			if (!inst) continue;
761 
762 			/* special cases;
763 				mpt doesn't do this if porta-enabled, */
764 			if (inst->ifr & 0x80) {
765 				channel->resonance = inst->ifr & 0x7F;
766 			} else {
767 				channel->resonance = 0;
768 				channel->flags &= (~CHN_FILTER);
769 			}
770 			if (inst->ifc & 0x80) {
771 				channel->cutoff = inst->ifc & 0x7F;
772 				setup_channel_filter(channel, 0, 256, current_song->mix_frequency);
773 			} else {
774 				channel->cutoff = 0x7F;
775 				if (inst->ifr & 0x80) {
776 					setup_channel_filter(channel, 0, 256, current_song->mix_frequency);
777 				}
778 			}
779 
780 			/* flip direction */
781 			channel->flags &= (~CHN_PINGPONGFLAG);
782 		}
783 	}
784 	song_unlock_audio();
785 }
786 
787 void song_update_playing_sample(int s_changed)
788 {
789 	song_voice_t *channel;
790 	song_sample_t *inst;
791 
792 	song_lock_audio();
793 	int n = MIN(current_song->num_voices, max_voices);
794 	while (n--) {
795 		channel = current_song->voices + current_song->voice_mix[n];
796 		if (channel->ptr_sample && channel->current_sample_data) {
797 			int s = channel->ptr_sample - current_song->samples;
798 			if (s != s_changed) continue;
799 
800 			inst = channel->ptr_sample;
801 			if (inst->flags & (CHN_PINGPONGSUSTAIN|CHN_SUSTAINLOOP)) {
802 				channel->loop_start = inst->sustain_start;
803 				channel->loop_end = inst->sustain_end;
804 			} else if (inst->flags & (CHN_PINGPONGFLAG|CHN_PINGPONGLOOP|CHN_LOOP)) {
805 				channel->loop_start = inst->loop_start;
806 				channel->loop_end = inst->loop_end;
807 			}
808 			if (inst->flags & (CHN_PINGPONGSUSTAIN | CHN_SUSTAINLOOP
809 					    | CHN_PINGPONGFLAG | CHN_PINGPONGLOOP|CHN_LOOP)) {
810 				if (channel->length != channel->loop_end) {
811 					channel->length = channel->loop_end;
812 				}
813 			}
814 			if (channel->length > inst->length) {
815 				channel->current_sample_data = inst->data;
816 				channel->length = inst->length;
817 			}
818 
819 			channel->flags &= ~(CHN_PINGPONGSUSTAIN
820 					| CHN_PINGPONGLOOP
821 					| CHN_PINGPONGFLAG
822 					| CHN_SUSTAINLOOP
823 					| CHN_LOOP);
824 			channel->flags |= inst->flags & (CHN_PINGPONGSUSTAIN
825 					| CHN_PINGPONGLOOP
826 					| CHN_PINGPONGFLAG
827 					| CHN_SUSTAINLOOP
828 					| CHN_LOOP);
829 			channel->instrument_volume = inst->global_volume;
830 		}
831 	}
832 	song_unlock_audio();
833 }
834 
835 void song_get_playing_samples(int samples[])
836 {
837 	song_voice_t *channel;
838 
839 	memset(samples, 0, MAX_SAMPLES * sizeof(int));
840 
841 	song_lock_audio();
842 	int n = MIN(current_song->num_voices, max_voices);
843 	while (n--) {
844 		channel = current_song->voices + current_song->voice_mix[n];
845 		if (channel->ptr_sample && channel->current_sample_data) {
846 			int s = channel->ptr_sample - current_song->samples;
847 			if (s >= 0 && s < MAX_SAMPLES) {
848 				samples[s] = MAX(samples[s], 1 + channel->strike);
849 			}
850 		} else {
851 			// no sample.
852 			// (when does this happen?)
853 		}
854 	}
855 	song_unlock_audio();
856 }
857 
858 void song_get_playing_instruments(int instruments[])
859 {
860 	song_voice_t *channel;
861 
862 	memset(instruments, 0, MAX_INSTRUMENTS * sizeof(int));
863 
864 	song_lock_audio();
865 	int n = MIN(current_song->num_voices, max_voices);
866 	while (n--) {
867 		channel = current_song->voices + current_song->voice_mix[n];
868 		int ins = song_get_instrument_number((song_instrument_t *) channel->ptr_instrument);
869 		if (ins > 0 && ins < MAX_INSTRUMENTS) {
870 			instruments[ins] = MAX(instruments[ins], 1 + channel->strike);
871 		}
872 	}
873 	song_unlock_audio();
874 }
875 
876 // ------------------------------------------------------------------------
877 // changing the above info
878 
879 void song_set_current_speed(int speed)
880 {
881 	if (speed < 1 || speed > 255)
882 		return;
883 
884 	song_lock_audio();
885 	current_song->current_speed = speed;
886 	song_unlock_audio();
887 }
888 
889 void song_set_current_global_volume(int volume)
890 {
891 	if (volume < 0 || volume > 128)
892 		return;
893 
894 	song_lock_audio();
895 	current_song->current_global_volume = volume;
896 	song_unlock_audio();
897 }
898 
899 void song_set_current_order(int order)
900 {
901 	song_lock_audio();
902 	csf_set_current_order(current_song, order);
903 	song_unlock_audio();
904 }
905 
906 // Ctrl-F7
907 void song_set_next_order(int order)
908 {
909 	song_lock_audio();
910 	current_song->process_order = order - 1;
911 	song_unlock_audio();
912 }
913 
914 // Alt-F11
915 int song_toggle_orderlist_locked(void)
916 {
917 	current_song->flags ^= SONG_ORDERLOCKED;
918 	return current_song->flags & SONG_ORDERLOCKED;
919 }
920 
921 // ------------------------------------------------------------------------
922 // global flags
923 
924 void song_flip_stereo(void)
925 {
926 	current_song->mix_flags ^= SNDMIX_REVERSESTEREO;
927 }
928 
929 int song_get_surround(void)
930 {
931 	return (current_song->mix_flags & SNDMIX_NOSURROUND) ? 0 : 1;
932 }
933 
934 void song_set_surround(int on)
935 {
936 	if (on)
937 		current_song->mix_flags &= ~SNDMIX_NOSURROUND;
938 	else
939 		current_song->mix_flags |= SNDMIX_NOSURROUND;
940 
941 	// without copying the value back to audio_settings, it won't get saved (oops)
942 	audio_settings.surround_effect = on;
943 }
944 
945 // ------------------------------------------------------------------------------------------------------------
946 // well this is certainly a dopey place to put this, config having nothing to do with playback... maybe i
947 // should put all the cfg_ stuff in config.c :/
948 
949 #define CFG_GET_A(v,d) audio_settings.v = cfg_get_number(cfg, "Audio", #v, d)
950 #define CFG_GET_M(v,d) audio_settings.v = cfg_get_number(cfg, "Mixer Settings", #v, d)
951 void cfg_load_audio(cfg_file_t *cfg)
952 {
953 	CFG_GET_A(sample_rate, DEF_SAMPLE_RATE);
954 	CFG_GET_A(bits, 16);
955 	CFG_GET_A(channels, 2);
956 	CFG_GET_A(buffer_size, DEF_BUFFER_SIZE);
957 
958 	cfg_get_string(cfg, "Audio", "driver", cfg_audio_driver, 255, NULL);
959 
960 	CFG_GET_M(channel_limit, DEF_CHANNEL_LIMIT);
961 	CFG_GET_M(interpolation_mode, SRCMODE_LINEAR);
962 	CFG_GET_M(no_ramping, 0);
963 	CFG_GET_M(surround_effect, 1);
964 
965 	if (audio_settings.channels != 1 && audio_settings.channels != 2)
966 		audio_settings.channels = 2;
967 	if (audio_settings.bits != 8 && audio_settings.bits != 16)
968 		audio_settings.bits = 16;
969 	audio_settings.channel_limit = CLAMP(audio_settings.channel_limit, 4, MAX_VOICES);
970 	audio_settings.interpolation_mode = CLAMP(audio_settings.interpolation_mode, 0, 3);
971 
972 	audio_settings.eq_freq[0] = cfg_get_number(cfg, "EQ Low Band", "freq", 0);
973 	audio_settings.eq_freq[1] = cfg_get_number(cfg, "EQ Med Low Band", "freq", 16);
974 	audio_settings.eq_freq[2] = cfg_get_number(cfg, "EQ Med High Band", "freq", 96);
975 	audio_settings.eq_freq[3] = cfg_get_number(cfg, "EQ High Band", "freq", 127);
976 
977 	audio_settings.eq_gain[0] = cfg_get_number(cfg, "EQ Low Band", "gain", 0);
978 	audio_settings.eq_gain[1] = cfg_get_number(cfg, "EQ Med Low Band", "gain", 0);
979 	audio_settings.eq_gain[2] = cfg_get_number(cfg, "EQ Med High Band", "gain", 0);
980 	audio_settings.eq_gain[3] = cfg_get_number(cfg, "EQ High Band", "gain", 0);
981 
982 	if (cfg_get_number(cfg, "General", "stop_on_load", 1)) {
983 		status.flags &= ~PLAY_AFTER_LOAD;
984 	} else {
985 		status.flags |= PLAY_AFTER_LOAD;
986 	}
987 }
988 
989 #define CFG_SET_A(v) cfg_set_number(cfg, "Audio", #v, audio_settings.v)
990 #define CFG_SET_M(v) cfg_set_number(cfg, "Mixer Settings", #v, audio_settings.v)
991 void cfg_atexit_save_audio(cfg_file_t *cfg)
992 {
993 	CFG_SET_A(sample_rate);
994 	CFG_SET_A(bits);
995 	CFG_SET_A(channels);
996 	CFG_SET_A(buffer_size);
997 
998 	CFG_SET_M(channel_limit);
999 	CFG_SET_M(interpolation_mode);
1000 	CFG_SET_M(no_ramping);
1001 
1002 	// Say, what happened to the switch for this in the gui?
1003 	CFG_SET_M(surround_effect);
1004 
1005 	// hmmm....
1006 	//     [Equalizer]
1007 	//     low_band=freq/gain
1008 	//     med_low_band=freq/gain
1009 	//     etc.
1010 	// would be a cleaner way of storing this
1011 
1012 	cfg_set_number(cfg, "EQ Low Band", "freq", audio_settings.eq_freq[0]);
1013 	cfg_set_number(cfg, "EQ Med Low Band", "freq", audio_settings.eq_freq[1]);
1014 	cfg_set_number(cfg, "EQ Med High Band", "freq", audio_settings.eq_freq[2]);
1015 	cfg_set_number(cfg, "EQ High Band", "freq", audio_settings.eq_freq[3]);
1016 
1017 	cfg_set_number(cfg, "EQ Low Band", "gain", audio_settings.eq_gain[0]);
1018 	cfg_set_number(cfg, "EQ Med Low Band", "gain", audio_settings.eq_gain[1]);
1019 	cfg_set_number(cfg, "EQ Med High Band", "gain", audio_settings.eq_gain[2]);
1020 	cfg_set_number(cfg, "EQ High Band", "gain", audio_settings.eq_gain[3]);
1021 }
1022 
1023 void cfg_save_audio(cfg_file_t *cfg)
1024 {
1025 	cfg_atexit_save_audio(cfg);
1026 
1027 	cfg_set_number(cfg, "General", "stop_on_load", !(status.flags & PLAY_AFTER_LOAD));
1028 }
1029 
1030 // ------------------------------------------------------------------------------------------------------------
1031 static void _schism_midi_out_note(int chan, const song_note_t *starting_note)
1032 {
1033 	const song_note_t *m = starting_note;
1034 	unsigned int tc;
1035 	int m_note;
1036 
1037 	unsigned char buf[4];
1038 	int ins, mc, mg, mbl, mbh;
1039 	int need_note, need_velocity;
1040 	song_voice_t *c;
1041 
1042 	if (!current_song || !song_is_instrument_mode() || (status.flags & MIDI_LIKE_TRACKER)) return;
1043 
1044     /*if(m)
1045     fprintf(stderr, "midi_out_note called (ch %d)note(%d)instr(%d)volcmd(%02X)cmd(%02X)vol(%02X)p(%02X)\n",
1046 	chan, m->note, m->instrument, m->voleffect, m->effect, m->volparam, m->param);
1047     else fprintf(stderr, "midi_out_note called (ch %d) m=%p\n", m);*/
1048 
1049 	if (!midi_playing) {
1050 		csf_process_midi_macro(current_song, 0, current_song->midi_config.start, 0, 0, 0, 0); // START!
1051 		midi_playing = 1;
1052 	}
1053 
1054 	if (chan < 0) {
1055 		return;
1056 	}
1057 
1058 	c = &current_song->voices[chan];
1059 
1060 	chan %= 64;
1061 
1062 	if (!m) {
1063 		if (last_row_number != (signed) current_song->row) return;
1064 		m = last_row[chan];
1065 		if (!m) return;
1066 	} else {
1067 		last_row[chan] = m;
1068 		last_row_number = current_song->row;
1069 	}
1070 
1071 	ins = ins_tracker[chan];
1072 	if (m->instrument > 0) {
1073 		ins = m->instrument;
1074 	}
1075 	if (ins < 0 || ins >= MAX_INSTRUMENTS)
1076 		return; /* err...  almost certainly */
1077 	if (!current_song->instruments[ins]) return;
1078 
1079 	if (current_song->instruments[ins]->midi_channel_mask >= 0x10000) {
1080 		mc = chan % 16;
1081 	} else {
1082 		mc = 0;
1083 		if(current_song->instruments[ins]->midi_channel_mask > 0)
1084 			while(!(current_song->instruments[ins]->midi_channel_mask & (1 << mc)))
1085 				++mc;
1086 	}
1087 
1088 	m_note = m->note;
1089 	tc = current_song->tick_count % current_song->current_speed;
1090 #if 0
1091 printf("channel = %d note=%d starting_note=%p\n",chan,m_note,starting_note);
1092 #endif
1093 	if (m->effect == FX_SPECIAL) {
1094 		switch (m->param & 0x80) {
1095 		case 0xC0: /* note cut */
1096 			if (tc == (((unsigned)m->param) & 15)) {
1097 				m_note = NOTE_CUT;
1098 			} else if (tc != 0) return;
1099 			break;
1100 
1101 		case 0xD0: /* note delay */
1102 			if (tc != (((unsigned)m->param) & 15)) return;
1103 			break;
1104 		default:
1105 			if (tc != 0) return;
1106 		};
1107 	} else {
1108 		if (tc != 0 && !starting_note) return;
1109 	}
1110 
1111 	need_note = need_velocity = -1;
1112 	if (m_note > 120) {
1113 		if (note_tracker[chan] != 0) {
1114 			csf_process_midi_macro(current_song, chan, current_song->midi_config.note_off,
1115 				0, note_tracker[chan], 0, ins_tracker[chan]);
1116 		}
1117 
1118 		note_tracker[chan] = 0;
1119 		if (m->voleffect != VOLFX_VOLUME) {
1120 			vol_tracker[chan] = 64;
1121 		} else {
1122 			vol_tracker[chan] = m->voleffect;
1123 		}
1124 	} else if (!m->note && m->voleffect == VOLFX_VOLUME) {
1125 		vol_tracker[chan] = m->volparam;
1126 		need_velocity = vol_tracker[chan];
1127 
1128 	} else if (m->note) {
1129 		if (note_tracker[chan] != 0) {
1130 			csf_process_midi_macro(current_song, chan, current_song->midi_config.note_off,
1131 				0, note_tracker[chan], 0, ins_tracker[chan]);
1132 		}
1133 		note_tracker[chan] = m_note;
1134 		if (m->voleffect != VOLFX_VOLUME) {
1135 			vol_tracker[chan] = 64;
1136 		} else {
1137 			vol_tracker[chan] = m->volparam;
1138 		}
1139 		need_note = note_tracker[chan];
1140 		need_velocity = vol_tracker[chan];
1141 	}
1142 
1143 	if (m->instrument > 0) {
1144 		ins_tracker[chan] = ins;
1145 	}
1146 
1147 	mg = (current_song->instruments[ins]->midi_program)
1148 		+ ((midi_flags & MIDI_BASE_PROGRAM1) ? 1 : 0);
1149 	mbl = current_song->instruments[ins]->midi_bank;
1150 	mbh = (current_song->instruments[ins]->midi_bank >> 7) & 127;
1151 
1152 	if (mbh > -1 && was_bankhi[mc] != mbh) {
1153 		buf[0] = 0xB0 | (mc & 15); // controller
1154 		buf[1] = 0x00; // corse bank/select
1155 		buf[2] = mbh; // corse bank/select
1156 		csf_midi_send(current_song, buf, 3, 0, 0);
1157 		was_bankhi[mc] = mbh;
1158 	}
1159 	if (mbl > -1 && was_banklo[mc] != mbl) {
1160 		buf[0] = 0xB0 | (mc & 15); // controller
1161 		buf[1] = 0x20; // fine bank/select
1162 		buf[2] = mbl; // fine bank/select
1163 		csf_midi_send(current_song, buf, 3, 0, 0);
1164 		was_banklo[mc] = mbl;
1165 	}
1166 	if (mg > -1 && was_program[mc] != mg) {
1167 		was_program[mc] = mg;
1168 		csf_process_midi_macro(current_song, chan, current_song->midi_config.set_program,
1169 			mg, 0, 0, ins); // program change
1170 	}
1171 	if (c->flags & CHN_MUTE) {
1172 		// don't send noteon events when muted
1173 	} else if (need_note > 0) {
1174 		if (need_velocity == -1) need_velocity = 64; // eh?
1175 		need_velocity = CLAMP(need_velocity*2,0,127);
1176 		csf_process_midi_macro(current_song, chan, current_song->midi_config.note_on,
1177 			0, need_note, need_velocity, ins); // noteon
1178 	} else if (need_velocity > -1 && note_tracker[chan] > 0) {
1179 		need_velocity = CLAMP(need_velocity*2,0,127);
1180 		csf_process_midi_macro(current_song, chan, current_song->midi_config.set_volume,
1181 			need_velocity, note_tracker[chan], need_velocity, ins); // volume-set
1182 	}
1183 
1184 }
1185 static void _schism_midi_out_raw(const unsigned char *data, unsigned int len, unsigned int pos)
1186 {
1187 #if 0
1188 	i = (8000*(audio_buffer_samples - delay));
1189 	i /= (current_song->mix_frequency);
1190 #endif
1191 #if 0
1192 	for (int i=0; i < len; i++) {
1193 		printf("%02x ",data[i]);
1194 	}puts("");
1195 #endif
1196 
1197 	if (!_disko_writemidi(data,len,pos)) midi_send_buffer(data,len,pos);
1198 }
1199 
1200 
1201 
1202 // ------------------------------------------------------------------------------------------------------------
1203 
1204 void song_lock_audio(void)
1205 {
1206 	SDL_LockAudio();
1207 }
1208 void song_unlock_audio(void)
1209 {
1210 	SDL_UnlockAudio();
1211 }
1212 void song_start_audio(void)
1213 {
1214 	SDL_PauseAudio(0);
1215 }
1216 void song_stop_audio(void)
1217 {
1218 	SDL_PauseAudio(1);
1219 }
1220 
1221 
1222 static void song_print_info_top(const char *d)
1223 {
1224 	log_append(2, 0, "Audio initialised");
1225 	log_underline(17);
1226 	log_appendf(5, " Using driver '%s'", d);
1227 }
1228 
1229 
1230 /* --------------------------------------------------------------------------------------------------------- */
1231 /* Nasty stuff here */
1232 
1233 const char *song_audio_driver(void)
1234 {
1235 	return driver_name;
1236 }
1237 
1238 /* NOTE: driver_spec must not be NULL here */
1239 static void _audio_set_envvars(const char *driver_spec)
1240 {
1241 	char *driver = NULL, *device = NULL;
1242 
1243 	unset_env_var("AUDIODEV");
1244 	unset_env_var("SDL_PATH_DSP");
1245 
1246 	if (!*driver_spec) {
1247 		unset_env_var("SDL_AUDIODRIVER");
1248 	} else if (str_break(driver_spec, ':', &driver, &device)) {
1249 		/* "nosound" and "none" are for the sake of older versions: --help suggested using
1250 		"none", but the name presented in the rest of the interface was "nosound".
1251 		"oss" is a synonym for "dsp" because everyone should know what "oss" is and "dsp"
1252 		is a lousy name for an audio driver */
1253 		put_env_var("SDL_AUDIODRIVER",
1254 			(strcmp(driver, "oss") == 0) ? "dsp"
1255 			: (strcmp(driver, "nosound") == 0) ? "dummy"
1256 			: (strcmp(driver, "none") == 0) ? "dummy"
1257 			: driver);
1258 		if (*device) {
1259 			/* Documentation says that SDL_PATH_DSP overrides AUDIODEV if it's set,
1260 			but the SDL alsa code only looks at AUDIODEV. Annoying. */
1261 			put_env_var("AUDIODEV", device);
1262 			put_env_var("SDL_PATH_DSP", device);
1263 		}
1264 
1265 		free(driver);
1266 		free(device);
1267 	} else {
1268 		/* Assuming just the driver was given.
1269 		(Old behavior was trying to guess -- selecting 'dsp' driver for /dev/dsp, etc.
1270 		but this is rather flaky and problematic) */
1271 		put_env_var("SDL_AUDIODRIVER", driver_spec);
1272 	}
1273 
1274 	strncpy(active_audio_driver, driver_spec, sizeof(active_audio_driver));
1275 	active_audio_driver[sizeof(active_audio_driver) - 1] = '\0';
1276 }
1277 
1278 /* NOTE: driver_spec must not be NULL here
1279 'verbose' => print stuff to the log about what device/driver was configured */
1280 static int _audio_open(const char *driver_spec, int verbose)
1281 {
1282 	_audio_set_envvars(driver_spec);
1283 
1284 	if (SDL_WasInit(SDL_INIT_AUDIO))
1285 		SDL_QuitSubSystem(SDL_INIT_AUDIO);
1286 	if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
1287 		return 0;
1288 
1289 	/* This is needed in order to coax alsa into actually respecting the buffer size, since it's evidently
1290 	ignored entirely for "fake" devices such as "default" -- which SDL happens to use if no device name
1291 	is set. (see SDL_alsa_audio.c: http://tinyurl.com/ybf398f)
1292 	If hw doesn't exist, so be it -- let this fail, we'll fall back to the dummy device, and the
1293 	user can pick a more reasonable device later. */
1294 	if (SDL_AudioDriverName(driver_name, sizeof(driver_name)) != NULL && !strcmp(driver_name, "alsa")) {
1295 		char *dev = getenv("AUDIODEV");
1296 		if (!dev || !*dev)
1297 			put_env_var("AUDIODEV", "hw");
1298 	}
1299 
1300 	/* ... THIS is needed because, if the buffer size isn't a power of two, the dsp driver will punt since
1301 	it's not nice enough to fix it for us. (contrast alsa, which is TOO nice and fixes it even when we
1302 	don't want it to) */
1303 	int size_pow2 = 2;
1304 	while (size_pow2 < audio_settings.buffer_size)
1305 		size_pow2 <<= 1;
1306 	/* Round to nearest, I suppose */
1307 	if (size_pow2 != audio_settings.buffer_size
1308 	    && (size_pow2 - audio_settings.buffer_size) > (audio_settings.buffer_size - (size_pow2 >> 1))) {
1309 		size_pow2 >>= 1;
1310 	}
1311 
1312 	SDL_AudioSpec desired = {
1313 		.freq = audio_settings.sample_rate,
1314 		.format = (audio_settings.bits == 8) ? AUDIO_U8 : AUDIO_S16SYS,
1315 		.channels = audio_settings.channels,
1316 		.samples = size_pow2,
1317 		.callback = audio_callback,
1318 		.userdata = NULL,
1319 	};
1320 	SDL_AudioSpec obtained;
1321 
1322 	if (SDL_OpenAudio(&desired, &obtained) < 0)
1323 		return 0;
1324 
1325 	/* I don't know why this would change between SDL_AudioInit and SDL_OpenAudio, but I'm paranoid */
1326 	SDL_AudioDriverName(driver_name, sizeof(driver_name));
1327 
1328 	song_lock_audio();
1329 
1330 	/* format&255 is SDL specific... need bits */
1331 	csf_set_wave_config(current_song, obtained.freq,
1332 		obtained.format & 255,
1333 		obtained.channels);
1334 	audio_output_channels = obtained.channels;
1335 	audio_output_bits = obtained.format & 255;
1336 	audio_sample_size = audio_output_channels * (audio_output_bits/8);
1337 	audio_buffer_samples = obtained.samples;
1338 
1339 	if (verbose) {
1340 		song_print_info_top(driver_name);
1341 
1342 		log_appendf(5, " %d Hz, %d bit, %s", obtained.freq, (obtained.format & 0xff),
1343 			obtained.channels == 1 ? "mono" : "stereo");
1344 		log_appendf(5, " Buffer size: %d samples", obtained.samples);
1345 	}
1346 
1347 	return 1;
1348 }
1349 
1350 // Configure a device. (called at startup)
1351 static void _audio_init_head(const char *driver_spec, int verbose)
1352 {
1353 	const char *err = NULL, *err_default = NULL;
1354 	char ugh[256];
1355 
1356 	/* Use the device from the config if it exists. */
1357 	if (!driver_spec || !*driver_spec)
1358 		driver_spec = cfg_audio_driver;
1359 
1360 	if (*driver_spec) {
1361 		errno = 0;
1362 
1363 		if (_audio_open(driver_spec, verbose))
1364 			return;
1365 		err = SDL_GetError();
1366 
1367 		/* Errors returned only as strings! Environment variables used for everything!
1368 		Turns out that SDL is actually a very elaborate shell script, so it all makes sense.
1369 
1370 		Anyway, this error isn't really accurate because there might be many more devices
1371 		and it's just as likely that the *driver* name is wrong (e.g. "asla").
1372 		errno MIGHT be useful, at least on 'nix, and it does tend to provide reasonable
1373 		messages for common cases such as the device being opened already; plus, we can
1374 		make a guess if SDL just gave up and didn't do anything because it didn't know the
1375 		driver name. However, since this is probably just as likely to be wrong as it is
1376 		right, make a note of it. */
1377 
1378 		if (strcmp(err, "No available audio device") == 0) {
1379 			if (errno == 0) {
1380 				err = "Device init failed (No SDL driver by that name?)";
1381 			} else {
1382 				snprintf(ugh, sizeof(ugh), "Device init failed (%s?)", strerror(errno));
1383 				ugh[sizeof(ugh) - 1] = '\0';
1384 				err = ugh;
1385 			}
1386 		}
1387 
1388 		log_appendf(4, "%s: %s", driver_spec, err);
1389 		log_appendf(4, "Retrying with default device...");
1390 		log_nl();
1391 	}
1392 
1393 	/* Try the default device? */
1394 	if (_audio_open("", verbose))
1395 		return;
1396 
1397 	err_default = SDL_GetError();
1398 	log_appendf(4, "%s", err_default);
1399 
1400 	if (!_audio_open("dummy", 0)) {
1401 		/* yarrr, abandon ship! */
1402 		if (*driver_spec)
1403 			fprintf(stderr, "%s: %s\n", driver_spec, err);
1404 		fprintf(stderr, "%s\n", err_default);
1405 		fprintf(stderr, "Couldn't initialise audio!\n");
1406 		exit(1);
1407 	}
1408 }
1409 
1410 // Set up audio_buffer, reset the sample count, and kick off the mixer
1411 // (note: _audio_open will leave the device LOCKED)
1412 static void _audio_init_tail(void)
1413 {
1414 	free(audio_buffer);
1415 	audio_buffer = mem_calloc(audio_buffer_samples, audio_sample_size);
1416 	samples_played = (status.flags & CLASSIC_MODE) ? SMP_INIT : 0;
1417 
1418 	song_unlock_audio();
1419 	song_start_audio();
1420 }
1421 
1422 void audio_init(const char *driver_spec)
1423 {
1424 	_audio_init_head(driver_spec, 1);
1425 	_audio_init_tail();
1426 }
1427 
1428 void audio_reinit(void)
1429 {
1430 	if (status.flags & (DISKWRITER_ACTIVE|DISKWRITER_ACTIVE_PATTERN)) {
1431 		/* never allowed */
1432 		return;
1433 	}
1434 	song_stop();
1435 	_audio_init_head(active_audio_driver, 0);
1436 	_audio_init_tail();
1437 
1438 	if (status.flags & CLASSIC_MODE)
1439 		// FIXME: but we spontaneously report a GUS card sometimes...
1440 		status_text_flash("Sound Blaster 16 reinitialised");
1441 	else
1442 		status_text_flash("Audio output reinitialised");
1443 }
1444 
1445 /* --------------------------------------------------------------------------------------------------------- */
1446 
1447 void song_init_eq(int do_reset, uint32_t mix_freq)
1448 {
1449 	uint32_t pg[4];
1450 	uint32_t pf[4];
1451 	int i;
1452 
1453 	for (i = 0; i < 4; i++) {
1454 		pg[i] = audio_settings.eq_gain[i];
1455 		pf[i] = 120 + (((i*128) * audio_settings.eq_freq[i])
1456 			* (mix_freq / 128) / 1024);
1457 	}
1458 
1459 	set_eq_gains(pg, 4, pf, do_reset, mix_freq);
1460 }
1461 
1462 
1463 void song_init_modplug(void)
1464 {
1465 	song_lock_audio();
1466 
1467 	max_voices = audio_settings.channel_limit;
1468 	csf_set_resampling_mode(current_song, audio_settings.interpolation_mode);
1469 	if (audio_settings.no_ramping)
1470 		current_song->mix_flags |= SNDMIX_NORAMPING;
1471 	else
1472 		current_song->mix_flags &= ~SNDMIX_NORAMPING;
1473 
1474 	// disable the S91 effect? (this doesn't make anything faster, it
1475 	// just sounds better with one woofer.)
1476 	song_set_surround(audio_settings.surround_effect);
1477 
1478 	// update midi queue configuration
1479 	midi_queue_alloc(audio_buffer_samples, audio_sample_size, current_song->mix_frequency);
1480 
1481 	// timelimit the playback_update() calls when midi isn't actively going on
1482 	audio_buffers_per_second = (current_song->mix_frequency / (audio_buffer_samples * 8 * audio_sample_size));
1483 	if (audio_buffers_per_second > 1) audio_buffers_per_second--;
1484 
1485 	song_unlock_audio();
1486 }
1487 
1488 void song_initialise(void)
1489 {
1490 	csf_midi_out_note = _schism_midi_out_note;
1491 	csf_midi_out_raw = _schism_midi_out_raw;
1492 
1493 
1494 	current_song = csf_allocate();
1495 
1496 	//song_stop(); <- song_new does this
1497 	song_set_linear_pitch_slides(1);
1498 	song_new(0);
1499 
1500 	// hmm.
1501 	current_song->mix_flags |= SNDMIX_MUTECHNMODE;
1502 }
1503 
1504