A library for writing patterns to generate or process (a)musical sequences of mathematically (un)related (non-)compound values in Lisp.
Put more simply, cl-patterns is a system for making music and noise via Lisp code.
It is heavily inspired by SuperCollider’s patterns system, with aims to implement much of it, but in a more robust, expressive, consistent, reflective, and lispy way:
- robust: prefer coercing values into something “correct” rather than failing or giving an error. if you’re “in the zone” and writing music, you probably want your compositional tools to “do what you mean” and allow you to take as many sensible shortcuts as possible, rather than forcing you to waste time manually declaring and setting up everything.
- expressive: make writing music as easy and “natural” as possible, so that patterns can be built in real-time, in performance settings, without having to think so hard about how to bend the library to your will. I feel this is a weakness of SuperCollider.
- consistent: edge cases minimized, arguments for the various functions in an intuitive order, thus resulting in less cognitive load for the user.
- reflective: store more data about the stream state and more metadata about the patterns. make it easier for a pattern to access the values of another pattern, for patterns to affect other patterns, etc.
- lispy: prefer lisp idioms rather than direct translations of the SuperCollider way of doing things (while still keeping things relatively similar so it’s not a huge adjustment for SC users to make).
In addition to emulating most of SuperCollider’s patterns system, another goal is to further extend it with more tools and more ways to write patterns/sequences. The most obvious example being a “drum sequence” notation like k - - - k - - - k - - - k - - - for a four-to-the-floor beat. The idea is that Lisp’s macros should make it possible to more expressively write music with code.
Make sure you have Quicklisp installed and working with your Lisp implementation, then load cl-patterns:
(ql:quickload 'cl-patterns)
(use-package 'cl-patterns)Create a pattern like so:
(defparameter *pat* (pbind :foo (pseq '(1 2 3))
:bar (prand '(9 8 7) 5)))Since patterns are basically “templates”, you need to turn them into pstream objects in order to actually get output from them:
(defparameter *pstream* (as-pstream *pat*))Then, you can get results from the pstream one at a time with next, or many at a time with next-n or next-upto-n:
(next-n *pstream* 3)
;; => ((EVENT :FOO 1 :BAR 8) (EVENT :FOO 2 :BAR 9) (EVENT :FOO 3 :BAR 8))To actually hear sound output, you’ll need to start an audio server. Right now, SuperCollider is the main audio server that cl-patterns is tested against, but there is also preliminary support for Incudine as well as MIDI output through ALSA.
To use the SuperCollider backend, load the cl-patterns/supercollider system with quicklisp. This will automatically take care of loading the required cl-collider library for you:
(ql:quickload :cl-patterns/supercollider)Once loaded, you can start a backend using the backend-start function:
(backend-start 'supercollider)From here, you can take a look at the code in the supercollider-example.lisp file for a quick example of how to define your own synths and play them with patterns. You may also be interested in my cl-collider tutorial for a more in-depth introduction to cl-collider.
For more information on how to use cl-patterns, refer to tutorial.org for an introduction.
You can get a list of all defined patterns using (all-patterns). Each pattern has usage information and an example in its docstring, which of course can be accessed using Common Lisp’s standand describe and documentation functions.
This library isn’t just a copy of SuperCollider’s patterns - I wanted to improve upon them as well. For a list of notable features in cl-patterns, see features.org.
If you’re familiar with SuperCollider, you may also want to look at sc-differences.org for a listing of differences between this library and SC’s patterns, or sc.org for a listing of patterns in SuperCollider and their equivalent (and implementation status) in cl-patterns.
Included in res/emacs/ are a few small libraries that make it more convenient to work with cl-patterns and the synthesis engines it supports from inside Emacs. Their functionality includes:
- commands for playing/stopping the pattern, buffer, proxy, or other object under point
- command to stop all playing patterns, nodes, etc.
- command to open the SuperCollider documentation for a specified class (with completion)
- skeletons for commonly-used patterns/functions
- and a few other utility functions.
Here’s the recommended setup to load these libraries automatically via your Emacs init file:
(defun cl-patterns-helpers-load ()
(interactive)
(sly-eval-async '(cl:let ((system (asdf:find-system "cl-patterns" nil)))
(cl:when system (cl:namestring (asdf:system-source-directory system))))
(lambda (path)
(load (concat path "res/emacs/cl-patterns-helpers") nil nil nil t)
(load (concat path "res/emacs/cl-patterns-skeletons") nil nil nil t)))
(define-key sly-mode-map (kbd "C-c p") 'cl-patterns-play-or-end-context-or-select-pdef)
(define-key sly-mode-map (kbd "C-c P") 'cl-patterns-play-or-stop-context-or-select-pdef)
(define-key sly-mode-map (kbd "C-c s") 'cl-patterns-stop-all)
(define-key sly-doc-map (kbd "s") 'cl-patterns-supercollider-documentation))
(add-hook 'sly-connected-hook 'cl-patterns-helpers-load)The above should also work with slime; just replace all instances of sly with slime.
Right now, the library may be described as being in a “late alpha” stage. Fewer and fewer major changes are being made, but a few major refactors and API changes are in the works. Most of the included patterns and exported functionality now have relatively stable APIs as well as tests to guard against regressions. There may still be the occasional change of functionality in the library, though most user-facing changes will be gracefully deprecated and documented in commit messages, so check those if you have any issues after updating.
Despite that, lots of functionality is already written and the library should be stable enough for normal usage in most cases.
There is already a decent amount of documentation in the doc directory, and all exported symbols are documented (in fact, one of the tests checks that all exported symbols have docstrings). If any aspect of the library isn’t clear, please ask so the documentation can be made more complete.
See TODO.org and roadmap.org for a listing of tasks that need to be completed and ideas for future features. The code itself is also littered with comments marked FIX, to note known issues and possible improvements or optimizations that could be made.
The SuperCollider backend is the primary backend that cl-patterns is tested against, so for the most part its functionality should “just work”.
The Incudine backend is missing various functionality such as multichannel expansion, and has not been thoroughly tested in some time, so it may have bit-rotted as the library has evolved. This backend is planned to be greatly improved once the core of the library (i.e. the clock and timeline abstractions) has been fully reworked.
Most of the ALSA MIDI backend’s basic functionality is complete, but it has not been tested or expanded upon as much as the SuperCollider backend yet.
- README.org - This file. Self-explanatory.
- LICENSE - The MIT license.
- cl-patterns.asd - File containing the definitions of cl-patterns’ ASDF systems.
- backends.org - Information about cl-patterns backends, including how to write your own.
- cookbook.org - A “cookbook” containing ideas and inspiration for your cl-patterns hacking.
- features.org - Listing of notable features of cl-patterns.
- isobar.org - List of patterns in isobar and their equivalents in cl-patterns.
- other-libraries.org - Listing of other libraries that have similar goals or may be useful in conjunction with cl-patterns.
- patterns.org - Organized index of the pattern classes included in cl-patterns.
- roadmap.org - General overview of major goals for the future development of cl-patterns.
- sc.org - A list of pattern classes and special keys in SuperCollider, and the status of their implementation in cl-patterns.
- sc-differences.org - A listing of (some of the) things that differ between cl-patterns and SuperCollider.
- special-keys.org - Description of keys that (by default) have special effects when used in an event or pbind.
- supercollider-example.lisp - A short example of how to use cl-patterns with cl-collider.
- TODO.org - A list of things and ideas that have not yet been implemented into cl-patterns, but may be in the future.
- tutorial.org - Explanation of the basics of cl-patterns, meant for people who aren’t familiar with SuperCollider’s patterns.
- writing-your-own.org - Information about how to write your own pattern classes.
- cl-patterns-helpers.el - Helper functions to make cl-patterns more convenient to use from Emacs (see above).
- cl-patterns-skeletons.el - Emacs skeletons (templates) for quickly inserting commonly-used lisp forms.
- package.lisp - File containing the definition of cl-patterns’ Common Lisp package.
- utility.lisp - General utility functions and special variable definitions.
- conversions.lisp - Functions to convert between units (i.e. midinote to frequency, decibels to amplitude, etc.).
- scales.lisp - Data, structs, and functionality relating to musical pitch (i.e. scales, tuning, etc).
- event.lisp - Code to represent and deal with events. The
eventclass, special keys (i.e.freq,amp…), etc. - timeline.lisp - Timeline class and functionality.
- backend.lisp - Generic functionality for working with the backends, which do the work of actually generating audio.
- render.lisp - Functionality for rendering patterns in non-realtime.
- clock.lisp - Scheduling, to make sure that patterns are kept in sync and events are played at the proper time.
- patterns.lisp - General pattern functionality and the set of fundamental patterns - the
patternsuperclass,pbind,pseq,pk, etc. - pdef.lisp -
pdefand associated functionality to define and reference “named patterns”. - pmeta.lisp -
pmeta; meta-pattern for embedding and controlling other patterns. - bjorklund.lisp - Euclidean pattern functionality -
pbjorklundand related functions. - cycles.lisp - TidalCycles-inspired patterns and notation, i.e.
pcycles, etc. - track.lisp - Tracker-inspired patterns and notation -
ptrackand related functions and (reader) macros. - sc-compatibility.lisp - Patterns intended to be fully compatible with SuperCollider’s patterns system.
- export.lisp - Export all defined patterns in the
*patterns*list.
- supercollider.lisp - Code to interface cl-patterns with SuperCollider via the cl-collider library.
- incudine.lisp - Code to interface cl-patterns with Incudine.
- debug.lisp - Basic debugging backend for printing and/or storing output events without producing audio.
- alsa-midi.lisp - Code to interface cl-patterns with ALSA MIDI via cl-alsaseq.
- midifile.lisp - MIDI file functionality (load the
cl-patterns/midifilesystem to use this). - renoise.lisp - Renoise project file functionality (load the
cl-patterns/renoisesystem to use this). - supercollider-score.lisp - SuperCollider Score file functionality (part of the
cl-patterns/supercollidersystem).
- generic-cl.lisp - Additional methods for generic-cl (load the
cl-patterns/generic-clsystem to enable them). - sequence.lisp - Additional methods for implementations that support extensible sequences.
- swank.lisp - Creature comforts for SLIME/SWANK users.
- slynk.lisp - Creature comforts for Sly/Slynk users.
Contains the files for the FiveAM-based test suite for the library.
If you need support or just want to chat, the official cl-patterns chatroom is on Matrix at #cl-patterns:struct.ws, and bridged to IRC at #cl-patterns on irc.libera.chat.
Any bugs, feature requests, suggestions, etc should be submitted to the GitHub issue tracker. Please feel free to submit issues even if they might already be known as it helps to figure out which parts of the library to prioritize development on. It’s also nice to know that people are using the library. :)