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 = ¤t_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