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