bdef

2019-12-27

"Buffer definition"; abstraction of audio buffers for Lisp sound synthesis systems.

Basically, this simplifies buffer management in cl-collider, making them easier to use.

Note: Previously at the URL for this repository was Bdef for SuperCollider. That repository has since moved here.

Features

Can be re-evaluated without loading a new buffer:

Compare:

  (defparameter *buf* (cl-collider:buffer-read "/buffer.wav"))

  (defparameter *buf* (cl-collider:buffer-read "/buffer.wav")) ;; the same variable, and same file!

  (length (remove-if #'null (slot-value *s* 'cl-collider::buffers))) ;; => 2 -- duplicate buffers!

versus:

  (bdef :buf "/buffer.wav") ;; here we give it the name :buf

  (bdef :foo "/buffer.wav") ;; same file, different "name"...

  (length (remove-if #'null (slot-value *s* 'cl-collider::buffers))) ;; => 1 -- no duplicate buffers :D

...To force a file to be reloaded, simply call bdef-free on it, then call bdef again.

Automatically converts files unsupported by the backend if you have ffmpeg installed:

(bdef :bar "/blah.mp3") ;; works!

It does this by storing them in a temporary directory (/tmp/bdef/ by default on linux and mac).

No additional name needed if loading from a file:

(bdef "/my-file.ogg")

Supports pathname abbreviations:

(bdef "~/cool-sound.wav") ;; will find a cool sound in your home directory

Loads mono files as stereo by default.

For consistency. To load as mono, supply 1 for bdef's num-channels keyword argument.

Supports loading in wavetable format:

(bdef "~/wilhelm.wav" :wavetable t) ;; load the Wilhelm scream as a wavetable

Supports loading envelopes as buffers:

Either as wavetables, or standard.

Integration with cl-collider:

(cl-collider:bufnum (bdef :sound)) ;; returns the buffer number.

(cl-collider:synth :playbuf :bufnum (bdef :sound)) ;; plays the buffer.

Load the bdef/cl-collider system to enable this.

Integration with cl-patterns:

(cl-patterns:play (bdef :sound)) ;; plays the buffer using the *cl-collider-buffer-preview-synth* set in cl-patterns.

(cl-patterns:play (cl-patterns:event :instrument :playbuf :bufnum (bdef :sound))) ;; automatically converts bdef to the buffer number.

Load the bdef/cl-patterns system to enable this.

Designed to work with multiple backends:

At the moment, SuperCollider/cl-collider is the main one. Support for Incudine is planned.

Enable the cl-collider backend like so:

  (ql:quickload :bdef/cl-collider)

Allows metadata about the buffer to be stored:

(setf (bdef-metadata (bdef :snd) :tempo) (/ 99 60)) ;; set :snd's tempo to 99 BPM.

(bdef-metadata (bdef :snd) :tempo) ;; get the stored tempo value.

Automatically gets various metadata for a file when available:

(bdef-metadata (bdef "~/my-file-128bpm.wav") :tempo) ;; => 32/15 (128bpm in beats per second)

You can also add your own auto-metadata keys with the define-auto-metadata macro or set-auto-metadata function, or remove them with the remove-auto-metadata function.

Additional metadata is loaded asynchronously in background threads using futures from the eager-future2 library. If a requested metadatum is still being generated, bdef-metadata will block until the result is available.

"Splits" functionality to define split points or regions in buffers:

  (make-splits (list 0 0.25 0.5 0.75) :bdef (bdef :foo)) ;; splits at the start, 25%, 50%, and 75% into the file.

  (splits-from-audacity-labels "/path/to/label.txt") ;; make a splits object from an Audacity labels file.

  (setf (bdef-splits :my-bdef) *) ;; set the :my-bdef bdef's :splits metadatum to the splits object generated from the above.

  (splits-point :my-bdef 3 :start :second) ;; get the start of :my-bdef's fourth split in seconds.

Splits integration with cl-patterns:

  (pbind :instrument :playbuf
         :bufnum (bdef :my-bdef)
         :split (pwhite 0 (1- (splits-length :my-bdef))) ;; pick a random split
         :embed (psplits) ;; the psplits pattern yields events with :start, :end, and :dur keys to play the split specified by :split from the :splits metadatum of the bdef specified as :bufnum.
         :dur 1)

Integration with the Aubio audio analysis library if installed:

(bdef::splits-from-aubio-onsets "/path/to/audio/file.wav")

(bdef :pee "/path/to/pee.wav") ;; since no BPM is listed in the filename, aubio is used to detect it (if installed)...

(bdef-metadata :pee :tempo) ;; ...and it is stored in the bdef's :tempo metadatum! nice!

Future

  • Right now, cl-collider is the only supported backend. In the future, Incudine should work as well.
  • Support for configurable pathname shortcuts. (i.e. set foo as a shortcut to /a/long/path/name/, then provide ~"foo/bar.wav"~ instead of ~"/a/long/path/name/bar.wav"~.)
  • Loading with num-channels set to 1 loads only the first channel. Might make more sense to mix all channels down to mono, perhaps as an option.
Author
modula t. <defaultxr at gmail dot com>
License
MIT