mlua-pulse 0.1.0

Lua-friendly music composition and audio export bindings built on tunes and mlua
Documentation
local pulse = require("pulse")

local bpm = 110.0
local beat = 60.0 / bpm
local export_options = {
  sample_rate = 44100,
  normalize = "rms",
  target_db = -17.0,
  true_peak_db = -1.0,
}

local function rep(value, count)
  local values = {}
  for index = 1, count do
    values[index] = value
  end
  return values
end

local keys = pulse.sequence()
  :chords({
    pulse.chord("F3", "maj7"),
    pulse.chord("C3", "maj7"),
    pulse.chord("D3", "min7"),
    pulse.chord("Bb2", "maj7"),
  })
  :durations(rep(beat * 2.0, 4))
  :instrument("electric_piano")
  :volume(0.66)
  :pan(-0.12)
  :velocity(0.58)
  :effect("reverb", "room")

local melody = pulse.sequence()
  :notes({pulse.scale("F4", "lydian")[3], pulse.scale("F4", "lydian")[5], pulse.scale("F4", "lydian")[8], pulse.transpose(pulse.scale("F4", "lydian")[2], 12),
          pulse.scale("D4", "minor")[8], pulse.scale("D4", "minor")[6], pulse.scale("C4", "ionian")[5], pulse.scale("Bb3", "lydian")[8]})
  :durations(rep(beat, 8))
  :instrument("music_box")
  :volume(0.38)
  :pan(0.22)
  :velocity(0.48)
  :at(beat / 2.0)
  :effect("delay", "eighth_note")

local song = pulse.song()
  :tempo(bpm)
  :add(keys)
  :add(melody)
  :master_effect("eq", "warm")
  :master_effect("limiter", "transparent")

song:export_wav("output/playback-preview.wav", export_options)

if os.getenv("MLUA_PULSE_PLAYBACK") == "1" then
  local engine = pulse.playback()
  local handle = engine:play_realtime(song)

  handle:volume(0.7)
    :pan(-0.15)
    :rate(1.0)

  handle:pause()
  handle:resume()
  handle:stop()
end