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)
(in-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, simply 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)
From here, you can take a look at the code in the supercollider-example.lisp file for a short 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)
. Every pattern should have usage information and examples in its docstring, which of course can be accessed using the standand describe
or 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.
Right now, the library may be described as being in a “alpha” state, as major changes (which may break code you write) are still very likely to happen. However, these changes should be 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.
Many tests have already been written to help guard against regressions.
Much documentation is still being written, but there is already a good amount of information in the doc directory, and in the docstrings for the patterns, functions, etc.
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” noting various known issues and possible changes and optimizations that could be made.
The SuperCollider backend is the primary backend that cl-patterns is tested against so it should generally work the best and should be usable for most purposes.
The Incudine backend should work for most purposes, though currently multichannel expansion does not work.
The ALSA MIDI backend has some functionality complete and should be usable for basic tasks, but is still very much a work in progress.
Don’t cut yourself on these. These are the weaker parts of the library; they’re still very much WIPs and are even less likely to be correct :^)
- scales/tunings - calculations may be wrong sometimes; sometimes throw errors
pcycles
- still needs work, API may change- sc-compatibility patterns - hardly anything written for these!
- multichannel expansion - still somewhat new, might not work with all backends
- README.org - this file. self-expanatory, I’d hope.
- LICENSE - the MIT license.
- cl-patterns.asd - cl-patterns systems definition file.
- backends.org - information about cl-patterns backends, including how to write your own.
- cookbook.org - a cookbook of ideas and inspiration for your cl-patterns hacking.
- features.org - listing of notable features of 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 in SuperCollider and their cl-patterns implementation status.
- sc-differences.org - listing of things that differ between cl-patterns and SuperCollider.
- special-keys.org - description of keys that have special effects when used in an event or pbind.
- supercollider-example.lisp - 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 basic concepts of cl-patterns, meant for people who have never used SuperCollider’s patterns.
- writing-your-own.org - information about how to write your own pattern classes.
- package.lisp - the package definition file.
- 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 - musical pitch (scales/tuning) data and structs.
- event.lisp - code to represent and deal with events. includes the
event
class, information about special keys (i.e.freq
,amp
…), etc. - eseq.lisp - event sequence class and functionality.
- backend.lisp - code to handle “backends”; i.e. how cl-patterns will actually “play” events.
- clock.lisp - the scheduling functionality to make sure that each event is played at the proper time.
- sugar.lisp - additional syntax sugar and utility functions, accessible via the
cl-patterns/sugar
subsystem.
- patterns.lisp - general pattern macros and functionality + the standard set of patterns; includes the
pattern
superclass,pbind
,pseq
,pk
, etc. - bjorklund.lisp - Euclidean pattern functionality such as
pbjorklund
, etc. - cycles.lisp - TidalCycles-inspired patterns and notation, i.e.
pcycles
, etc. - tracker.lisp - tracker-inspired patterns and notation, i.e.
ptracker
and associated functions, macros, reader macros, etc. - sc-compatibility.lisp - patterns intended to be fully compatible with SuperCollider’s patterns system.
- 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 debug backend. responds to all events, printing and storing them without any audio output.
- alsa-midi.lisp - code to interface cl-patterns with cl-alsaseq.
- midifile.lisp - functionality to interact with MIDI files (load the
cl-patterns/midifile
system to use this). - supercollider-score.lisp - functionality to interact with SuperCollider Score files (load the
cl-patterns/supercollider/score
system to use this).
- 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.
As far as I’m aware there isn’t a huge community of people using this library to make music yet. However, if you need support or just want to chat, the “official” room is on Matrix: #cl-patterns:struct.ws.
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 what parts of the library to prioritize development on. It’s also nice to hear that people are using the library. :)