Skip to content
Lua Perl
Branch: master
Clone or download
graue Disable HistArray lookup safety checks for filter
This makes the filter 8.9% faster in my testing.
Latest commit 4ddb9e9 Aug 24, 2013

README.md

Luasynth

Luasynth is a small audio framework, written in Lua, emphasizing clean, modular, declarative code. For a taste, read the source of its panning effect (effects/pan.lua) or delay (effects/delay.lua). Both are very short.

The plan: allow sound generators (oscillator, noise generator, sampler...) and effects (gain, distortion, reverb, delay...) to be written, chained together, and embedded in a host program. It's like a miniature version of the VST or LV2 plugin interfaces.

Why use Lua? Unlike other high-level languages, it's extremely simple to embed and LuaJIT provides excellent performance for this type of thing.

Installing and using

By itself, Luasynth doesn't do very much. It only comes with a basic demo app for generating or processing audio offline, via the command line. To use that, install LuaJIT. You'll probably also want SoX to convert into and out of the raw, 32-bit, floating-point audio format Luasynth uses.

Here's an example:

sox input.wav -tf32 -c2 -r44100 -q - \
 | ./luasynth delay -len 83 -feedback 90 \
 | ./luasynth amp -gain -6 \
 | sox -tf32 -c2 -r44100 -q - -b16 delayed.wav

This adds a delay to input.wav, reduces the volume by 6 dB, and writes the output to delayed.wav. The -tf32 -c2 -r44100 options to SoX tell it to handle the format Luasynth uses, while -b16 converts the output file back to 16-bit, the resolution of CD-quality audio.

In this example, we're using luasynth twice. The first usage

./luasynth delay -len 83 -feedback 90

creates a delay unit with the len knob (length of time to delay) set to 83 milliseconds and feedback (amount of feedback) set to 90%. The second usage

./luasynth amp -gain -6

creates an amp unit and sets the gain knob, which is in decibels, to -6. For a full list of available units, run ./luasynth help units, and for help on an individual one, run ./luasynth help <unit name>.

The sample rate is assumed to be 44100 Hz by default, but can be changed by setting the environment variable RATE. For example, to work at 48KHz, type export RATE=48000 in the shell followed by similar commands to those above.

Embedding

Moon-Noise, a random noise generator, provides a small example of embedding Luasynth (in another Lua program in this case). You can also embed Luasynth in a C application using Lua's C API.

Luasynth's command-line driver (main.lua, which you're calling if you run ./luasynth as above) requires LuaJIT for binary I/O to work. However, the audio units themselves will run (albeit slower) in regular Lua.

There's no complete documentation of the API yet, sorry, but it's very simple, and the tests in spec/wrap_spec.lua do describe how most of it works.

Tests

Luasynth uses Busted for testing. To run tests:

busted spec

The specs cover most, if not all, of Luasynth's API, including graceful error handling in case the API is misused. Audio units themselves are not currently tested. I'm not aware of an easy way to test that, for example, a sine-wave generator or lowpass filter is working as expected, but I'm open to suggestions.

History and design

Luasynth is an evolution of similar concepts that I explored in two past projects, both written in C: Synth and Truesynth.

I started writing "Synth" way back in 2005. At the time, I was using OpenBSD as my home operating system, which I admit is a pretty unusual choice. There was next to no audio software available for OpenBSD, and I wanted to create a little toolbox for the basic stuff.

In Synth, all audio units are command-line programs, piped together to generate or process sound, like this:

square -freq 1000 -len 5000 \
 | filter -type bandpass -center 2000 -q 10 \
 | pan -angle -20 \
 | fmt -16 \
 | <some command to play or save the audio>

Luasynth comes with a command-line driver app that can be used similarly:

./luasynth osc -oscType square -freq 1000 -length 5 \
 | ./luasynth filter -filtType Bandpass -center 2000 -q 10 \
 | ./luasynth pan -angle 20 \
 | <command to convert, play or save... "fmt" is not included>

Both pipelines generate 5 seconds of a square wave, bandpass filter it, and pan it about halfway to the right.

But Truesynth and Luasynth are both embeddable. Audio units do not parse command-line arguments or handle file I/O directly. Instead, they define parameters ("knobs" in Luasynth) that the host application can set, and methods the host application can call to process or generate audio. The command-line interface is therefore just one possible host application.

From 2009 to 2010, while a member of the experimental noise band Extremities, I used Truesynth as part of my rig to improvise and play live shows. The host application created a software feedback loop which passed through several Truesynth effects, whose parameters were controlled by the orientation, rotation and button state of a joystick.

Luasynth refines the concept by using Lua as the implementation language instead of C. Compare a delay effect in Truesynth (C) to the same effect in Luasynth. The C version is fragile, contains repetitive boilerplate code and is written in terms of memory allocation, pointers and buffers. In contrast, the Lua code is simple and elegant, closely resembling a mathematical description of what the effect does. It also has the potential to one day run in web browsers, using compilation to JavaScript and the Web Audio API.

Luasynth was one of my projects while attending the Winter 2013 batch of Hacker School. Hacker School is awesome.

You can’t perform that action at this time.