Christoph Senjak <christoph.sen...@...> writes:

> 
> Hello.
> 
> I dont want to use sdl-mixer if possible. I found cffi/audio.lisp,
> including the SDL_OpenAudio-Command which takes a struct with a
> mixer-callback. Is it possible to use this? Is there any reason not to
> use it (i.e. callbacks too slow, etc.)?
> 
> I am asking this because these functions are not mentioned in the 
documentation.

- sdl-mixer supports both streams and samples of many audio formats.

- lisbuilder-sdl currently supports samples in WAV format only. 

Supporting audio in SDL posed a problem because the SDL process spawns a new 
thread (unknown to the Lisp process) to handle the audio callback. Lisps tend 
to dislike callbacks into the Lisp process from "unknown" threads.

There are three mechanisms for handling audio in SDL;

#1 sdl-mixer
   Does not need a callback into the Lisp process to fill the audio buffer. It 
takes case of this internally. Seems to work for all Lisps I have tried. 
Perhaps a little flakey under Windows if called repeatedly from the same Lisp 
process (e.g. during development).

#2 lispbuilder-sdl without the glue library
   The "unknown" audio thread calls into the Lisp process to fill the audio 
buffer. Works fine for Lispworks but other Lisps including SBCL and CCL tend to 
core, especially in Win32.

#3 lispbuilder-sdl with the glue library
   The audio callback is handled by the glue library. Lisp calls the glue 
library once per game loop asking (polling) if the audio buffer is empty and 
then filling the audio buffer if necessary. Seems to work for Lispworks/win32 
and SBCL/Linux/Win32. I haven't heard of reports of the glue library crashing 
in OSX. Perhaps an OSX user can verify this by determining if :lispbuilder-sdl-
audio is in *FEATURES*, and running (SDL-EXAMPLES:MIXER-TEST).

I tend to code primarily in Lispworks which is why both #2 and #3 are included 
in lispbuilder-sdl (Why do something once when you can do it twice and take 
twice as long.)

Audio processing is as follows;

* lispbuilder-sdl with the glue library;
Buried inside the WITH-EVENTS macro is a call to PROCESS-AUDIO that is made 
each game loop. PROCESS-AUDIO handles #3. If the glue library is unavailable 
then PROCESS-AUDIO is a no-op. PROCESS-AUDIO will call FILL-AUDIO-BUFFER if the 
glue library indicates that the audio buffer is empty. If you look at the 
source of sdl/mixer.lisp you will see that FILL-AUDIO-BUFFER is also defined as 
the audio callback function. But this callback is *not used* when the glue 
library is available.

* lispbuilder-sdl without the glue library
The PROCESS-AUDIO call within WITH-EVENTS is a no-op. As described in the 
previous section, FILL-AUDIO-BUFFER is defined as the audio callback function. 
The audio thread performs a callback into FILL-AUDIO-BUFFER to fill the audio 
buffer when necessary.


lispbuilder-sdl loads WAV samples from disk. These samples are loaded in their 
entirety into memory. I haven't added support yet for audio streams. So right 
now lispbuilder-sdl is useful for creating old-school "Tracker" music. However 
the tracker will also have to be written by yourself. 

If you want to generate samples on-the-fly from Lisp then take a look at LOAD-
AUDIO and LOAD-SAMPLE in sdl/mixer.lisp. I'll add 'official' support for "Lisp-
generated" samples as soon as I finish up integrating sdl-gfx into lispbuilder-
sdl.

Basically, LOAD-SAMPLE converts the WAV file from a foreign array of bytes into 
a Lisp array. This is an optimization allowing the audio mixer to operate on 
Lisp arrays instead of having to bit-twiddle bytes via CFFI. The disadvantage 
is that the output from the mixer must be converted back into a foreign array 
when written to the audio buffer.

LOAD-AUDIO calls BUILD-AUDIO-CVT to convert the output of LOAD-SAMPLE to the 
same audio format of the mixer. For example if the WAV sample is 8-bit unsigned 
and the mixer is setup for 16-bit unsigned, then following the call to BUILD-
AUDIO-CVT the sample will have been converted to 16-bit unsigned. 

This is something to take note of if you want to create your own audio from 
Lisp as the mixer expects the audio samples to be in the same format at mixing 
time.

I just realized that it is only possible to use a custom audio mixer as a 
replacement for FILL-AUDIO-MIXER if the glue library is not used. I'll fix this.

As to your question; If you want the best performance then you have to use sdl-
mixer as there is quite some overhead involved when lispbuilder-sdl performs 
the byte-copy over the FFI interface to fill the audio buffer.

What I plan to do in the future is to use pinned vectors which should hopefully 
make the mixer in lispbuilder-sdl as efficient as sdl-mixer by removing the 
need for the the byte-copy.

I hope this hasn't discouraged you.
-Luke

_______________________________________________
application-builder mailing list
application-builder@lispniks.com
http://www.lispniks.com/mailman/listinfo/application-builder

Reply via email to