Reading audio files in Extempore
AudioBuffer library bindings provide functionality for reading and
playing back audio files. Here’s a short example of how to read audio files.
First, load the
audiobuffer.xtm library and create an
(sys:load "libs/core/audiobuffer.xtm") (bind-func dsp:DSP (let ((ab (AudioBuffer "assets/samples/christmas_carol.aif"))) (lambda (in time chan dat) (AudioBuffer_read ab chan)))) (dsp:set! dsp)
Once you run the code, you should hear the (long-ish) christmas carol audio file
start playing (in stereo). Notice that in the body of the
dsp closure there’s
no explicit mention of where in the file we’re up to, because the current
“playhead” is stored in the
You can play back from a different position in the file by supplying an extra
AudioBuffer_read. For example, this (slightly weird) playback
approach will only advance the playhead 10% of the time:
(bind-func dsp:DSP (let ((ab (AudioBuffer "assets/samples/christmas_carol.aif")) (pos 0)) (lambda (in time chan dat) (if (< (random) 0.1:f) (set! pos (+ pos 1))) (AudioBuffer_read ab pos chan))))
AudioBuffer_read functions will stop playback when they reach the end
of the audio data from the file. If you’d like to loop the audio file instead,
you can use
One other thing to say here is that
AudioBuffer is both the name of the
(overloaded) constructor function and the name of the type which holds the audio
data and metadata.
AudioBuffer is a polymorphic function, and there are
versions for e.g. reading files with non-standard samplerates, and copying audio
data from other
AudioBuffer variables, but the simple case (shown above) just
takes a single filename argument and returns an initialised
(the audio data is heap-allocated).
To mess with this audio stream, let’s add a low-pass filter to the left channel, and a high-pass filter to the right channel (both with the resonance paramater cranked right up).
;; need to load this library as well to get the lpf/hpf (sys:load "libs/core/audio_dsp.xtm") (bind-func dsp:DSP (let ((ab (AudioBuffer "assets/samples/christmas_carol.aif")) (lp (lpf_c)) (hp (hpf_c))) (lambda (in time chan dat) (cond ((= chan 0) (lp (AudioBuffer_read ab chan) 400. 0.99)) ((= chan 1) (hp (AudioBuffer_read ab chan) 5000. 0.99)) (else 0.0:f)))))
If you’re looking for more options for messing with the signal at this low
level, have a look at the functions in the