{"id":42010202,"url":"https://github.com/defaultxr/bdef","last_synced_at":"2026-01-26T02:22:19.424Z","repository":{"id":148627395,"uuid":"206692830","full_name":"defaultxr/bdef","owner":"defaultxr","description":"Buffer definition; audio buffer abstraction for sound synthesis systems.","archived":false,"fork":false,"pushed_at":"2025-04-21T03:19:12.000Z","size":274,"stargazers_count":13,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-21T04:36:45.218Z","etag":null,"topics":["buffers","convenience","lisp","live-coding","livecoding","supercollider","synthesis"],"latest_commit_sha":null,"homepage":null,"language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/defaultxr.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-09-06T02:03:39.000Z","updated_at":"2025-04-21T03:19:16.000Z","dependencies_parsed_at":"2024-08-18T09:47:09.821Z","dependency_job_id":"b5ed0bd2-6f77-4894-bcb3-b2353577fcf0","html_url":"https://github.com/defaultxr/bdef","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/defaultxr/bdef","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/defaultxr%2Fbdef","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/defaultxr%2Fbdef/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/defaultxr%2Fbdef/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/defaultxr%2Fbdef/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/defaultxr","download_url":"https://codeload.github.com/defaultxr/bdef/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/defaultxr%2Fbdef/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28764923,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-26T00:37:26.264Z","status":"online","status_checked_at":"2026-01-26T02:00:08.215Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["buffers","convenience","lisp","live-coding","livecoding","supercollider","synthesis"],"created_at":"2026-01-26T02:22:18.764Z","updated_at":"2026-01-26T02:22:19.410Z","avatar_url":"https://github.com/defaultxr.png","language":"Common Lisp","readme":"#+TITLE: bdef\n\n\"Buffer definition\"; abstraction of audio buffers for Lisp sound synthesis systems.\n\nBasically, this simplifies buffer management in [[https://github.com/byulparan/cl-collider][cl-collider]], making them easier to use.\n\n*Note:* Previously, Bdef for SuperCollider was hosted at this URL. That repository has since moved [[https://github.com/defaultxr/supercollider-bdef][here]].\n\n* Intro\n\nBdef is available from Quicklisp, so you can simply Quickload it:\n\n#+BEGIN_SRC lisp\n  (ql:quickload :bdef)\n#+END_SRC\n\nIt 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:\n\n#+BEGIN_SRC lisp\n  ;; integration with cl-patterns and cl-collider:\n  (ql:quickload '(bdef/cl-patterns bdef/cl-collider))\n#+END_SRC\n\nTo load a buffer from a file, provide the path to the ~bdef~ function:\n\n#+BEGIN_SRC lisp\n  (bdef \"~/path/to/your/buffer.mp3\")\n\n  ;; you can also give it an alias:\n  (bdef :foo \"/path/to/buffer.wav\")\n\n  ;; the buffer can then be referred to with it:\n  (bdef :foo)\n#+END_SRC\n\n~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:\n\n#+BEGIN_SRC lisp\n  ;; cl-collider:\n  (synth :playbuf :buffer (bdef :foo)) ; will work if you've loaded the bdef/cl-collider system and defined a synth named :playbuf.\n\n  ;; cl-patterns:\n  (play (event :instrument :playbuf :buffer :foo)) ; will work if you've loaded the bdef/cl-patterns system and defined a synth named :playbuf.\n  ;; 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.\n#+END_SRC\n\nMetadata can be associated with bdefs for various uses:\n\n#+BEGIN_SRC lisp\n  (setf (bdef-metadata :foo :bpm) 120) ; set the \"bpm\" metadatum to 120\n#+END_SRC\n\nSome metadata is automatically generated; for example, the tempo may be automatically detected from the filename or id3 tags.\n\nbdef 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.\n\n#+BEGIN_SRC lisp\n;; define three consecutive regions, one second long each:\n(make-splits (list (list 0 1) (list 1 2) (list 2 3)) :unit :seconds)\n\n;; auto-generate splits from sound onsets in a file using the aubio library:\n(splits-from-aubio-onsets \"/path/to/file.wav\")\n#+END_SRC\n\n[[https://aubio.org][Aubio]] is an external library of audio analysis functions. If installed, splits can be automatically generated from its analyses.\n\nbdef can also generate splits from other formats as well:\n- OP-1 drumsets (~splits-from-op-1-drumset~, but automatically parsed from any valid ~aif~ or ~aiff~ file)\n- Audacity labels (~splits-from-audacity-labels~)\n- Renoise regions (planned for future implementation)\n\nSee the following section for detail on more features of the bdef library.\n\n* Features\n\n** Can be re-evaluated without loading a new buffer:\n\nCompare:\n\n#+BEGIN_SRC lisp\n  (defparameter *buf* (cl-collider:buffer-read \"/buffer.wav\"))\n\n  (defparameter *buf* (cl-collider:buffer-read \"/buffer.wav\")) ; the same variable, and same file!\n\n  (length (remove nil (slot-value *s* 'cl-collider::buffers))) ; =\u003e 2 -- duplicate buffers!\n#+END_SRC\n\nversus:\n\n#+BEGIN_SRC lisp\n  (bdef :buf \"/buffer.wav\") ; here we give it the name :buf\n\n  (bdef :foo \"/buffer.wav\") ; same file, different \"name\"...\n\n  (length (remove nil (slot-value *s* 'cl-collider::buffers))) ; =\u003e 1 -- no duplicate buffers :D\n#+END_SRC\n\n...To force a file to be reloaded, simply call ~bdef-free~ on it, then call ~bdef~ again.\n\n** Automatically converts files unsupported by the backend if you have ffmpeg installed:\n\n#+BEGIN_SRC lisp\n  (bdef :bar \"/blah.mp3\") ; works!\n#+END_SRC\n\nIt does this by storing them in a temporary directory (~/tmp/bdef/~ by default on linux and mac).\n\n** No additional name needed if loading from a file:\n\n#+BEGIN_SRC lisp\n  (bdef \"/my-file.ogg\")\n#+END_SRC\n\n** Supports pathname abbreviations:\n\n#+BEGIN_SRC lisp\n  (bdef \"~/cool-sound.wav\") ; will find a cool sound in your home directory\n#+END_SRC\n\n** Loads mono files as stereo by default.\n\nFor consistency. To load as mono, supply 1 for ~bdef~'s ~num-channels~ keyword argument. To load buffers as mono by default so you don't need to specify it each time you load a buffer, you can set ~*bdef-default-num-channels*~ to ~1~.\n\n** Supports loading in wavetable format:\n\n#+BEGIN_SRC lisp\n  (bdef \"~/wilhelm.wav\" :wavetable t) ; load the Wilhelm scream as a wavetable\n#+END_SRC\n\n** Supports loading envelopes as buffers:\n\nEither as wavetables, or standard.\n\n** Integration with [[https://github.com/byulparan/cl-collider][cl-collider]]:\n\n#+BEGIN_SRC lisp\n  (cl-collider:bufnum (bdef :sound)) ; returns the buffer number.\n\n  (cl-collider:synth :playbuf :buffer (bdef :sound)) ; when bdef/cl-collider is loaded, bdef objects are automatically coerced to their buffer ID where it is needed.\n#+END_SRC\n\nLoad the ~bdef/cl-collider~ system to enable this.\n\n** Integration with [[https://github.com/defaultxr/cl-patterns][cl-patterns]]:\n\n#+BEGIN_SRC lisp\n  (cl-patterns:play (bdef :sound)) ; plays the buffer using the *cl-collider-buffer-preview-synth* set in cl-patterns.\n\n  (cl-patterns:play (cl-patterns:event :instrument :playbuf :buffer (bdef :sound))) ; when bdef/cl-patterns is loaded, bdef objects are automatically coerced to their buffer ID where it is needed.\n#+END_SRC\n\nLoad the ~bdef/cl-patterns~ system to enable this.\n\n** Supports multiple sound server backends:\n\n[[https://supercollider.github.io/][SuperCollider]]/[[https://github.com/byulparan/cl-collider][cl-collider]] is the primary backend tested against, however [[https://incudine.sourceforge.net/][Incudine]] is also supported for most functionality.\n\nEnable the cl-collider backend, for example, like so:\n\n#+BEGIN_SRC lisp\n  (ql:quickload :bdef/cl-collider)\n#+END_SRC\n\n** Allows metadata about the buffer to be stored:\n\n#+BEGIN_SRC lisp\n  (setf (bdef-metadata (bdef :snd) :bpm) 99) ; set :snd's tempo to 99 BPM.\n\n  (bdef-metadata (bdef :snd) :bpm) ; get the stored bpm value.\n#+END_SRC\n\n** Automatically set various metadata when a bdef is created:\n\n#+BEGIN_SRC lisp\n  ;; load a file with its bpm in its filename:\n  (bdef :my-file \"~/my-file-128bpm.wav\")\n\n  ;; the bpm is automatically stored as metadata:\n  (bdef-metadata :my-file :bpm) ; =\u003e 128\n#+END_SRC\n\nYou 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.\n\nAdditional metadata is loaded asynchronously in background threads using futures from the [[https://common-lisp.net/project/eager-future/][eager-future2]] library. If a requested metadatum is still being generated, ~bdef-metadata~ will block until the result is available.\n\n** Automatically generate metadata from functions:\n\n#+BEGIN_SRC lisp\n  (setf (bdef-metadata :foo :bpm) 142) ; sets the \"tempo\" metadata key instead to its beats per minute value\n\n  ;; tempo is stored as beats per second:\n  (bdef-metadata :foo :tempo) ; =\u003e 71/30 (142 beats per minute in beats per second)\n\n  ;; beats per minute is still available, dynamically calculated from the tempo key:\n  (bdef-metadata :foo :bpm) ; =\u003e 142\n#+END_SRC\n\nYou can define your own \"dynamic metadata\" with ~define-bdef-dynamic-metadata~.\n\n** \"Splits\" functionality to define split points or regions in buffers:\n\n#+BEGIN_SRC lisp\n  (make-splits (list 0 0.25 0.5 0.75) :bdef (bdef :foo)) ; splits at the start, 25%, 50%, and 75% into the file.\n\n  (splits-from-audacity-labels \"/path/to/label.txt\") ; make a splits object from an Audacity labels file.\n\n  (setf (bdef-splits :my-bdef) *) ; set the :my-bdef bdef's :splits metadatum to the splits object generated from the above.\n\n  (splits-point :my-bdef 3 :start :second) ; get the start of :my-bdef's fourth split in seconds.\n#+END_SRC\n\n** Splits integration with cl-patterns:\n\n#+BEGIN_SRC lisp\n  (pbind :instrument :playbuf ; if you've defined a synth named :playbuf that accepts the parameters buffer, start, and end.\n         :buffer (bdef :my-bdef)\n         :split (pwhite 0 (1- (splits-length :my-bdef))) ; pick a random split\n         :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 :buffer.\n         :dur 1)\n#+END_SRC\n\n** Integration with the [[https://aubio.org/][Aubio]] audio analysis library if installed:\n\n#+BEGIN_SRC lisp\n(bdef::splits-from-aubio-onsets \"/path/to/audio/file.wav\")\n\n(bdef :pee \"/path/to/pee.wav\") ; since no BPM is listed in the filename, aubio is used to detect it (if installed)...\n\n(bdef-metadata :pee :tempo) ; ...and it is stored in the bdef's :tempo metadatum! nice!\n#+END_SRC\n\n** Ability to import splits from OP-1 drumset file metadata:\n\n#+begin_src lisp\n  (bdef::splits-from-op-1-drumset \"/path/to/op-1-drumset.aif\") ; generates a splits by parsing the metadata in the file.\n#+end_src\n\nNote that any ~aif~ or ~aiff~ file will automatically be checked for OP-1 metadata, which will be parsed and stored in the ~splits~ bdef metadata key if it is found.\n\n* Backends\n\nCurrently, bdef supports SuperCollider via cl-collider as a backend. There is also basic (likely buggy) Incudine support - this will be improved later.\n\nTo write your own backend, you will need to implement the following methods on your backend's buffer class:\n\n- ~bdef-backend-supported-file-types~\n- ~bdef-backend-load~\n- ~bdef-backend-free~\n- ~bdef-length~\n- ~bdef-sample-rate~\n- ~bdef-channels~\n- ~bdef-id~ (optional if your backend doesn't use buffer IDs)\n- ~bdef-file~ (optional if your backend doesn't keep track of what file a buffer was loaded from)\n- ~bdef-frames~\n\nAll other functionality is derived from those functions.\n\nFor 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 [[file:cl-collider.lisp][cl-collider.lisp]] for an example.\n\n* Future\n\n- Fix the various minor/not-so-minor issues marked with \"FIX\" in the code.\n- We have ~bdef-frames~ to get buffer data; we should have support for setting buffer data as well.\n- 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\"~.)\n- \"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.\n- Allow importing as ~splits~ from ~.srt~ (subtitle) files, ~.tsv~ (tab-separated values; this seems to be what Audacity uses, and Whisper has an option to export in this format), and ~.vtt~ (WebVTT; similar to ~.srt~)?\n- Auto-generate metadata with [[https://librosa.org/][librosa]] ([[https://github.com/librosa/librosa/][github]]) similar to how we do for Aubio.\n  https://librosa.org/doc/latest/index.html\n  https://librosa.org/doc/latest/tutorial.html\n- Rename the ~:cl-collider~ backend to ~:supercollider~ for consistency with cl-patterns.\n- Allow allocating an empty buffer by specifying the number of frames as the value.\n- Rename ~bdef-frames~ to ~bdef-data~ ? This is what Incudine calls it (~buffer-data~) and it's less ambiguous whether \"frames\" refers to the contents of the frames, or to the number of frames.\n- Functionality to load multiple files at once and deal with multiple bdefs at once. i.e. \"load all files in this directory, get a list of the resulting bdefs\".\n- Synchronous loading, i.e. variant of the ~bdef~ function which only returns once the file is loaded/buffer is ready.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdefaultxr%2Fbdef","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdefaultxr%2Fbdef","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdefaultxr%2Fbdef/lists"}