Strudelify
Two Hearts cover art

1989

Two Hearts

Phil Collins

KeyA majorTempo157 bpm
0:00/0:00
// Two Hearts — Phil Collins
// 157 bpm, 4/4, key G major. Source: mcgill + midi.
// Generated by strudelify. One cycle = one bar.
// note: Full arrangement: all 136 bars on a 24-step grid, each part at one level. Source detail keeps the original performance.
setcpm(157/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, A@4 for four bars: edit a riff to change every repeat.

// bass · electric bass finger · "BASS"
const bass = note(`<
  ~@2 A B C D E B C F G@3 H G@3 I J G@2 K G@3 L M@4 N@4 E B C D E B C O G@3 H G@3 I J G@2 K G@3 L M@4 N@4 P B C D E B C
  O E B C Q A B C R S T U V W X Y Z AA AB U V W X Y AC AD AE E B C D E B C O A AF C AG E AH C Q AI AJ C AK E B C Q AI AJ
  C AK E B C AL S AM AN AO
>`.pickRestart({
  A: "d2 ~ d2!2 ~ d2!2 ~ d2!2 ~ d1", B: "d1 ~ d1!2 ~ d1 d1@3 f#1@3", C: "e1 ~ e1!2 ~ e1!2 ~ e1!2 ~ a1",
  D: "a1 ~ a1!2 ~ a1 b1@3 a1@2 b1", E: "d1 ~ d1!2 ~ d1!2 ~ d1!2 ~ d1", F: "a1 ~ a1!2 ~ a1 b1 ~ a1 f#1@2 a1",
  G: "~@2 a1 ~@2 a1 a1@2 a1 a1@2 a1", H: "~@2 a1 ~@2 a1 f#1@3 e1@2 a1", I: "~@2 a1 ~@2 a1 f#1@3 e1@3",
  J: "a1@2 a1 ~@2 a1 a1@2 a1 a1@2 a1", K: "~@2 a1 ~@2 a1 f#1@3 e1@2 f#1", L: "a1 g1 a1 a#1",
  M: "[b1 ~ b1!2 ~ b1!2 ~ b1!2 ~ c#2@2 ~ c#2!2 ~ c#2!2 ~ c#2!2 ~ d2@3 d2!2 ~ d2!2 ~ d2!2 ~ e2@3 e1!2 ~ e1 a1@3 a#1@3]/4",
  N: "[b1 ~ b1!2 ~ b1!2 ~ b1!2 ~ c#2@3 c#2!2 ~ c#2!2 ~ c#2!2 ~ d2@3 d2!2 ~ d2!2 ~ d2!2 ~ e2@3 e1!2 ~ e1 e2 ~ e1 e2@2 ~]/4",
  O: "a1 ~ a1!2 ~ a1 b1@2 a1 f#1@2 a1", P: "~@2 d1!2 ~ d1!2 ~ d1!2 ~ d1", Q: "a1 ~ a1!2 ~ a1 b1@3 c#2@3",
  R: "a1 ~ a1!2 ~ a1!2 ~ a1 a1@3", S: "a1 f1 a1 a#1@3", T: "b1@3 c2 d2@2", U: "c#2 ~ c#2!2 ~ c#2 a#1@3 g#1@3",
  V: "a#1 ~ a#1!2 ~ a#1 a#1@3 b1@3", W: "c2 ~ c2!2 ~ c2!2 ~ c2!2 ~ f2", X: "f2@3 d#2@3 c2@3 f1@2 a#1",
  Y: "a#1 ~ a#1!2 ~ a#1!2 ~ a#1!2 ~ a#1", Z: "a#1 ~ a#1!2 ~ a#1!2 ~ a#1 b1 ~ b1", AA: "c2 ~ c2!2 ~ c2!2 ~ c2!2 ~ c2",
  AB: "c2 ~ c2!2 ~ c2!2 ~ c2@4", AC: "a#1 ~ a#1!2 ~ a#1!2 ~ a#1!2 c#2 a#1", AD: "b1 ~ b1!2 ~ b1!2 ~ b1 ~@3",
  AE: "e2!3 b1", AF: "d1 ~ d1!2 ~ d1!2 ~ d1 f#1@3", AG: "a1 ~ a1!2 ~ a1 b1@3 a1@3", AH: "d1 ~ d1 c#1@3 d1@3 d#1@3",
  AI: "d2 ~ d2!2 ~ d2!2 ~ d2!2 ~ a1", AJ: "d2 c#2 b1 a1", AK: "a1 ~ a1!2 ~ a1 b1 ~ a1 f#1 ~ e1",
  AL: "a1 ~ a1!2 ~ a1 a1@2 a1 a1@3", AM: "b1 g1 b1 c2@3", AN: "c#2 a1 c#2 d2 e2@2", AO: "a1 ~@11",
})).s("gm_electric_bass_finger").gain(0.19)

// chords · epiano2 · "PIANO"
const epiano2 = note(`<
  ~@2 A@2 B@2 C@2 D@2 E@16 F@8 A@2 B@2 C@2 D@2 E@16 F@8 A@2 B@2 C@2 G@2 A@2 B@2 C@2 H@2 I J K L M N O@2 P Q K O M R O@2
  S T A@2 B@2 C@2 G@2 A@2 B@2 C@2 D@2 A@2 B@2 C@2 D@2 A@2 B@2 C@2 H@2 I U V W
>`.pickRestart({
  A: "[[d4,f#4,a4,c#5]@4 ~ [d4,f#4,a4,b4]@11 ~@2 [f#4,a4]@3 g#4@2 ~, ~@18 d4@5 ~]/2", // Dmaj7 Bm7 F#m
  B: "[[e4,g#4,b4]@6 [e4,g#4,b4]@4 ~ [c#4,e4,a4]@7 a4@2 b4 [a4,c#5]@3]/2", // E A
  C: "[[d4,f#4,a4,c#5]@8 ~@2 [d4,f#4,a4,b4]@22 ~@4 [f#4,a4]@6 g#4@5 ~, ~@36 d4@11 ~]/2", // Dmaj7 Bm7 F#m
  D: "[[e4,g#4,b4]@6 [g#4,b4,e5]@4 ~ [e4,a4,c#5]@7 a4@2 b4 [a4,c#5]@2 ~]/2", // E A
  E: "[[e4,a4,c#5]@9 [e4,a4,c#5]@2 [f#4,b4,d#5]@9 ~ [b4,d#5,f#5]@2 [a4,c#5,e5]@10 [a4,c#5,e5]@2 [f#4,b4,d#5]@13]/4", // A B A B
  F: "[[b3,d4,f#4,a4]@21 ~ [c#4,e4,g#4,b4]@23 ~ [d4,f#4,a4,c#5]@23 ~ [f#4,a4,d5]@25 ~]/4", // Bm7 C#m7 Dmaj7 D
  G: "[[e4,g#4,b4]@12 [g#4,b4,e5]@8 ~@2 [e4,a4,c#5]@14 a4@4 b4@4 c#5@3 ~]/2", // E A
  H: "[[e4,g#4,b4]@6 [g#4,b4,e5]@4 ~ [e4,a4,c#5]@13]/2", I: "[c4,f4,a4] [d4,f4,a#4]",
  J: "[d4,g4,b4]@6 [e4,g4,c5] ~ [d4,f4,a#4]@4", K: "[c4,f4,g#4]", L: "[c#4,f4,g#4]@2 c#4 f4", M: "[a#3,d#4,g4]",
  N: "[d#4,g4,a#4] d#4", O: "[c#4,f4,g#4]", P: "[d#4,g4,a#4]@11 ~",
  Q: "[d#4,g4,a#4]@10 ~@2 [d#4,a#4] ~@3 [d#4,g4,a#4]@8, ~@6 g4 ~@5", R: "[d#4,g4,a#4] [a#3,d#4,g4]", S: "[d4,f#4,a4]",
  T: "[f#4,a4,c#5]!2", U: "[d4,g4,b4] [e4,g4,c5]", V: "[e4,a4,c#5]@6 [a4,d5] ~ [g#4,b4,e5]@3 ~, ~@12 f#4 ~@11",
  W: "[c#5,e5,a5] ~@23", // A
})).s("gm_epiano2").gain(0.17)

// chords · electric guitar clean · "GUITAR"
const electric_guitar_clean = note(`<
  ~@2 A@2 B C A@2 B C@2 D C D C D C D C D C D C D C D E F G A E F G A@3 B C A@2 B C@2 D C D C D C D C D C D C D C D E F
  G A E F G A@3 B C A@2 B C A@2 B C A@2 B C H I ~@16 A@2 B C A@2 B C A@2 B C A@2 B J A@2 B C A@2 B C A@2 B C A@2 B J H K
  L M
>`.pickRestart({
  A: "~@3 [d4,f#4,a4] ~@5 [d4,f#4,a4] ~@2", B: "~@3 [b3,e4,g#4] ~@5 [b3,e4,g#4] ~@2",
  C: "~@3 [c#4,e4,a4] ~@5 [c#4,e4,a4] ~@2", D: "~@3 [d#4,f#4,b4] ~@5 [d#4,f#4,b4] ~@2",
  E: "~@3 [d4,f#4,b4] ~@5 [d4,f#4,b4] ~@2", F: "~@3 [e4,g#4,b4] ~@5 [e4,g#4,b4] ~@2",
  G: "~@3 [f#4,a4,c#5] ~@5 [f#4,a4,c#5] ~@2", H: "[c4,f4,a4] [d4,f4,a#4]", I: "[b3,d4,g4]@6 [c4,e4,g4] ~ [d4,f4,a#4]@4",
  J: "~@6 [c#4,e4,a4]@2 ~@10 [c#4,e4,a4]@3 ~@3", K: "[b3,d4,g4] [c4,e4,g4]",
  L: "[c#4,e4,a4]@6 [d4,f#4,a4] ~ [e4,g#4,b4]@4", M: "[e4,a4,c#5] ~@11",
})).s("gm_electric_guitar_clean").gain(0.16).pan(0.4)

// other · string ensemble 1 · "STRINGS"
const string_ensemble_1 = note(`<
  ~ A B@2 C@2 D@2 E@2 F@8 ~@16 G@2 H@2 G@2 I@2 J@8 ~@16 G@2 H@2 G@2 K@2 G@2 H@2 G@2 L@2 M N O P Q@2 R S@3 T P U V R W X
  Y G@2 H@2 G@2 K@2 Z@2 AA@2 Z@2 AB@2 Z@2 AA@2 Z@2 AB@2 Z@2 AA@2 Z@2 AC@2 M AD AE AF
>`.pickRestart({
  A: "~@8 e4 f#4 a4 b4", B: "[c#5@5 b4@13 a4@3 g#4@3]/2", C: "[b4@12 b4@10 a4@12 ~@2 a4@4 b4@2 c#5@4 ~ b4]/2",
  D: "[c#5@5 b4@12 ~ a4@3 g#4@3]/2", E: "[b4@11 d5 e5@10 c#5@14 a4 g#4 g4 f#4 f4 e4 d#4 d4 c#4 c4 b3 a#3]/2",
  F: "[e6@16 c#6@2 a5@4 d#6@8 b5@4 c#6@2 d#6@4 e6@2 f#6@4 e6@11 ~ a5 b5 c#6@4 d6@2 e6@4 d#6@22 a5 a#5 b5 c6 c#6@18 e6@4 d#6@8 b5@4 c#6@2 d#6@4 e6@2 f#6@4 e6@8 a5@4 b5@2 c#6@4 d6@2 e6@2 ~@2 [d#6,a6]@20 ~@6, a3@31 ~]/8", // D#dim
  G: "[c#6@5 b5@12 ~ a5@3 g#5@3]/2", H: "[b5@11 c#6@7 a5@2 b5 c#6@3]/2",
  I: "[b5@12 e6@10 c#6@13 ~ a5 g#5 g5 f#5 f5 e5 d#5 d5 c#5 c5 b4 ~]/2",
  J: "[~@43 e5 f#5 g#5 a5 b5 c#6@9 e6@2 d#6@4 b5@2 c#6 d#6@2 e6 f#6@2 e6@3 ~ a5@2 b5 c#6@2 d6 e6@2 a6@10 ~@3, a4@31 ~]/8",
  K: "[b5@12 e6@10 c#6@13 ~ a5@4 b5@4 c#6@4]/2", L: "[b5@6 e6@4 ~ c#6@13]/2", M: "f5 c5 a4!2 c5 f5!2 d5 a#4 d5 f5 a#5",
  N: "b5@2 a5@2 g5@2 g5@2 a5@2 b5@2 c6@2 g5@2 c6@2 ~@2 a#5 c6 d6 e6",
  O: "[f5,f6]@9 [d#5,d#6] [c#5,c#6]@2 [c5,c6]@4 [c#5,c#6]@4 [d#5,d#6]@4", P: "[f5,f6]",
  Q: "[[g5,g6]@11 ~ [a#5,a#6]@12, ~@11 [g#5,g#6]@2 ~@11]/2", R: "[f5,f6]@3 [c6,c7]",
  S: "[[a#5,a#6]@6 [g#5,g#6]@2 ~ [g5,g6]@2 ~ [f5,f6]@24 [d#5,d#6]@22 ~@2 [d#5,d#6]@4 [c5,c6]@2 [a#4,a#5]@3 [c5,c6] [c#5,c#6] [d#5,d#6]]/3", // A# G# G F D# C A# C …
  T: "[f5,f6]@3 [c5,c6] [c#5,c#6] [d#5,d#6]", U: "[g5,g6]@11 [g#5,g#6]", V: "[a#5,a#6]",
  W: "[a#5,a#6]@2 [g#5,g#6] [g5,g6] [f5,f6]@4", X: "[f#5,f#6]@3 [d6,d7]", Y: "[c#6,c#7]@2 [b5,b6] [a5,a6] [f#5,f#6]@4",
  Z: "[[c#5,c#6]@5 [b4,b5]@12 ~ [a4,a5]@3 [g#4,g#5]@3]/2", // C# B A G#
  AA: "[[b4,b5]@6 [b4,b5]@5 [c#5,c#6]@7 [a4,a5]@2 [b4,b5] [c#5,c#6]@3]/2", // B C# A B C#
  AB: "[[b4,b5]@6 [e5,e6]@5 [c#5,c#6]@6 ~ [a4,a5]@2 [b4,b5] [c#5,c#6]@2 ~]/2", // B E C# A B C#
  AC: "[[b4,b5]@12 [e5,e6]@10 [c#5,c#6]@25 ~]/2", AD: "b5 a5 g5!2 a5 b5 c6 g5 e5!2 g5 c6",
  AE: "c#6@2 b5@2 a5@2 a5@2 b5@2 c#6@2 d6@2 ~@2 e6@7 ~", AF: "[c#6,a6] ~@11",
})).s("gm_string_ensemble_1").gain(0.22)

// chords · brass section · "BRASS"
const brass_section = note(`<
  ~@34 A@2 ~@2 A@2 ~@26 A@2 ~@2 A@2 ~@2 A@2 ~@2 A@2 ~@2 B C ~@16 A@2 ~@2 A@2 ~@2 A@2 ~@2 A@2 ~@2 A@2 ~@2 A@2 ~@2 A@2 ~@2
  A@2 ~@2 B D E F
>`.pickRestart({
  A: "[~@9 [a4,d5,f#5]@2 [d5,f#5,a5]@7 ~@6]/2", B: "[c5,f5,a5] [d5,f5,a#5]",
  C: "[d5,g5,b5]@6 [e5,g5,c6] ~ [d5,f5,a#5]@4", D: "[d5,g5,b5] [e5,g5,c6]",
  E: "[e5,a5,c#6]@6 [f#5,a5,d6] ~ [g#5,b5,e6]@3 ~", F: "[c#6,e6,a6] ~@5",
})).s("gm_brass_section").gain(0.21).pan(0.4)

// drums · kick
const kick = s("bd").struct("<~@2 A@81 B A@7 B A@7 C A@35 D>".pickRestart({
  A: "x!2", B: "x ~ x", C: "x!4", D: "x",
})).gain(0.35)

// drums · snare
const snare = s("sd").struct(`<
  ~ A B@7 C B@7 D B@7 C B@7 C B@7 C B@7 D B@7 C B@7 C B@7 C B@7 C B E B@7 F B@7 G B@7 C B@7 C B@7 C B@7 C B@2 E H
>`.pickRestart({
  A: "~@8 x!4", B: "~ x ~ x", C: "~@3 x ~@5 x!3", D: "~ x ~@2", E: "~@2 x!5 ~@5", F: "~@3 x!4 ~@5",
  G: "~@3 x!4 ~ x ~@3", H: "x",
})).gain(0.45)

// drums · clap
const clap = s("cp").struct("<~@2 [~ x ~ x]!133 ~>").gain(0.45)

// drums · hihat
const hihat = s("hh").struct(`<
  A B C@7 D C@7 D C@7 D C@15 D C@7 D C@7 D C@15 D C@17 E C@15 D C@7 D C@19 F
>`.pickRestart({
  A: "x!2", B: "x!3 ~", C: "x ~ x!2 ~ x!2 ~ x!2 ~ x", D: "x ~ x!2 ~ x!2 ~@2 x ~ x", E: "x ~ x!2 ~ x!2 ~ x ~@3", F: "x",
})).gain(0.3)

// drums · low tom
const low_tom = s("lt").struct("<~@17 [~@11 x] ~@31 [~@11 x] ~@49 [~@11 x] ~@36>").gain(0.4)

// drums · mid tom
const mid_tom = s("mt").struct("<~@17 [~@5 x] ~@31 [~@5 x] ~@49 [~@5 x] ~@36>").gain(0.4)

// drums · crash
const crash = s("cr").struct(`<
  ~@2 A ~@7 A ~@7 A ~@7 A ~@7 A ~@7 A ~@7 A ~@7 A ~@7 A ~@7 A ~@7 B C A ~@6 D ~@8 A ~@7 A ~@7 A ~@7 A ~@7 B@2 C ~
>`.pickRestart({
  A: "x", B: "x!2", C: "x ~ x", D: "~@2 x",
})).gain(0.4)

// drums · high tom
const high_tom = s("ht").struct("<~@17 [~@3 x] ~@31 [~@3 x] ~@49 [~@3 x] ~@36>").gain(0.5)

// drums · tambourine
const tambourine = s("tb").struct("<~@2 [x ~ x!2 ~@2 x ~ x!2 ~@2]!133 x>").gain(0.45)

stack(
  bass, epiano2, electric_guitar_clean, string_ensemble_1, brass_section, kick, snare, clap, hihat, low_tom, mid_tom,
  crash, high_tom, tambourine
)

More by Phil Collins