Strudelify

Too Late for Goodbyes

Julian Lennon

KeyA majorTempo120 bpm
0:00/0:00
// Too Late for Goodbyes — Julian Lennon
// 120 bpm, 4/4, key A major. Source: midi.
// Generated by strudelify. One cycle = one bar.
// note: pitch bends are ignored
// note: Full arrangement: all 104 bars on a 16-step grid, each part at one level; ghost notes are separate "_soft" parts. Source detail keeps the original performance.
setcpm(120/4)

// Notation: c3@3 lasts 3 steps · ~ is a rest · [c3,e3] is a chord · "a, b" plays two voices at once · [...]/2 spreads a riff over 2 bars.
// A part's distinct bars are riffs (A, B, C...) played in order: edit a riff to change every repeat.

// chords · lead 8 bass lead
const lead_8_bass_lead = note(`<
  A B A B A B A B C D E A F D E A@2 B A B A B A B C D E A F D E A@2 B A B A B A B C D E A F D E A@2 B A B A B A B A B A
  B A B A B C D E A F D E A@2 B A B A B A B C D E A F D E A@2 B A B A B A B A B A B A B A B
>`.pickRestart({
  A: "~@2 [a3,c#4,e4] ~@3 [a3,c#4,e4] ~@3 [a3,c#4,e4] ~@3 [a3,c#4,e4] ~", // A
  B: "~@2 [g3,b3,e4] ~@3 [g3,b3,e4] ~@3 [g3,b3,e4] ~@3 [g3,b3,e4] ~", // Em
  C: "[c4,e4,g4] ~ [c4,e4,g4] ~@3 [c4,e4,g4] ~ [c4,e4,g4] ~ [c4,e4,g4] ~@3 [c4,e4,g4] ~", // C
  D: "[b3,d4,a4] ~ [b3,d4,a4] ~@3 [b3,d4,a4] ~ [b3,d4,a4] ~ [b3,d4,a4] ~@3 [b3,d4,a4] ~", // Bm7
  E: "[a3,c#4,e4] ~ [a3,c#4,e4] ~@3 [a3,c#4,e4] ~@3 [a3,c#4,e4] ~@3 [a3,c#4,e4] ~", // A
  F: "[c4,e4,g4] ~ [c4,e4,g4] ~@3 [c4,e4,g4] ~@3 [c4,e4,g4] ~@3 [c4,e4,g4] ~", // C
})).s("gm_lead_8_bass_lead").gain(0.31)

// chords · string ensemble 2 · "Strings"
const string_ensemble_2 = note(`<
  A B C B C B C B D E F@2 D E G@2 H B C B C B C B D E F@2 D E F@2 H B C B C B C B D E F@2 D E F@2 H B C B C B C B H B C
  B C B C B I E F@2 D E F@2 H B C B C B C B I E F@2 D E F@2 H B C B H B C B H B C B ~@4
>`.pickRestart({
  A: "[a3,c#4]@7 ~", B: "[g3,b3]", C: "[a3,c#4]", D: "c4", E: "b3", F: "[a3,c#4]/2", G: "[c#4, a3 ~]/2",
  H: "c#4, a3@7 ~", I: "[g3,b3] ~@15, c4",
})).s("gm_string_ensemble_2").gain(0.31)

// chords · string ensemble 2 · "Strings" · soft notes · G A G
const string_ensemble_2_soft = note("<~@100 [c#4, a3@7 ~] [[g3,b3]] [[a3,c#4]] [[g3,b3]]>")
  .s("gm_string_ensemble_2").gain(0.15)

// bass · electric bass finger · "Bass Guitar"
const bass = note(`<
  A B A C A B A D E F G@2 H F I@2 A B A C A B A D E F G@2 H F J@2 A B A C A B A D E F G@2 H F J@2 ~ K ~ K ~ K L M A B A
  C A B A D E F G@2 H F J@2 A B A C A B A D E F G@2 H F N@2 O P Q R O P Q R A B A C ~@4
>`.pickRestart({
  A: "~@2 a1@2 c2@2 d2@2 e2@2 g2@2 e2 d2 c2@2", B: "d2@2 c2@2 a1 ~ a1@10", C: "d2@2 c2@2 a1 ~ a2@10",
  D: "d2@2 c2@2 a1 ~ a2@6 a1@2 b1@2", E: "~@5 d2 e2@2, c2@3 ~", F: "b1@5 c#2 d2@2", G: "[a1@27 ~ a1@2 b1@2]/2",
  H: "c2@4 ~ d2 e2@2", I: "[a1@31 a1]/2", J: "[~@12 g1!3 a1, a1@15 ~]/2", K: "~@8 g1@2 g1@2 g1 a1@2 ~", L: "~@7 a2",
  M: "a1 ~", N: "[g1@12 g1!2 ~ a1, ~@7 g1]/2", O: "a2@2 a1@2 ~ a1@2 ~", P: "a1@2 ~ a1@2 g1 ~ a1",
  Q: "~@2 a2@2 ~ a1@2 ~", R: "a1@2 ~ a1@2 g1!2 a1",
})).s("gm_electric_bass_finger").gain(0.46)

// bass · electric bass finger · "Bass Guitar" · soft notes
const bass_soft = note(`<
  ~@54
  [~@13 a1 ~@2]
  ~@45
  [~@2 a1@2 c2@2 d2@2 e2@2 g2@2 e2 d2 c2@2]
  [d2@2 c2@2 a1 ~ a1@10]
  [~@2 a1@2 c2@2 d2@2 e2@2 g2@2 e2 d2 c2@2]
  [d2@2 c2@2 a1 ~ a2@10]
>`).s("gm_electric_bass_finger").gain(0.26)

// bass · slap bass 1 · "Bass Guitar Slaps"
const bass_2 = note(`<
  ~@10 A B ~@2 A ~@11 A B ~@2 A ~@11 A B ~@2 A ~@5 C ~@2 D C ~@9 A B ~@2 A ~@11 A B ~@8 C E F G H ~@7
>`.pickRestart({
  A: "~@7 a2", B: "~@10 a2@3 ~@3", C: "a2 ~@3", D: "~@8 e3 ~@3 d3 ~@3", E: "~@4 g3 ~@2 g3 ~ f#3 ~@2 e3@4",
  F: "~@8 c3@2 d3@2 d#3 e3@2 ~", G: "c3 a2@3 ~@4", H: "c#3 ~@3",
})).s("gm_slap_bass_1").gain(0.51)

// chords · electric guitar clean · "Lead Guitar"
const electric_guitar_clean = note(`<
  ~ A ~ B ~ A ~ A ~@2 C@2 ~@2 D E ~ A ~ B ~ A ~ A ~@2 F@2 ~@2 F G H A ~ B ~ A ~ A ~@2 F I ~@2 F J H A ~ B ~ A ~ A ~ A ~
  B ~ A ~ A ~@2 F I ~@2 F J H A ~ B ~ A ~ A ~@2 F@2 ~@2 K L M A ~ B ~ A ~ B ~ A ~ B ~@4
>`.pickRestart({
  A: "~@3 b4", B: "~@12 b4@3 ~", C: "~@2 a4@2 a4@2 g4 e4", D: "a4 ~ a4@2 g4@2 e4 ~ c#4@3 ~ c#4@3 ~", E: "a3",
  F: "~@2 [a4,c#5]@2 [a4,c#5]@2 g4 [e4,g4], ~@3 b4", G: "~@2 [a4,c#5]@2 [g4,b4] [e4,g4] [c#4,e4]!2", H: "[a3,c#4] ~@3",
  I: "~@2 [a4,c#5]@4 g4 [e4,g4], ~@3 b4", J: "~ [a4,c#5] [g4,b4] [e4,g4] [c#4,e4]@2 [c#4,e4]@2",
  K: "~@3 [a4,c#5]@2 [g4,b4]@3 [e4,g4]@3 [d4,f#4]@2 [c#4,e4]@3", // A G Em D C#m
  L: "[a3,c#4]@3 [g3,b3]@2 [f#3,a3]@3 [e3,g3]@3 [d3,f#3]@2 [c#3,e3]@3", M: "[a2,c#3] ~@3",
})).s("gm_electric_guitar_clean").gain(0.31)

// chords · electric guitar clean · "Lead Guitar" · soft notes
const electric_guitar_clean_2 = note("<~@101 [~@3 b4] ~ [~@12 b4@3 ~]>").s("gm_electric_guitar_clean").gain(0.2)

// other · synth drum · "Drum Fills"
const synth_drum = note(`<
  ~@5 A ~@5 B ~@3 C ~@7 D ~@2 E F ~@2 G H ~@6 E I ~@2 J K ~@2 L H ~@7 M ~@3 N ~ O ~@4 P Q ~@3 R ~@6 E I ~@2 S F ~@2 T U
  ~@3 V ~@3 W ~ X ~ Y ~@4
>`.pickRestart({
  A: "~@8 g#4 ~ g#4 ~ g#3 ~ g#3@2", B: "~@2 g#4!3 ~ g#4 ~ g#3 ~ g#3 ~ g#4 ~ g#3 ~",
  C: "~@6 g#4 ~ g#4@2 g#3 g#4 g#3 ~@3", D: "~@3 g4 g4@2 ~@10", E: "~@7 g4", F: "g4 g3!2 g2!2 ~@3", G: "~@14 g4!2",
  H: "g3 ~@3", I: "~ g3 ~ g2 ~@4", J: "~ g4 ~ g3 g3@2 ~@2", K: "~ g4 ~ g3 ~@4", L: "~@14 g3!2", M: "~@3 g3!2 ~@3",
  N: "~@6 g4@2 g3@2 g3!2 g3@2 g2@2", O: "~@2 g3 ~", P: "~ g4 ~ g3 ~@2 g2 g4", Q: "~@3 g3 ~@4", R: "~ g3 ~@6",
  S: "~@13 g4!3", T: "~@3 g2", U: "~@3 g3", V: "~@5 g3 ~ g3", W: "~@2 g4!2 g4@4 ~@8",
  X: "~@2 g4@2 ~ g3 g3@2 g3@2 g2@2 g2@2 g2@2", Y: "~ g2 ~@3 g4!3",
})).s("gm_synth_drum").gain(0.41)

// other · synth drum · "Drum Fills" · soft notes
const synth_drum_soft = note("<~@101 [~@2 g3!2 g3@4 g2@2 g2@2 g4@2 g3@2] ~ [~@2 g4@2 ~@2 g3@2 ~@2 g3!2 g2@2 g2@2]>")
  .s("gm_synth_drum").gain(0.2)

// chords · harmonica
const harmonica = note("<~@56 A B C@2 D E F@2 ~@40>".pickRestart({
  A: "~@4 [e5,c#6]@2 [f#5,d6] ~ [e5,c#6]@2 [d5,b5]@2 [c#5,a5] ~ [d5,b5]@2, ~@14 [c#5,a5] ~", // C#m D C#m G F#m G F#m
  B: "c#5@2 [c#5,a5]@13 ~, a5 ~@15", C: "[~@4 [c#5,a5] ~ [c#5,a5] ~ [e5,c#6]@2 [f#5,d6]@2 [a5,e6] ~ [c#6,a6]@15 ~@3]/2",
  D: "~@4 [e5,c#6]@2 [f#5,d6] ~ [e5,c#6]@2 b5@2 [c#5,a5] ~ [d5,b5]@2, ~@10 d5 ~@3 [c#5,a5] ~", // C#m D C#m F#m G F#m
  E: "[c#5,a5] ~ [c#5,a5]@13 ~", // F#m
  F: "[~@2 [c#5,a5] ~ c#5 a5 c#5@2 [e5,c#6]@2 [f#5,d6]@2 [a5,e6] ~ [e6,b6]@4 [e6,a6] ~ e6@11 ~, ~@6 a5 ~@13 a6@9 ~@3]/2", // F#m C#m D A5 E5 A5
})).s("gm_harmonica").gain(0.41)

// drums · kick
const kick = s("bd").struct("x ~@2 x!2 ~@3").gain(0.41)

// drums · snare
const snare = s("sd").struct("~ x ~ x").gain(0.31)

// drums · clap
const clap = s("cp").struct("~ x ~ x").gain(0.46)

// drums · pedal hat
const pedal_hat = s("hh").struct(`<
  A@3 B A@3 B A@3 B A@3 B A@3 B A@3 B A@3 B A@3 B A@3 B A@3 B A@3 B A@3 B A@3 B A@3 B A@3 B A@3 B A@3 B A@3 B A@3 B A@3
  B A@3 B A@3 B A@3 B A@3 B A@3 B A@3 B
>`.pickRestart({
  A: "x!8", B: "x!5 ~ x ~",
})).gain(0.46)

// drums · open hat
const open_hat = s("oh").struct(`<
  ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3
  A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A ~@3 A
>`.pickRestart({
  A: "~@5 x ~ x",
})).gain(0.46)

// drums · tambourine
const tambourine = s("tb").struct("<~@16 A@8 ~@8 A@8 ~@8 A@16 ~@8 A@8 ~@8 A@12 ~@4>".pickRestart({
  A: "~ x",
})).gain(0.46)

// drums · tambourine · soft notes
const tambourine_soft = s("tb").struct("<~@100 [~ x]!4>").gain(0.2)

// drums · claves
const claves = s("clave:2").struct("<A@8 ~@8 A@8 ~@8 A@8 ~@8 A@16 ~@8 A@8 ~@8 A@12 ~@4>".pickRestart({
  A: "~ x ~@3 x ~@2",
})).gain(1.51)

// drums · claves · soft notes
const claves_soft = s("clave:2").struct("<~@100 [~ x ~@3 x ~@2]!4>").gain(0.75)

// drums · woodblocks
const woodblocks = s("woodblock:5").struct("<A@8 ~@8 A@8 ~@8 A@8 ~@8 A@16 ~@8 A@8 ~@8 A@12 ~@4>".pickRestart({
  A: "~ x ~ x",
})).gain(0.45)

// drums · woodblocks · soft notes
const woodblocks_soft = s("woodblock:5").struct("<~@100 [~ x ~ x]!4>").gain(0.15)

// drums · woodblocks
const woodblocks_2 = s("woodblock:4").struct("<A@8 ~@8 A@8 ~@8 A@8 ~@8 A@16 ~@8 A@8 ~@8 A@12 ~@4>".pickRestart({
  A: "~@3 x ~@3 x",
})).gain(0.45)

// drums · woodblocks · soft notes
const woodblocks_soft_2 = s("woodblock:4").struct("<~@100 [~@3 x ~@3 x]!4>").gain(0.15)

stack(
  lead_8_bass_lead, string_ensemble_2, string_ensemble_2_soft, bass, bass_soft, bass_2, electric_guitar_clean,
  electric_guitar_clean_2, synth_drum, synth_drum_soft, harmonica, kick, snare, clap, pedal_hat, open_hat, tambourine,
  tambourine_soft, claves, claves_soft, woodblocks, woodblocks_soft, woodblocks_2, woodblocks_soft_2
)