local pulse = require("pulse")
local title = "kaze-ensemble"
local bpm = 88.0
local beat = 60.0 / bpm
local export_options = {
sample_rate = 44100,
normalize = "rms",
target_db = -17.5,
true_peak_db = -1.2,
midi_velocity_gain = 2.0,
midi_min_velocity = 0.6,
}
local function rep(value, count)
local values = {}
for index = 1, count do
values[index] = value
end
return values
end
local function degree(scale, value)
local unique = #scale - 1
local zero = value - 1
local octave = math.floor(zero / unique)
local position = (zero % unique) + 1
return pulse.transpose(scale[position], octave * 12)
end
local function line(scale, degrees)
local notes = {}
for index, value in ipairs(degrees) do
notes[index] = degree(scale, value)
end
return notes
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 g4 = pulse.scale("G4", "ionian")
local g3 = pulse.scale("G3", "ionian")
local e3 = pulse.scale("E3", "minor")
local c4 = pulse.scale("C4", "lydian")
local d4 = pulse.scale("D4", "mixolydian")
local g_bass = pulse.scale("G2", "ionian")
local e_bass = pulse.scale("E2", "minor")
local soft_filter = { type = "low_pass", cutoff = 5200.0, resonance = 0.12 }
local string_filter = { type = "low_pass", cutoff = 4300.0, resonance = 0.1 }
local function soft_kick(volume)
return pulse.drum_grid()
:sound("kick_acoustic", {0, 8})
:sound("cajon", {4, 12})
:step_duration(beat / 4.0)
:volume(volume)
:effect("filter", { type = "low_pass", cutoff = 1800.0, resonance = 0.08 })
:effect("compressor", "gentle")
end
local intro = pulse.phrase()
:add(
pulse.sequence()
:chords({
voicing("G3", "maj7", {0, 12, 0, 12}),
voicing("D3", "dominant7", {0, 12, 0, 12}),
voicing("E3", "min7", {0, 12, 0, 12}),
voicing("C3", "maj7", {0, 12, 0, 12}),
})
:durations(rep(beat * 2.0, 4))
:instrument("acoustic_guitar")
:volume(0.36)
:pan(-0.24)
:velocity(0.42)
:effect("filter", soft_filter)
:effect("reverb", "room")
)
:add(
pulse.sequence()
:notes(line(g4, {5, 6, 8, 6, 5, 3, 2, 3}))
:durations(rep(beat, 8))
:instrument("flute")
:volume(0.22)
:pan(0.22)
:velocity(0.34)
:at(beat)
:effect("filter", soft_filter)
:effect("reverb", "chamber")
)
:add(
pulse.sequence()
:notes(line(g_bass, {1, 5, 6, 3, 4, 1, 5, 5}))
:durations(rep(beat, 8))
:instrument("upright_bass")
:volume(0.38)
:velocity(0.48)
)
:repeat_times(2)
local verse = pulse.phrase()
:add(
pulse.sequence()
:chords({
voicing("G3", "maj7", {0, 12, 0, 12}),
voicing("B2", "min7", {0, 12, 0, 12}),
voicing("C3", "maj7", {0, 12, 0, 12}),
voicing("D3", "dominant7", {0, 12, 0, 12}),
})
:durations(rep(beat * 2.0, 4))
:instrument("acoustic_piano")
:volume(0.42)
:pan(-0.06)
:velocity(0.44)
:effect("reverb", "room")
)
:add(
pulse.sequence()
:notes(line(g3, {1, 5, 8, 5, 6, 3, 5, 1, 4, 8, 10, 8, 5, 3, 5, 4}))
:durations(rep(beat / 2.0, 16))
:instrument("pizzicato_strings")
:volume(0.2)
:pan(0.18)
:velocity(0.34)
:effect("filter", { type = "low_pass", cutoff = 3000.0, resonance = 0.08 })
)
:add(
pulse.sequence()
:notes(line(g4, {3, 5, 6, 8, 8, 6, 5, 3, 5, 6, 8, 10, 9, 8, 6, 5}))
:durations(rep(beat / 2.0, 16))
:instrument("flute")
:volume(0.27)
:pan(0.24)
:velocity(0.4)
:at(beat)
:effect("filter", soft_filter)
:effect("reverb", "chamber")
)
:add(
pulse.sequence()
:notes(line(g_bass, {1, 5, 6, 3, 4, 1, 5, 5}))
:durations(rep(beat, 8))
:instrument("fingerstyle_bass")
:volume(0.48)
:velocity(0.56)
)
:add_drum_grid(soft_kick(0.26))
:repeat_times(2)
local lift = pulse.phrase()
:add(
pulse.sequence()
:chords({
voicing("E3", "min7", {0, 12, 0, 12}),
voicing("C3", "maj7", {0, 12, 0, 12}),
voicing("G3", "maj7", {0, 12, 0, 12}),
voicing("D3", "dominant7", {0, 12, 0, 12}),
})
:durations(rep(beat * 2.0, 4))
:instrument("warm_pad")
:volume(0.26)
:velocity(0.36)
:effect("filter", { type = "low_pass", cutoff = 3600.0, resonance = 0.1 })
:effect("reverb", "hall")
)
:add(
pulse.sequence()
:notes(line(e3, {8, 10, 11, 10, 8, 6, 5, 6}))
:durations(rep(beat, 8))
:instrument("violin")
:volume(0.24)
:pan(0.18)
:velocity(0.36)
:effect("filter", string_filter)
:effect("reverb", "chamber")
)
:add(
pulse.sequence()
:notes(line(e_bass, {1, 5, 6, 3, 4, 1, 5, 5}))
:durations(rep(beat, 8))
:instrument("upright_bass")
:volume(0.44)
:velocity(0.5)
)
local chorus = pulse.phrase()
:add(
pulse.sequence()
:chords({
voicing("C3", "maj7", {0, 12, 0, 12}),
voicing("D3", "dominant7", {0, 12, 0, 12}),
voicing("G3", "maj7", {0, 0, 12, 12}),
voicing("E3", "min7", {0, 12, 0, 12}),
})
:durations(rep(beat * 2.0, 4))
:instrument("slow_strings")
:volume(0.34)
:velocity(0.44)
:effect("filter", string_filter)
:effect("reverb", "hall")
)
:add(
pulse.sequence()
:notes(line(g4, {8, 10, 12, 13, 12, 10, 8, 6, 8, 9, 10, 12, 10, 8, 6, 5}))
:durations(rep(beat / 2.0, 16))
:instrument("flute")
:volume(0.34)
:pan(0.22)
:velocity(0.48)
:effect("filter", soft_filter)
:effect("reverb", "chamber")
)
:add(
pulse.sequence()
:notes(line(c4, {5, 7, 8, 10, 8, 7, 5, 3, 5, 7, 8, 10, 12, 10, 8, 7}))
:durations(rep(beat / 2.0, 16))
:instrument("violin")
:volume(0.24)
:pan(-0.18)
:velocity(0.38)
:at(beat)
:effect("filter", string_filter)
:effect("reverb", "chamber")
)
:add(
pulse.sequence()
:notes(line(g_bass, {4, 1, 5, 6, 4, 1, 5, 1}))
:durations(rep(beat, 8))
:instrument("fingerstyle_bass")
:volume(0.5)
:velocity(0.58)
)
:add_drum_grid(soft_kick(0.3))
:repeat_times(2)
local bridge = pulse.phrase()
:add(
pulse.sequence()
:chords({
voicing("A2", "min7", {0, 12, 0, 12}),
voicing("D3", "dominant7", {0, 12, 0, 12}),
voicing("B2", "min7", {0, 12, 0, 12}),
voicing("E3", "min7", {0, 12, 0, 12}),
})
:durations(rep(beat * 2.0, 4))
:instrument("acoustic_piano")
:volume(0.32)
:pan(-0.1)
:velocity(0.36)
:effect("reverb", "room")
)
:add(
pulse.sequence()
:notes(line(d4, {3, 5, 7, 8, 7, 5, 3, 2}))
:durations(rep(beat, 8))
:instrument("flute")
:volume(0.2)
:pan(0.22)
:velocity(0.32)
:effect("filter", soft_filter)
:effect("reverb", "chamber")
)
local final_chorus = pulse.phrase()
:add(
pulse.sequence()
:chords({
voicing("C3", "maj7", {0, 12, 0, 12}),
voicing("D3", "dominant7", {0, 12, 0, 12}),
voicing("G3", "maj7", {0, 0, 12, 12}),
voicing("E3", "min7", {0, 12, 0, 12}),
})
:durations(rep(beat * 2.0, 4))
:instrument("strings")
:volume(0.36)
:velocity(0.46)
:effect("filter", string_filter)
:effect("reverb", "hall")
)
:add(
pulse.sequence()
:notes(line(g4, {8, 10, 12, 13, 12, 10, 8, 6, 8, 9, 10, 12, 15, 13, 12, 10}))
:durations(rep(beat / 2.0, 16))
:instrument("flute")
:volume(0.34)
:pan(0.24)
:velocity(0.5)
:effect("filter", soft_filter)
:effect("reverb", "chamber")
)
:add(
pulse.sequence()
:notes(line(c4, {5, 7, 8, 10, 8, 7, 5, 3, 5, 7, 8, 10, 12, 10, 8, 7}))
:durations(rep(beat / 2.0, 16))
:instrument("violin")
:volume(0.26)
:pan(-0.2)
:velocity(0.4)
:at(beat)
:effect("filter", string_filter)
:effect("reverb", "chamber")
)
:add(
pulse.sequence()
:notes(line(g_bass, {4, 1, 5, 6, 4, 1, 5, 1}))
:durations(rep(beat, 8))
:instrument("fingerstyle_bass")
:volume(0.52)
:velocity(0.6)
)
:add_drum_grid(soft_kick(0.28))
:repeat_times(2)
local coda = pulse.phrase()
:add(
pulse.sequence()
:chords({
voicing("G3", "maj7", {0, 12, 0, 12}),
voicing("D3", "dominant7", {0, 12, 0, 12}),
voicing("E3", "min7", {0, 12, 0, 12}),
voicing("G3", "maj7", {0, 0, 12, 12}),
})
:durations(rep(beat * 2.0, 4))
:instrument("acoustic_piano")
:volume(0.3)
:pan(-0.08)
:velocity(0.32)
:effect("reverb", "room")
)
:add(
pulse.sequence()
:notes(line(g4, {8, 9, 10, 12, 10, 8, 6, 5}))
:durations(rep(beat, 8))
:instrument("flute")
:volume(0.18)
:pan(0.2)
:velocity(0.28)
:at(beat)
:effect("filter", soft_filter)
:effect("reverb", "chamber")
)
local song = pulse.song()
:tempo(bpm)
:add_phrase(intro)
:add_phrase(verse)
:add_phrase(lift)
:add_phrase(chorus)
:add_phrase(bridge)
:add_phrase(final_chorus)
:add_phrase(coda)
:master_effect("reverb", "room")
:master_effect("eq", "warm")
:master_effect("limiter", "transparent")
assert(title == "kaze-ensemble")
song:export_wav("output/kaze-ensemble.wav", export_options)
song:export_flac("output/kaze-ensemble.flac", export_options)
song:export_midi("output/kaze-ensemble.mid", export_options)