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 = 124.0
local beat = 60.0 / bpm
local export_options = {
  sample_rate = 44100,
  normalize = "rms",
  target_db = -16.0,
  true_peak_db = -1.0,
  midi_velocity_gain = 1.9,
  midi_min_velocity = 0.6,
}
local instruments = pulse.instruments()
assert(#instruments >= 150)

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

local function voicing(root, kind, shifts)
  local source = pulse.chord(root, kind)
  local chord = {}
  for index, shift in ipairs(shifts) do
    chord[index] = pulse.transpose(source[((index - 1) % #source) + 1], shift)
  end
  return chord
end

local pad = pulse.sequence()
  :chords({
    voicing("D3", "min7", {0, 0, 12, 12}),
    voicing("Bb2", "maj7", {0, 12, 0, 12}),
    voicing("F3", "maj7", {0, 0, 12, 12}),
    voicing("C3", "dominant7", {0, 0, 12, 12}),
  })
  :durations(rep(beat * 2.0, 4))
  :instrument("supersaw")
  :volume(0.44)
  :pan(0.18)
  :velocity(0.52)
  :effect("filter", { type = "low_pass", cutoff = 2600.0, resonance = 0.22 })
  :effect("chorus", "wide")

local lead = pulse.sequence()
  :notes({
    pulse.scale("D4", "dorian")[1], pulse.scale("D4", "dorian")[3], pulse.scale("D4", "dorian")[5], pulse.scale("D4", "dorian")[6],
    pulse.scale("D4", "dorian")[8], pulse.scale("D4", "dorian")[6], pulse.scale("D4", "dorian")[5], pulse.scale("D4", "dorian")[3],
    pulse.scale("F4", "ionian")[5], pulse.scale("F4", "ionian")[6], pulse.scale("F4", "ionian")[8], pulse.transpose(pulse.scale("F4", "ionian")[2], 12),
    pulse.scale("C4", "mixolydian")[8], pulse.scale("C4", "mixolydian")[7], pulse.scale("C4", "mixolydian")[5], pulse.scale("C4", "mixolydian")[3],
  })
  :durations(rep(beat / 2.0, 16))
  :instrument("synth_lead")
  :volume(0.52)
  :pan(-0.16)
  :velocity(0.64)
  :effect("delay", "dotted_eighth")

local beat = pulse.drum_machine("808")
  :steps(16)
  :step_duration(beat / 4.0)
  :kick("x---x---x-xxx---")
  :snare("----x-------x---")
  :hihat("x-x-xxx-x-x-xxxx")
  :open_hihat("--x-----x---x---")
  :clap("----x-------x---")
  :grid()
  :repeat_times(1)
  :volume(0.78)
  :effect("compressor", "drum_bus")

local extra = pulse.drum_grid()
  :track("euclidean")
  :steps(16)
  :step_duration(60.0 / bpm / 4.0)
  :sound("clap_808", pulse.euclidean(5, 16))
  :sound("hihat_909_sizzle_layer", pulse.euclidean(7, 16))
  :accent("x---x---x---x---")
  :volume(0.34)
  :pan(0.32)

local song = pulse.song()
  :tempo(bpm)
  :add(pad)
  :add(lead)
  :add_drum_grid(beat)
  :add_drum_grid(extra)
  :master_effect("eq", "bright")
  :master_effect("limiter", "standard")

song:export_wav("output/capability-expansion.wav", export_options)
song:export_flac("output/capability-expansion.flac", export_options)
song:export_midi("output/capability-expansion.mid", export_options)