1 /*(GPL)
2 ---------------------------------------------------------------------------
3 audio.c - Public Audio Engine Interface
4 ---------------------------------------------------------------------------
5 * Written for SGI DMedia API by Masanao Izumo <mo@goice.co.jp>
6 * Mostly rewritten by David Olofson <do@reologica.se>, 2001
7 *
8 * Copyright (C) 19??, Masanao Izumo
9 * Copyright (C) 2001-2003, 2007 David Olofson
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2.1 of the License, or (at your
14 * option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 #include "kobolog.h"
27 #include "a_globals.h"
28 #include "config.h"
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <math.h>
35
36 #ifdef HAVE_OSS
37 #include <pthread.h>
38 #include <unistd.h>
39 #include <sys/ioctl.h>
40 #ifdef OSS_USE_SOUNDCARD_H
41 #include <soundcard.h>
42 #else
43 #include <sys/soundcard.h>
44 #endif
45 #include "audiodev.h"
46 #endif
47
48 #include "SDL.h"
49 #include "SDL_audio.h"
50 #include "logger.h"
51
52 #include "a_struct.h"
53 #include "a_commands.h"
54 #include "a_control.h"
55 #include "a_pitch.h"
56 #include "a_filters.h"
57 #include "a_limiter.h"
58 #include "a_midicon.h"
59 #include "a_midi.h"
60 #include "a_midifile.h"
61 #include "a_sequencer.h"
62 #include "a_agw.h"
63 #include "a_events.h"
64
65
66 /*----------------------------------------------------------
67 Engine stuff
68 ----------------------------------------------------------*/
69
70 #ifdef HAVE_OSS
71 static audiodev_t adev;
72 static pthread_t engine_thread;
73 #endif
74
75 static int using_oss = 0;
76 static int using_midi = 0;
77 static int using_polling = 0;
78
79 int _audio_pause = 1;
80
81 /*
82 * Note that a_settings.buffersize is in stereo samples!
83 */
84 static int *mixbuf = NULL;
85 static int *busbufs[AUDIO_MAX_BUSSES];
86
87 limiter_t limiter;
88
89 /* Silent buffer for plugins */
90 int *audio_silent_buffer = NULL;
91
92 #if defined(AUDIO_LOCKING) && defined(HAVE_OSS)
93 static pthread_mutex_t _audio_mutex = PTHREAD_MUTEX_INITIALIZER;
94 static int _audio_mutex_locked = 0;
95 #endif
96
97
98 /*----------------------------------------------------------
99 Timing/Sync code
100 ----------------------------------------------------------*/
101
102 static int audio_last_callback = 0;
103
104 /* Running timer (milliseconds) */
105 static double audio_timer = 0.0;
106
107 /* Call this to nudge the current time towards 'ms'. */
sync_time(int ms)108 static inline void sync_time(int ms)
109 {
110 if(labs((int)audio_timer - ms) > 1000)
111 audio_timer = (double)ms;
112 else
113 audio_timer = audio_timer * 0.95 + (double)ms * 0.05;
114 }
115
116 /* Advance time by 'frames' audio samples. */
advance_time(int frames)117 static inline void advance_time(int frames)
118 {
119 audio_timer += (double)frames * 1000.0 / (double)a_settings.samplerate;
120 if(audio_timer >= 2147483648.0)
121 audio_timer -= 4294967296.0;
122 }
123
124 /* Get current audio time in ms, wrapping Sint32. */
get_time(void)125 static int get_time(void)
126 {
127 return (Sint32)audio_timer;
128 }
129
130
audio_next_callback(void)131 int audio_next_callback(void)
132 {
133 return get_time() + a_settings.buffersize * 1000 / a_settings.samplerate;
134 }
135
136
137 /*----------------------------------------------------------
138 Engine code
139 ----------------------------------------------------------*/
140
141 static int hold_until = 0;
142
143 /*
144 * This is where buffered asynchronous commands are
145 * processed. Some of them turn directly into timestamped
146 * events right here.
147 */
_run_commands(void)148 static void _run_commands(void)
149 {
150 int d = hold_until - get_time();
151 if(labs(d) > 1000)
152 hold_until = get_time();
153 else if(d > 0)
154 return;
155
156 while(sfifo_used(&commands) >= sizeof(command_t))
157 {
158 command_t cmd;
159 if(sfifo_read(&commands, &cmd, (unsigned)sizeof(cmd)) < 0)
160 {
161 log_printf(ELOG, "audio.c: Engine failure!\n");
162 _audio_running = 0;
163 return;
164 }
165 switch(cmd.action)
166 {
167 case CMD_STOP:
168 DBG2(log_printf(D3LOG, "%d: CMD_STOP\n", get_time());)
169 (void)ce_stop(channeltab + cmd.cid, 0, cmd.tag, 32768);
170 break;
171 case CMD_STOP_ALL:
172 DBG2(log_printf(D3LOG, "%d: CMD_STOP_ALL\n", get_time());)
173 channel_stop_all();
174 break;
175 case CMD_PLAY:
176 DBG2(log_printf(D3LOG, "%d: CMD_PLAY\n", get_time());)
177 (void)ce_start(channeltab + cmd.cid, 0,
178 cmd.tag, cmd.arg1, cmd.arg2);
179 break;
180 case CMD_CCONTROL:
181 DBG2(log_printf(D3LOG, "%d: CMD_CCONTROL\n", get_time());)
182 (void)ce_control(channeltab + cmd.cid, 0,
183 cmd.tag, cmd.index, cmd.arg1);
184 break;
185 case CMD_GCONTROL:
186 DBG2(log_printf(D3LOG, "%d: CMD_GCONTROL\n", get_time());)
187 acc_group_set((unsigned)cmd.cid, cmd.index, cmd.arg1);
188 break;
189 case CMD_MCONTROL:
190 DBG2(log_printf(D3LOG, "%d: CMD_MCONTROL\n", get_time());)
191 bus_ctl_set((unsigned)cmd.cid, (unsigned)cmd.arg1,
192 cmd.index, cmd.arg2);
193 break;
194 case CMD_WAIT:
195 DBG2(log_printf(D3LOG, "%d: CMD_WAIT", get_time());)
196 hold_until = cmd.arg1;
197 DBG2(log_printf(D3LOG, " (Holding until %d)\n", hold_until);)
198 if(hold_until - get_time() > 0)
199 return;
200 break;
201 }
202 }
203 }
204
205
206 #define CLIP_MIN -32700
207 #define CLIP_MAX 32700
208
209 #if 0
210 /*
211 * Convert with saturation
212 */
213 static void _clip(Sint32 *inbuf, Sint16 *outbuf, unsigned frames)
214 {
215 unsigned i;
216 frames <<= 1;
217 for(i = 0; i < frames; i+=2)
218 {
219 int l = inbuf[i];
220 int r = inbuf[i+1];
221 if(l < CLIP_MIN)
222 outbuf[i] = CLIP_MIN;
223 else if(l > CLIP_MAX)
224 outbuf[i] = CLIP_MAX;
225 else
226 outbuf[i] = l;
227 if(r < CLIP_MIN)
228 outbuf[i+1] = CLIP_MIN;
229 else if(r > CLIP_MAX)
230 outbuf[i+1] = CLIP_MAX;
231 else
232 outbuf[i+1] = r;
233 }
234 }
235 #endif
236
237 /*
238 * Convert to Sint16; no saturation
239 */
_s32tos16(Sint32 * inbuf,Sint16 * outbuf,unsigned frames)240 static void _s32tos16(Sint32 *inbuf, Sint16 *outbuf, unsigned frames)
241 {
242 unsigned i;
243 frames <<= 1;
244 for(i = 0; i < frames; i+=2)
245 {
246 int l = inbuf[i];
247 int r = inbuf[i+1];
248 outbuf[i] = (Sint16)l;
249 outbuf[i+1] = (Sint16)r;
250 }
251 }
252
253
254 #ifdef DEBUG
_grab(Sint16 * buf,unsigned frames)255 static void _grab(Sint16 *buf, unsigned frames)
256 {
257 static int locktime = 0;
258 static int trig = 0;
259 unsigned i = 0;
260 if(!trig)
261 for(i = 0; i < frames-1; ++i)
262 {
263 int c1 = buf[i<<1] + buf[(i<<1)+1];
264 int c2 = buf[(i<<1)+2] + buf[(i<<1)+3];
265 if((c1 > 0) && (c2 < 0))
266 {
267 trig = 1;
268 break;
269 }
270 }
271 if(locktime - SDL_GetTicks() > 200)
272 trig = 1;
273 if(!trig)
274 return;
275 for( ; i < frames; ++i)
276 {
277 oscbufl[oscpos] = buf[i<<1];
278 oscbufr[oscpos] = buf[(i<<1)+1];
279 ++oscpos;
280 if(oscpos >= oscframes)
281 {
282 oscpos = 0;
283 trig = 0;
284 locktime = SDL_GetTicks();
285 break;
286 }
287 }
288 }
289 #endif
290
291 #ifdef PROFILE_AUDIO
292 # define DBGT(x) x
293 /*
294 * Replace with something else on non-x86 archs, or
295 * compilers that don't understand this. Replacement
296 * must have better resolution than 1 ms to be useful.
297 * Unit is not important as calculations are relative.
298 */
299 # if defined(__GNUC__) && defined(i386)
timestamp(void)300 inline int timestamp(void)
301 {
302 unsigned long long int x;
303 __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
304 return x >> 8;
305 }
306 # else
307 # ifdef HAVE_GETTIMEOFDAY
308 # if TIME_WITH_SYS_TIME
309 # include <sys/time.h>
310 # include <time.h>
311 # else
312 # if HAVE_SYS_TIME_H
313 # include <sys/time.h>
314 # else
315 # include <time.h>
316 # endif
317 # endif
timestamp(void)318 inline int timestamp(void)
319 {
320 struct timeval tv;
321 gettimeofday(&tv, NULL);
322 return tv.tv_sec * 1000000 + tv.tv_usec;
323 }
324 # else
timestamp(void)325 inline int timestamp(void)
326 {
327 return SDL_GetTicks();
328 }
329 # endif
330 # endif
331 #else
332 # define DBGT(x)
333 #endif
334
335 #ifdef PROFILE_AUDIO
336 int audio_cpu_ticks = 333;
337 float audio_cpu_total = 0.0;
338 float audio_cpu_function[AUDIO_CPU_FUNCTIONS] = { 0,0,0,0,0,0,0,0,0,0 };
339 char audio_cpu_funcname[AUDIO_CPU_FUNCTIONS][20] = {
340 "Async. Commands",
341 "MIDI Input",
342 "Sequencer",
343 "MIDI -> Control",
344 "Channel/Patch Proc.",
345 "Voice Mixer",
346 "Clearing Master Buf",
347 "Bus & Mixdown",
348 "Limiter Effect",
349 "32 -> 16 bit Conv"
350 };
351 #endif
352
353
354 /*
355 * Engine callback for SDL_audio and OSS
356 */
_audio_callback(void * ud,Uint8 * stream,int len)357 static void _audio_callback(void *ud, Uint8 *stream, int len)
358 {
359 #ifdef PROFILE_AUDIO
360 int i;
361 int t[AUDIO_CPU_FUNCTIONS+2];
362 static int avgt[AUDIO_CPU_FUNCTIONS+1];
363 static int avgtotal;
364 static int lastt = 0;
365 static int last_out = 0;
366 int adjust;
367 int ticks;
368 #define TS(x) t[x] = timestamp();
369 #else
370 #define TS(x)
371 #endif
372 unsigned remaining_frames;
373 Sint16 *outbuf = (Sint16 *)stream;
374
375 audio_last_callback = SDL_GetTicks();
376 sync_time(audio_last_callback);
377
378 if(_audio_pause)
379 {
380 memset(stream, 0, (unsigned)len);
381 advance_time(len / (sizeof(Sint16) * 2));
382 return;
383 }
384
385 remaining_frames = len / sizeof(Sint16) / 2;
386 while(remaining_frames)
387 {
388 unsigned frames;
389 if(remaining_frames > a_settings.buffersize)
390 frames = a_settings.buffersize;
391 else
392 frames = remaining_frames;
393 remaining_frames -= frames;
394 TS(0);
395 TS(1);
396 aev_client("_run_commands()");
397 _run_commands();
398 TS(2);
399 aev_client("midi_process()");
400 if(using_midi)
401 midi_process();
402 TS(3);
403 /* This belongs in the MIDI patch plugin. */
404 aev_client("sequencer_process()");
405 sequencer_process(frames);
406 TS(4);
407 aev_client("midicon_process()");
408 midicon_process(frames);
409 TS(5);
410 aev_client("channel_process_all()");
411 channel_process_all(frames);
412 TS(6);
413 aev_client("voice_process_all()");
414 voice_process_all(busbufs, frames);
415 TS(7);
416 memset(mixbuf, 0, frames * sizeof(int) * 2);
417 TS(8);
418 aev_client("bus_process_all()");
419 bus_process_all(busbufs, mixbuf, frames);
420 TS(9);
421 lims_process(&limiter, mixbuf, mixbuf, frames);
422 TS(10);
423 _s32tos16(mixbuf, outbuf, frames);
424 TS(11);
425 #ifdef DEBUG
426 _grab(outbuf, frames);
427 #endif
428 #ifdef PROFILE_AUDIO
429 adjust = t[1] - t[0];
430
431 avgt[0] += t[1] - lastt;
432 lastt = t[1];
433 if(!avgt[0])
434 avgt[0] = 1;
435
436 for(i = 1; i <= AUDIO_CPU_FUNCTIONS; ++i)
437 {
438 int tt = t[i+1] - t[i] - adjust;
439 if(tt > 0)
440 {
441 avgt[i] += tt;
442 avgtotal += tt;
443 }
444 }
445 ticks = SDL_GetTicks();
446 if((ticks-last_out) > audio_cpu_ticks)
447 {
448 for(i = 1; i <= AUDIO_CPU_FUNCTIONS; ++i)
449 audio_cpu_function[i-1] =
450 (float)avgt[i] * 100.0 / avgt[0];
451 audio_cpu_total = (float)avgtotal * 100.0 / avgt[0];
452 memset(avgt, 0, sizeof(avgt));
453 avgtotal = 0;
454 last_out = ticks;
455 }
456 #undef TS
457 #endif
458 outbuf += frames * 2;
459 aev_advance_timer(frames);
460 advance_time(frames);
461 }
462 aev_client("Unknown");
463 }
464
465
466 #ifdef HAVE_OSS
467 /*
468 * Engine thread for OSS
469 */
470 int oss_outbufsize = 0;
471 Sint16 *oss_outbuf = NULL;
472
_audio_engine(void * dummy)473 void *_audio_engine(void *dummy)
474 {
475 while(_audio_running)
476 {
477 # ifdef AUDIO_LOCKING
478 pthread_mutex_lock(&_audio_mutex);
479 # endif
480 _audio_callback(NULL, (Uint8 *)oss_outbuf, oss_outbufsize);
481 # ifdef AUDIO_LOCKING
482 pthread_mutex_unlock(&_audio_mutex);
483 # endif
484 write(adev.outfd, oss_outbuf, oss_outbufsize);
485 }
486 audiodev_close(&adev);
487 return NULL;
488 }
489 #endif
490
491
492 /*
493 * "Driver" call for polling mode.
494 */
audio_run(void)495 void audio_run(void)
496 {
497 #ifdef HAVE_OSS
498 audio_buf_info info;
499
500 if(!(using_oss && using_polling && _audio_running))
501 return;
502
503 ioctl(adev.outfd, SNDCTL_DSP_GETOSPACE, &info);
504 while(info.bytes >= oss_outbufsize)
505 {
506 _audio_callback(NULL, (Uint8 *)oss_outbuf, oss_outbufsize);
507 write(adev.outfd, oss_outbuf, oss_outbufsize);
508 info.bytes -= oss_outbufsize;
509 }
510 #endif
511 }
512
513
_start_oss_output()514 static int _start_oss_output()
515 {
516 #ifdef HAVE_OSS
517 audiodev_init(&adev);
518 adev.rate = a_settings.samplerate;
519 adev.fragmentsize = a_settings.output_buffersize *
520 sizeof(Sint16) * 2;
521 adev.fragments = OSS_FRAGMENTS;
522 _audio_running = 1;
523 if(audiodev_open(&adev) < 0)
524 {
525 log_printf(ELOG, "audio.c: Failed to open audio!\n");
526 _audio_running = 0;
527 return -2;
528 }
529
530 if(a_settings.output_buffersize > MAX_BUFFER_SIZE)
531 a_settings.buffersize = MAX_BUFFER_SIZE;
532 else
533 a_settings.buffersize = a_settings.output_buffersize;
534
535 free(mixbuf);
536 mixbuf = calloc(1, a_settings.buffersize * sizeof(int) * 2);
537 if(!mixbuf)
538 return -1;
539
540
541 oss_outbufsize = a_settings.output_buffersize * sizeof(Sint16) * 2;
542 oss_outbuf = calloc(1, oss_outbufsize);
543 if(!oss_outbuf)
544 {
545 audiodev_close(&adev);
546 _audio_running = 0;
547 log_printf(ELOG, "audio.c: Failed to allocate output buffer!\n");
548 return -4;
549 }
550
551 if(using_polling)
552 return 0; //That's it!
553
554 if(pthread_create(&engine_thread, NULL, _audio_engine, NULL))
555 {
556 free(oss_outbuf);
557 oss_outbuf = NULL;
558 audiodev_close(&adev);
559 log_printf(ELOG, "audio.c: Failed to start audio engine!\n");
560 return -3;
561 }
562 return 0;
563 #else
564 log_printf(ELOG, "OSS audio not compiled in!\n");
565 return -1;
566 #endif
567 }
568
569
_start_SDL_output(void)570 static int _start_SDL_output(void)
571 {
572 SDL_AudioSpec as;
573 SDL_AudioSpec audiospec;
574
575 if(SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
576 return -2;
577
578 as.freq = a_settings.samplerate;
579 as.format = AUDIO_S16SYS;
580 as.channels = 2;
581 as.samples = (Uint16)a_settings.output_buffersize;
582 as.callback = _audio_callback;
583 if(SDL_OpenAudio(&as, &audiospec) < 0)
584 return -3;
585
586 if(audiospec.format != AUDIO_S16SYS)
587 {
588 log_printf(ELOG, "audio.c: ERROR: Only 16 bit output supported!\n");
589 SDL_CloseAudio();
590 return -4;
591 }
592
593 if(audiospec.channels != 2)
594 {
595 log_printf(ELOG, "audio.c: ERROR: Only stereo output supported!\n");
596 SDL_CloseAudio();
597 return -5;
598 }
599
600 if(a_settings.samplerate != audiospec.freq)
601 {
602 log_printf(ELOG, "audio.c: Warning: Requested fs=%d Hz, but"
603 "got %d Hz.\n", a_settings.samplerate,
604 audiospec.freq);
605 a_settings.samplerate = audiospec.freq;
606 }
607
608 if((unsigned)audiospec.samples != a_settings.output_buffersize)
609 {
610 log_printf(ELOG, "audio.c: Warning: Requested %u sample"
611 "buffer, but got %u samples.\n",
612 a_settings.output_buffersize, audiospec.samples);
613 a_settings.output_buffersize = audiospec.samples;
614 }
615
616 if(a_settings.output_buffersize > MAX_BUFFER_SIZE)
617 a_settings.buffersize = MAX_BUFFER_SIZE;
618 else
619 a_settings.buffersize = a_settings.output_buffersize;
620
621 free(mixbuf);
622 mixbuf = calloc(1, a_settings.buffersize * sizeof(int) * 2);
623 if(!mixbuf)
624 {
625 SDL_CloseAudio();
626 return -1;
627 }
628
629 _audio_running = 1;
630 SDL_PauseAudio(0);
631 return 0;
632 }
633
634
635 static int _mixing_open = 0;
636
_close_mixing(void)637 static void _close_mixing(void)
638 {
639 int i;
640 if(!_mixing_open)
641 return;
642
643 /* KLUDGE */ lim_close(&limiter);
644 for(i = 0; i < AUDIO_MAX_BUSSES; ++i)
645 {
646 free(busbufs[i]);
647 busbufs[i] = NULL;
648 }
649 free(audio_silent_buffer);
650 audio_silent_buffer = NULL;
651 _mixing_open = 0;
652 }
653
_open_mixing(void)654 static int _open_mixing(void)
655 {
656 unsigned bytes = a_settings.buffersize * sizeof(int) * 2;
657 unsigned i;
658 if(_mixing_open)
659 return 0;
660
661 for(i = 0; i < AUDIO_MAX_BUSSES; ++i)
662 {
663 busbufs[i] = calloc(1, bytes);
664 if(!busbufs[i])
665 {
666 _close_mixing();
667 return -1;
668 }
669 }
670 audio_silent_buffer = calloc(1, bytes);
671 if(!audio_silent_buffer)
672 {
673 _close_mixing();
674 return -2;
675 }
676
677 /* KLUDGE */ if(lim_open(&limiter, a_settings.samplerate) < 0)
678 /* KLUDGE */ {
679 /* KLUDGE */ _close_mixing();
680 /* KLUDGE */ return -3;
681 /* KLUDGE */ }
682 /* KLUDGE */ lim_control(&limiter, LIM_THRESHOLD, DEFAULT_LIM_THRESHOLD);
683 /* KLUDGE */ lim_control(&limiter, LIM_RELEASE, DEFAULT_LIM_RELEASE);
684
685 _mixing_open = 1;
686 return 0;
687 }
688
689
_stop_output(void)690 static void _stop_output(void)
691 {
692 _audio_running = 0;
693 if(using_oss)
694 {
695 #ifdef HAVE_OSS
696 if(!using_polling)
697 {
698 # ifdef AUDIO_LOCKING
699 if(_audio_mutex_locked)
700 pthread_mutex_unlock(&_audio_mutex);
701 # endif
702 pthread_join(engine_thread, NULL);
703 # ifdef AUDIO_LOCKING
704 pthread_mutex_destroy(&_audio_mutex);
705 _audio_mutex_locked = 0;
706 # endif
707 }
708 free(oss_outbuf);
709 oss_outbuf = NULL;
710 #endif
711 }
712 else
713 SDL_CloseAudio();
714 free(mixbuf);
715 mixbuf = NULL;
716 }
717
718
719 #ifdef AUDIO_LOCKING
720 /*
721 * This sucks. The engine should *never* be locked!
722 *
723 * Using the API mostly results in single-reader/single-writer
724 * situations (the *API* is not guaranteed to be thread safe!),
725 * so we just need to do things in the right order.
726 */
audio_lock(void)727 void audio_lock(void)
728 {
729 if(using_oss)
730 {
731 #ifdef HAVE_OSS
732 if(using_polling)
733 return;
734 if(!_audio_mutex_locked)
735 pthread_mutex_lock(&_audio_mutex);
736 ++_audio_mutex_locked;
737 #endif
738 }
739 else
740 SDL_LockAudio();
741 }
742
743
audio_unlock(void)744 void audio_unlock(void)
745 {
746 if(using_oss)
747 {
748 #ifdef HAVE_OSS
749 if(using_polling)
750 return;
751 if(_audio_mutex_locked)
752 {
753 --_audio_mutex_locked;
754 if(!_audio_mutex_locked)
755 pthread_mutex_unlock(&_audio_mutex);
756 }
757 #endif
758 }
759 else
760 SDL_UnlockAudio();
761 }
762 #endif
763
764
765 /*----------------------------------------------------------
766 Open/close code
767 ----------------------------------------------------------*/
768
769 static int _wasinit = 0;
770
771
audio_open(void)772 int audio_open(void)
773 {
774 if(_wasinit)
775 return 0;
776
777 aev_client("audio_open()");
778
779 audio_wave_open();
780 audio_patch_open();
781 audio_group_open();
782
783 /* NOTE: AGW will auto-initialize if used! */
784
785 _wasinit = 1;
786 return 0;
787 }
788
789
audio_start(int rate,int latency,int use_oss,int use_midi,int pollaudio)790 int audio_start(int rate, int latency, int use_oss, int use_midi, int pollaudio)
791 {
792 int i, fragments;
793 if(audio_open() < 0)
794 return -100;
795
796 audio_stop();
797
798 aev_client("audio_start()");
799
800 a_settings.samplerate = rate;
801 using_oss = use_oss;
802 using_polling = pollaudio;
803
804 if(sfifo_init(&commands, sizeof(command_t) * MAX_COMMANDS) < 0)
805 {
806 log_printf(ELOG, "audio.c: Failed to set up audio engine!\n");
807 return -1;
808 }
809
810 if(ptab_init(65536) < 0)
811 {
812 log_printf(ELOG, "audio.c: Failed to set up pitch table!\n");
813 sfifo_close(&commands);
814 return -2;
815 }
816
817
818 audio_channel_open();
819 audio_voice_open();
820 audio_bus_open();
821 if(aev_open(AUDIO_MAX_VOICES * MAX_BUFFER_SIZE) < 0)
822 {
823 audio_stop();
824 return -1;
825 }
826
827 if(using_oss)
828 fragments = OSS_FRAGMENTS;
829 else
830 fragments = SDL_FRAGMENTS;
831 if(latency > 1000)
832 latency = 1000;
833
834 a_settings.output_buffersize = MIN_BUFFER_SIZE;
835 /* We use 707 instead of 1000 for correct rounding. */
836 while(fragments * a_settings.output_buffersize * 707 /
837 a_settings.samplerate < latency)
838 a_settings.output_buffersize <<= 1;
839 a_settings.output_buffersize >>= 1;
840
841 log_printf(DLOG, "audio.c: Requested latency %d ms ==>"
842 " buffer size: %d samples;"
843 " latency: %.2f ms (error: %.2f).\n",
844 latency,
845 a_settings.output_buffersize,
846 fragments * a_settings.output_buffersize * 1000.0 /
847 a_settings.samplerate,
848 fabs(latency - fragments *
849 a_settings.output_buffersize * 1000.0 /
850 a_settings.samplerate)
851 );
852
853 _audio_pause = 1; /* Don't touch anything yet! */
854
855 if(using_polling && !using_oss)
856 {
857 log_printf(ELOG, "WARNING: Overriding driver selection!"
858 " 'pollaudio' requires OSS.\n");
859 using_oss = 1;
860 }
861
862 if(using_oss)
863 i = _start_oss_output();
864 else
865 i = _start_SDL_output();
866 if(i < 0)
867 {
868 audio_stop();
869 return -6;
870 }
871
872 if(_open_mixing() < 0)
873 {
874 audio_stop();
875 return -5;
876 }
877
878 #ifdef DEBUG
879 oscbufl = calloc(1, OSCFRAMES*sizeof(int));
880 oscbufr = calloc(1, OSCFRAMES*sizeof(int));
881 oscframes = OSCFRAMES;
882 #endif
883 midicon_open((float)a_settings.samplerate, 16);
884
885 if(use_midi)
886 using_midi = midi_open(&midicon_midisock) >= 0;
887 else
888 using_midi = 0;
889
890 sequencer_open(&midicon_midisock, (float)a_settings.samplerate);
891 audio_wave_prepare(-1); /* Update "natural speeds" and stuff... */
892 aev_reset_timer(); /* Reset event system timer */
893
894 aev_client("Unknown");
895 _audio_pause = 0; /* GO! */
896 _wasinit = 1;
897 return 0;
898 }
899
900
audio_stop(void)901 void audio_stop(void)
902 {
903 if(_audio_running)
904 {
905 log_printf(VLOG, "Stopping audio engine...\n");
906 _audio_pause = 1;
907 _stop_output();
908 }
909
910 _close_mixing();
911 sequencer_close();
912 if(using_midi)
913 midi_close();
914 midicon_close();
915 ptab_close();
916 sfifo_close(&commands);
917 #ifdef DEBUG
918 oscframes = 0;
919 free(oscbufl);
920 free(oscbufr);
921 oscbufl = NULL;
922 oscbufr = NULL;
923 #endif
924 audio_bus_close();
925 audio_voice_close();
926 audio_channel_close();
927 aev_close();
928 }
929
930
audio_close(void)931 void audio_close(void)
932 {
933 if(!_wasinit)
934 return;
935
936 audio_stop();
937
938 agw_close();
939 audio_group_close();
940 audio_patch_close();
941 audio_wave_close();
942
943 _wasinit = 0;
944 }
945
946
947 /*----------------------------------------------------------
948 Engine Control
949 ----------------------------------------------------------*/
950
audio_quality(audio_quality_t quality)951 void audio_quality(audio_quality_t quality)
952 {
953 a_settings.quality = quality;
954 }
955
audio_set_limiter(float thres,float rels)956 void audio_set_limiter(float thres, float rels)
957 {
958 int t, r;
959 t = (int)(32768.0 * thres);
960 if(t < 256)
961 t = 256;
962 r = (int)(rels * 65536.0);
963 lim_control(&limiter, LIM_THRESHOLD, t);
964 lim_control(&limiter, LIM_RELEASE, r);
965 }
966
967
968 /*----------------------------------------------------------
969 Engine Debugging Stuff
970 ----------------------------------------------------------*/
971
972 #ifdef DEBUG
print_accbank(accbank_t * ctl,int is_group)973 static void print_accbank(accbank_t *ctl, int is_group)
974 {
975 const char names[ACC_COUNT][8] = {
976 "GRP",
977 "PRI",
978 "PATCH",
979
980 "PBUS",
981 "SBUS",
982
983 "PAN",
984 "PITCH",
985
986 "VOL",
987 "SEND",
988
989 "MOD1",
990 "MOD2",
991 "MOD3",
992
993 "X",
994 "Y",
995 "Z"
996 };
997 int i;
998 if(is_group)
999 i = ACC_PAN;
1000 else
1001 i = 0;
1002 for(; i < ACC_COUNT; ++i)
1003 {
1004 log_printf(DLOG, "%s=", names[i]);
1005 if(ACC_IS_FIXEDPOINT(i))
1006 log_printf(DLOG, "%.4g ", (double)((*ctl)[i]/65536.0));
1007 else
1008 log_printf(DLOG, "%d ", (*ctl)[i]);
1009 }
1010 }
1011
print_vc(audio_voice_t * v)1012 static void print_vc(audio_voice_t *v)
1013 {
1014 const char names[VC_COUNT][8] = {
1015 "WAVE",
1016 "LOOP",
1017 "PITCH",
1018
1019 "RETRIG",
1020 "RANDTR",
1021
1022 "PBUS",
1023 "SBUS"
1024 };
1025 const char inames[VIC_COUNT][8] = {
1026 "LVOL",
1027 "RVOL",
1028 "LSEND",
1029 "RSEND"
1030 };
1031 int i;
1032 for(i = 0; i < VC_COUNT; ++i)
1033 {
1034 log_printf(DLOG, "%s=", names[i]);
1035 switch(i)
1036 {
1037 case VC_PITCH:
1038 case VC_RANDTRIG:
1039 log_printf(DLOG, "%.4g ", (double)(v->c[i]/65536.0));
1040 break;
1041 default:
1042 log_printf(DLOG, "%d ", v->c[i]);
1043 break;
1044 }
1045 }
1046 for(i = 0; i < VIC_COUNT; ++i)
1047 {
1048 log_printf(DLOG, "%s=", inames[i]);
1049 log_printf(DLOG, "%.4g ", (double)(v->ic[i].v/(65536.0*128.0)));
1050 }
1051 }
1052
print_voices(int channel)1053 static void print_voices(int channel)
1054 {
1055 int i;
1056 for(i = 0; i < AUDIO_MAX_VOICES; ++i)
1057 if(channel == -1 || (voicetab[i].channel ==
1058 (channeltab + channel) &&
1059 (voicetab[i].state != VS_STOPPED)) )
1060 {
1061 if((channel == -1) && (voicetab[i].state != VS_STOPPED))
1062 log_printf(DLOG, " ==>");
1063 else
1064 log_printf(DLOG, " -");
1065 log_printf(DLOG, "VOICE %.2d: ", i);
1066 print_vc(&voicetab[i]);
1067 log_printf(DLOG, "\n");
1068 }
1069 }
1070
print_channels(int group)1071 static void print_channels(int group)
1072 {
1073 int i;
1074 for(i = 0; i < AUDIO_MAX_CHANNELS; ++i)
1075 {
1076 if(channeltab[i].ctl[ACC_GROUP] != group)
1077 continue;
1078 log_printf(DLOG, " -CHANNEL %.2d: ", i);
1079 print_accbank(&channeltab[i].rctl, 0);
1080 log_printf(DLOG, "\n");
1081 log_printf(DLOG, " Transf.: ");
1082 print_accbank(&channeltab[i].ctl, 0);
1083 log_printf(DLOG, "\n");
1084 print_voices(i);
1085 }
1086 }
1087
group_in_use(int group)1088 static int group_in_use(int group)
1089 {
1090 int i;
1091 for(i = 0; i < AUDIO_MAX_CHANNELS; ++i)
1092 {
1093 if(channeltab[i].ctl[ACC_GROUP] == group)
1094 return 1;
1095 }
1096 return 0;
1097 }
1098
audio_print_info(void)1099 void audio_print_info(void)
1100 {
1101 int i;
1102 log_printf(DLOG, "--------------------------------------"
1103 "--------------------------------------\n");
1104 log_printf(DLOG, "Audio Engine Info:\n");
1105 for(i = 0; i < AUDIO_MAX_GROUPS; ++i)
1106 {
1107 if(!group_in_use(i))
1108 continue;
1109 log_printf(DLOG, "-GROUP %.2d-----------------------------"
1110 "--------------------------------------\n", i);
1111 log_printf(DLOG, " ctl: ");
1112 print_accbank(&grouptab[i].ctl, 1);
1113 log_printf(DLOG, "\n def: ");
1114 print_accbank(&grouptab[i].ctl, 1);
1115 log_printf(DLOG, "\n");
1116 print_channels(i);
1117 }
1118 log_printf(DLOG, "--------------------------------------"
1119 "--------------------------------------\n");
1120 #if 0
1121 print_voices(-1);
1122 log_printf(DLOG, "--------------------------------------"
1123 "--------------------------------------\n");
1124 #endif
1125 }
1126 #endif
1127