Skip to content
master
Go to file
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.org

bdef

“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 Bdef for SuperCollider was hosted at this URL. That repository has since moved here.

Intro

Bdef is available from Quicklisp, so you can simply Quickload it:

(ql:quickload :bdef)

It also has multiple sub-systems for integration with various other libraries. So if you use cl-patterns, cl-collider, or Incudine you may want to load bdef/cl-patterns and/or the other sub-systems:

;; integration with cl-patterns and cl-collider:
(ql:quickload '(bdef/cl-patterns bdef/cl-collider))

To load a buffer from a file, provide the path to the bdef function:

(bdef "~/path/to/your/buffer.mp3")

;; you can also give it an alias:
(bdef :foo "/path/to/buffer.wav")

;; the buffer can then be referred to with it:
(bdef :foo)

bdef returns a bdef object which can be provided in place of a buffer for any functions that expect it, as long as you’ve quickloaded the proper bdef sub-system for the library those functions are from. For example:

;; cl-collider:
(synth :playbuf :buffer (bdef :foo)) ;; will work if you've loaded the bdef/cl-collider system.

;; cl-patterns:
(play (event :instrument :playbuf :buffer :foo)) ;; will work if you've loaded the bdef/cl-patterns system.
;; Notice that you can just specify the bdef name as a symbol without even having to use the bdef function! The same is true in patterns too.

Metadata can be associated with bdefs for various uses:

(setf (bdef-metadata :foo :bpm) 120) ;; set the "bpm" metadatum to 120

Some metadata is automatically generated; for example, the tempo may be automatically detected from the filename or id3 tags.

bdef includes functionality for defining buffer regions called splits. This is useful, for instance, to divide a drum loop up by each hit, or to divide up a source track into sections based on onsets or beats.

;; define three consecutive regions, one second long each:
(make-splits (list (list 0 1) (list 1 2) (list 2 3)) :unit :seconds)

;; auto-generate splits from sound onsets in a file using the aubio library:
(splits-from-aubio-onsets "/path/to/file.wav")

Aubio is an external library of audio analysis functions. If installed, splits can be automatically generated from its analyses.

Functionality for importing/exporting audio splits/regions to other programs are in the works as well: OP-1 drumsets, Audacity labels, Renoise regions, etc.

See the following section for detail on more features of the bdef library.

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.

Supports multiple sound server backends:

SuperCollider/cl-collider is the primary backend tested against, however Incudine is also supported for most functionality.

Enable the cl-collider backend, for example, like so:

(ql:quickload :bdef/cl-collider)

Allows metadata about the buffer to be stored:

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

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

Automatically set various metadata when a bdef is created:

;; load a file with its bpm in its filename:
(bdef :my-file "~/my-file-128bpm.wav")

;; the bpm is automatically stored as metadata:
(bdef-metadata :my-file :bpm) ;; => 128

You can also add your own auto-metadata keys with the define-bdef-auto-metadata macro or set-bdef-auto-metadata function, or remove them with the remove-bdef-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.

Automatically generate metadata from functions:

(setf (bdef-metadata :foo :bpm) 142) ;; sets the "tempo" metadata key instead to its beats per minute value

;; tempo is stored as beats per second:
(bdef-metadata :foo :tempo) ;; => 71/30 (142 beats per minute in beats per second)

;; beats per minute is still available, dynamically calculated from the tempo key:
(bdef-metadata :foo :bpm) ;; => 142

You can define your own “dynamic metadata” with define-bdef-dynamic-metadata.

“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!

Backends

Currently, bdef supports SuperCollider via cl-collider as a backend. There is also basic (likely buggy) Incudine support - this will be improved later.

To write your own backend, you will need to implement the following methods on your backend’s buffer class:

  • bdef-backend-supported-file-types
  • bdef-backend-load
  • bdef-backend-free
  • bdef-length
  • bdef-sample-rate
  • bdef-channels
  • bdef-id (optional if your backend doesn’t use buffer IDs)
  • bdef-file (optional if your backend doesn’t keep track of what file a buffer was loaded from)
  • bdef-subseq

All other functionality is derived from those functions.

For the user’s convenience, you might also want to define methods on the bdef class for the backend’s relevant functions; see the bottom of cl-collider.lisp for an example.

Future

  • Fix the various minor/not-so-minor issues marked with “FIX” in the code.
  • We have bdef-subseq to get buffer data; we should have support for setting buffer data 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”~.)
  • “Dynamic” splits; i.e. define a set of splits as “this region in four equal-length pieces” rather than all splits being immediately “baked” as specific points.
  • Investigate using cl-aubio for interfacing with Aubio.

About

Buffer definition; audio buffer abstraction for sound synthesis systems.

Topics

Resources

License

Releases

No releases published

Packages

No packages published
You can’t perform that action at this time.