Reading audio files in Extempore
Extempore’s 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 AudioBuffer
variable:
(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 AudioBuffer
type.
You can play back from a different position in the file by supplying an extra
argument to 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))))
All the 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 AudioBuffer_read_looped
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 AudioBuffer
object
(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 audio_dsp.xtm
library.
- Previous
- Next