in which lisp generates musicLivecoding Music with Fennel and RenoiseAuthorabhirag
LicenseAGPL
Version3.5.4SourceGitHub

Livecoding Music with Fennel and Renoise

tl;dr

  • I extended the Rust library powering algorithmic music generation capabilities in Renoise digital audio workstation to also support Fennel

  • So now you can write Fennel (a Lisp that compiles to Lua) and create music:

--! fennel
(pattern {:unit "1/4"
          :pulse [1 0]
          :event ["c4"]})
  • Optionally install the companion tool I created for live-reloading .fnl and .lua files if you don’t want to be tied to the Renoise script editor and want to use your own code editor. Also grab the fennel-ls docset for editor support

  • Enough ceremony, go make some noise!

Why?

It’s hard to argue against programming being an art form when programs can sound like this:

Programming and creating music are the two things that have always helped me drown out the noise around me (and in my head). It has been a few years, but I still clearly remember the day I found Overtone and Emacs Live, I was instantly hooked and Sam Aaron’s work has inspired me ever since. I realized live coding is about expressing myself and found Lisp to be perfect for that. A language willing to bend at my every whim. Malleable. Mine.

So when I found that:

  • Renoise was now shipping with support for programmatically creating music in Rust or Lua
  • The dynamically loaded library behind it was open source and written in Rust

…it was enough for me to be nerd sniped into adding support for Fennel. I would be remiss not to mention Ramsey Nasser’s 8FL which is also a direct inspiration.

How?

  • The library already embeds a Lua VM via mlua for evaluating user scripts, which we’ll refer to as the engine VM hereon

  • To effectively sandbox user scripts, the engine VM is not given the LuaStdLib::PACKAGE capability which allows loading external Lua modules

  • The Fennel compiler is itself a Lua program that requires this capability to bootstrap its submodules, so a second dedicated compiler VM (the Fennel VM hereon) is spawned with it

  • The Fennel compiler source is vendored and compiled to bytecode once per process and reused across VM instantiations; when the Fennel VM is created, this bytecode is loaded and executed in it, producing the fennel module with a compileString function

  • Fennel scripts are passed to compileString, which returns Lua source that is then handed off to the engine VM for evaluation

  • A prelude compiled into the shared compiler scope provides custom macros to all scripts without explicit imports; src/bindings/prelude.fnl is where more macros can be added

Renoise with Fennel pattrns

Renoise with a Fennel phrase script in the built-in editor

What Else?

  • Also created a companion Renoise tool that watches a directory for .fnl and .lua files and live-reloads them into Renoise phrase scripts, so you’re not tied to the built-in script editor. Files follow a [instrument_index]-[phrase_index].(fnl|lua) naming convention to map to the right instrument and phrase
  • Also added a fennel-ls docset for the pattrns API, providing autocompletion and inline documentation when editing Fennel scripts in your own editor

Fin?

  • This is just the beginning, on to the fun part, making music!
  • Thanks to the Renoise devs for open sourcing pattrns! I’ll reach out soon to see if there’s room for Fennel support upstream
  • Also thanks to bakpakin, technomancy and the rest of the Fennel contributors for building such a great language
  • If this kind of thing appeals to you, which is frankly a niche within a niche, we probably have a lot in common. Let’s talk, potential friend!