Audio synthesis with LuaJIT, and performance

  • From: Henk Boom <henk@xxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Mon, 4 Jun 2012 21:47:07 -0400

Hi, I decided it would be a fun experiment to implement a Yamaha
DX7-style phase modulation synthesizer using LuaJIT. It creates 20
voices, each with 6 operators running sine waves from a lookup table.
The source code is pretty straight forward since I haven't yet added
envelopes or anything else, see synth.lua and synth.c here for lua and
c implementations:

https://gist.github.com/2871749

I also included portaudio.lua which is a first-pass interface to the
portaudio push api using the FFI, you can hear the synth by running
synth.lua with --play.

The performance with the current implementation isn't great, though,
to generate three minutes of audio took 27.729s for the LuaJIT version
and 6.996s for the C version, running each three times and taking the
minimum. The version of LuaJIT used was pulled from git earlier today.

This is after unrolling some loops in the lua version, which made a
pretty good difference. I also switched to calculating each voice 1024
samples at a time, rather than iterating through each voice for every
sample, and this helped as well. Increasing this buffer size more
helps, but will cause latency problems when I add message-handling to
the synth. Unfortunately I can't carry that loop down into the
individual operators since they can have arbitrary mutual recursion,
and delaying the recursion introduces high-frequency artifacts.

I have plans to runtime-generate lua code per-instrument, since most
of the modulation matrix is zero for any given instrument, but I'd
like to take a look at the numerical stuff before I make it more
complicated.

I don't have much experience optimizing lua code for LuaJIT, but -jv
seems to suggest everything goes smoothly. Does anyone have advice on
ways to optimize?

    henk

Other related posts: