local pulse = require("pulse")
local title = "fresh-pop"
local bpm = 112.0
local beat = 60.0 / bpm
local export_options = {
sample_rate = 44100,
normalize = "rms",
target_db = -15.5,
true_peak_db = -1.0,
midi_velocity_gain = 2.0,
midi_min_velocity = 0.62,
}
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 pop_beat(kick, hats, volume)
return pulse.drum_machine("808")
:steps(16)
:step_duration(beat / 4.0)
:kick(kick)
:snare("----x-------x---")
:hihat(hats)
:clap("----x-------x---")
:grid()
:repeat_times(3)
:volume(volume)
:effect("compressor", "drum_bus")
end
local e_major = pulse.scale("E4", "ionian")
local c_sharp_minor = pulse.scale("C#3", "minor")
local b_mixolydian = pulse.scale("B3", "mixolydian")
local verse = pulse.phrase()
:add(
pulse.sequence()
:chords({pulse.chord("E3", "maj7"), pulse.chord("B2", "dominant7"), pulse.chord("C#3", "min7"), pulse.chord("A2", "maj7")})
:durations(rep(beat * 4.0, 4))
:instrument("electric_piano")
:volume(0.58)
:pan(-0.18)
:velocity(0.52)
:effect("chorus", "classic")
)
:add(
pulse.sequence()
:notes(line(e_major, {3, 5, 6, 8, 9, 8, 6, 5, 3, 5, 6, 8, 10, 9, 8, 6}))
:durations(rep(beat, 16))
:instrument("ukulele")
:volume(0.34)
:pan(0.24)
:velocity(0.46)
:at(beat / 2.0)
:effect("reverb", "plate")
)
:add(
pulse.sequence()
:notes(line(c_sharp_minor, {1, 1, 5, 5, 6, 6, 4, 4, 1, 1, 5, 5, 6, 6, 4, 4}))
:durations(rep(beat, 16))
:instrument("fingerstyle_bass")
:volume(0.7)
:velocity(0.72)
)
:add_drum_grid(pop_beat("x---x-----x-x---", "x-x-x-x-x-x-x-x-", 0.58))
:repeat_times(2)
local chorus = pulse.phrase()
:add(
pulse.sequence()
:chords({pulse.chord("A2", "maj7"), pulse.chord("B2", "dominant7"), pulse.chord("E3", "maj7"), pulse.chord("C#3", "min7")})
:durations(rep(beat * 4.0, 4))
:instrument("warm_pad")
:volume(0.5)
:pan(0.12)
:velocity(0.5)
:effect("reverb", "ambient")
)
:add(
pulse.sequence()
:notes(line(e_major, {8, 9, 10, 12, 10, 9, 8, 6, 8, 9, 10, 12, 13, 12, 10, 8}))
:durations(rep(beat, 16))
:instrument("supersaw")
:volume(0.42)
:pan(-0.18)
:velocity(0.56)
:effect("filter", { type = "low_pass", cutoff = 4200.0, resonance = 0.2 })
:effect("delay", "dotted_eighth")
)
:add(
pulse.sequence()
:notes(line(c_sharp_minor, {6, 6, 7, 7, 1, 1, 5, 5, 6, 6, 7, 7, 1, 1, 5, 5}))
:durations(rep(beat, 16))
:instrument("picked_bass")
:volume(0.76)
:velocity(0.78)
)
:add_drum_grid(pop_beat("x---x-x-x---x-x-", "x-xxxxxxx-xxxxxx", 0.7))
:repeat_times(2)
local bridge = pulse.phrase()
:add(
pulse.sequence()
:chords({pulse.chord("B2", "dominant7"), pulse.chord("A2", "maj7"), pulse.chord("F#2", "min7"), pulse.chord("B2", "dominant7")})
:durations(rep(beat * 4.0, 4))
:instrument("electric_piano")
:volume(0.48)
:pan(-0.12)
:velocity(0.46)
:effect("phaser", "subtle")
)
:add(
pulse.sequence()
:notes(line(b_mixolydian, {1, 3, 5, 7, 8, 7, 5, 3, 1, 3, 5, 7, 8, 10, 8, 7}))
:durations(rep(beat, 16))
:instrument("music_box")
:volume(0.3)
:pan(0.26)
:velocity(0.44)
:effect("delay", "eighth_note")
)
:repeat_times(1)
local song = pulse.song()
:tempo(bpm)
:add_phrase(verse)
:add_phrase(chorus)
:add_phrase(bridge)
:add_phrase(chorus)
:master_effect("reverb", "room")
:master_effect("eq", "bright")
:master_effect("limiter", "transparent")
assert(title == "fresh-pop")
song:export_wav("output/fresh-pop.wav", export_options)
song:export_flac("output/fresh-pop.flac", export_options)
song:export_midi("output/fresh-pop.mid", export_options)