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 = 118.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.58,
}

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

local fib = pulse.generate("fibonacci", { length = 16 })
local primes = pulse.generate("primes", { length = 16 })
local chaos = pulse.generate("logistic_map", { r = 3.86, initial = 0.37, length = 16 })
local notes = pulse.map_to_scale(fib, "minor_pentatonic", "C4", 2)
local counter = pulse.map_to_scale(primes, "dorian", "G3", 2)
local durations = pulse.normalize(chaos, beat / 3.0, beat)

local phrase = pulse.sequence()
  :notes(notes)
  :durations(durations)
  :instrument("electric_piano")
  :volume(0.58)
  :pan(-0.18)
  :velocity(0.58)
  :effect("delay", { time = beat * 0.75, feedback = 0.32, mix = 0.22 })

local answer = pulse.sequence()
  :notes(counter)
  :durations(rep(beat / 2.0, #counter))
  :instrument("mallet")
  :volume(0.34)
  :pan(0.26)
  :velocity(0.5)
  :at(beat / 2.0)
  :effect("reverb", "plate")

local harmony = pulse.sequence()
  :chords({
    pulse.chord("C3", "min7"),
    pulse.chord("Eb3", "maj7"),
    pulse.chord("Bb2", "maj7"),
    pulse.chord("G2", "dominant7"),
  })
  :durations(rep(beat * 2.0, 4))
  :instrument("warm_pad")
  :volume(0.46)
  :pan(0.0)
  :velocity(0.46)
  :effect("chorus", "subtle")

local beat_grid = pulse.drum_grid()
  :steps(16)
  :step_duration(beat / 4.0)
  :sound("kick_808", pulse.generate("cantor_rhythm_16"))
  :sound("snare_808", {4, 12})
  :sound("hihat_808_closed", "x-x-x-x-x-x-x-x-")
  :sound("shaker", pulse.euclidean(9, 16))
  :volume(0.7)
  :effect("compressor", "drum_bus")

local song = pulse.song()
  :tempo(bpm)
  :add(harmony)
  :add(phrase)
  :add(answer)
  :add_drum_grid(beat_grid)
  :master_effect("eq", "warm")
  :master_effect("limiter", "transparent")

song:export_wav("output/algorithm-generators.wav", export_options)
song:export_midi("output/algorithm-generators.mid", export_options)