Strudelify

Heartbeat

Nick Berry

KeyA majorTempo150 bpm
0:00/0:00
// Heartbeat — Nick Berry
// 150 bpm, 4/4, key A major. Source: midi.
// Generated by strudelify. One cycle = one bar.
// note: Tempo changes preserved in elapsed time; displayed bars use the dominant tempo.
// note: pitch bends are ignored
// note: sustain pedal (CC 64) lengthens the held notes
// note: Full arrangement: all 84 bars on a 16-step grid, each part at one level. Source detail keeps the original performance.
// note: Guitar parts that double another keep only their own notes (fills, solos): guitar program 27.
setcpm(150/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.

// other · piano
const piano = note("<~@24 A B C ~@37 A B C ~@17>".pickRestart({
  A: "[c#5,c#6]@3 ~@3 [b4,b5]@3 ~@3 [a4,a5]@3 ~", B: "[g#4,g#5]", C: "[f#4,f#5]@7 ~",
})).s("gm_piano").gain(0.4).pan(0.7)

// bass · acoustic bass
const bass = note(`<
  ~ A B A C D@2 E C A B A C D@2 E C A B A F B E D G B E G H D@2 E C A B A C D@2 E C A B A C D@2 E C A B A C D@2 E C A B
  A F B E D G B E G H D@2 E C A B A C A B A C I@3
>`.pickRestart({
  A: "a1@3 c#2@3 e2 ~", B: "e2@3 b1@3 e2@2", C: "e2@6 b1@6 e2@3 ~", D: "a1@3 c#2@3 e2@2", E: "d2@3 a1@3 d2@2",
  F: "d2@6 a1 ~ a1@4 d2@3 ~", G: "a1@6 c#2@6 e2@3 ~", H: "e2 ~ e2@2 d2 ~ d2@2 c#2 ~ c#2@2 b1 ~ b1@2", I: "[a1@7 ~]/3",
})).s("gm_acoustic_bass").gain(0.4).pan(0.3)

// chords · electric guitar clean
const electric_guitar_clean = note(`<
  ~ A B C B ~@4 A B A B ~@4 A B A ~@4 D ~@8 A B A B ~@4 A B A B ~@4 A B A B ~@4 A B A ~@4 D ~@8 A B A B A B A E@4
>`.pickRestart({
  A: "~@4 [d4,f#4] ~@3", B: "~@4 c#4 ~@3", C: "[c#4,e4] ~@3 [d4,f#4] ~@3", D: "~@6 [g#3,b3]@3 ~@3 f#3@2 ~@2",
  E: "[~@8 c#4@2 ~@2 f#4 ~@3 b4@42 ~@6, ~@15 f#4@43 ~@6]/4",
})).s("gm_electric_guitar_clean").gain(0.3).pan(0.3)

// chords · electric guitar clean
const electric_guitar_clean_2 = note("<~@36 A B@2 C D ~@36 E F G H I@3>".pickRestart({
  A: "~@3 e4, ~@6 a4 ~", B: "[[a4,c#5]@6 [a4,c#5]@12 ~@2 [a4,c#5]@3 ~ [b4,d5]@3 ~ [c#5,e5]@2 ~@2]/2",
  C: "[d5,f#5]@5 ~ [d5,f#5]@6 [d5,f#5]@3 ~", D: "[c#5,e5]@4 ~@2 [c#5,e5]@2 [b4,d5]@4 [b4,d5]@3 ~",
  E: "[c#4,e4]!2 ~ [c#4,e4] [d4,f#4] ~ [c#4,e4]@2", F: "[b3,d4]!2 ~ [b3,d4]@2 ~ [b3,d4] ~",
  G: "[c#4,e4]!2 ~ [c#4,e4] [d4,f#4] ~ [c#4,e4] ~", H: "[b3,d4]@2 [b3,d4]@2 ~@2 [b3,d4]@2 [c#4,e4]@2 ~@2 c#4 ~@3",
  I: "[[c#4,f#4]@7 ~]/3", // F#5
})).s("gm_electric_guitar_clean").gain(0.4).pan(0.7)

// chords · electric guitar clean
const electric_guitar_clean_3 = note("<A B@7 C@8 D@4 E@8 F@8 G@16 H@8 E@8 F@8 I@8>".pickRestart({
  A: "~@15 c#3",
  B: "[[e3,a3]@15 ~ b3@15 ~ a3@15 ~ b3@15 ~ a3@31 ~ d4@15 [g#3,b3], ~@15 [e3,g#3]@16 [c#3,e3]@16 [e3,g#3]@16 [c#3,e3]@32 [f#3,a3]@17]/7", // A5 G#m E C#m E C#m F#m
  C: "[e4@15 ~ a3@15 ~ b3@15 ~ a3@15 ~ b3@15 ~ a3@31 ~ d4@15 [g#3,b3], ~@15 [c#3,e3]@16 [e3,g#3]@16 [c#3,e3]@16 [e3,g#3]@16 [c#3,e3]@32 [f#3,a3]@17]/8", // G#m C#m E C#m E C#m F#m
  D: "[e4@15 ~ a3@15 ~ b3@15 ~ a3@15 [f#3,a3], ~@15 [c#3,e3]@16 [e3,g#3]@16 [c#3,e3]@16 ~]/4", // F#m C#m E C#m
  E: "[d4@7 ~ c#4@7 ~ b3@15 ~ a3@15 ~ a3@31 ~ b3@15 ~ a3@15 ~ a3@15 [e3,g#3], ~@7 [e3,a3]@8 [e3,g#3]@16 [d3,f#3]@16 [c#3,e3]@32 [e3,g#3]@16 [d3,f#3]@16 [c#3,e3]@16 ~]/8", // E A5 E D C#m E D C#m
  F: "[b3@14 ~@2 a3@31 ~ d4@15 ~ e4@15 ~ a3@15 ~ b3@15 ~ a3@15 [e3,g#3], ~@15 [c#3,e3]@32 [f#3,a3]@16 [g#3,b3]@16 [c#3,e3]@16 [e3,g#3]@16 [c#3,e3]@17]/8", // E C#m F#m G#m C#m E C#m
  G: "[b3@15 ~ a3@31 ~ d4@15 ~ e4@15 ~ a3@15 ~ b3@15 ~ a3@15 [e3,g#3], ~@15 [c#3,e3]@32 [f#3,a3]@16 [g#3,b3]@16 [c#3,e3]@16 [e3,g#3]@16 [c#3,e3]@17]/8", // E C#m F#m G#m C#m E C#m
  H: "[b3@15 ~ a3@31 ~ d4@15 ~ e4@15 ~ a3@15 ~ b3@15 ~ a3@15 [f#3,a3], ~@15 [c#3,e3]@32 [f#3,a3]@16 [g#3,b3]@16 [c#3,e3]@16 [e3,g#3]@16 [c#3,e3]@16 ~]/8", // F#m C#m F#m G#m C#m E C#m
  I: "[b3@15 ~ a3@15 ~ b3@15 ~ a3@15 ~ b3@15 ~ a3@42 ~@6, ~@15 [c#3,e3]@16 [e3,g#3]@16 [c#3,e3]@16 [e3,g#3]@16 [c#3,e3]@43 ~@6]/8", // C#m E C#m E C#m
})).s("gm_electric_guitar_clean").gain(0.25)

// chords · acoustic guitar nylon
const acoustic_guitar_nylon = note(`<
  ~ A B@2 C D@2 E F D C D C D@2 E F D C D G H E D@2 H E D H D@2 E F D C D C D@2 E F D C D C D@2 E F D C D C D@2 E F D C
  D G H E D@2 H E D H D@2 E F D C D C I J I J K@3
>`.pickRestart({
  A: "[a3,c#4,e4] [a3,c#4,e4]@2 [a3,c#4,e4]!3 [a3,c#4,e4]@2", // A
  B: "[[b3,d4,e4] ~ [b3,d4,e4]@4 [b3,d4,e4]@2 [b3,d4,e4]@2 [b3,d4,e4]@2 [b3,d4,e4]@6 [a3,c#4,e4] ~ [a3,c#4,e4]@2 [a3,c#4,e4]@2 [a3,c#4,e4]@2 [a3,c#4,e4]@2 [a3,c#4,e4]@2 [a3,c#4,e4]@2]/2", // E7 A
  C: "[b3,d4,e4]!8", D: "[a3,c#4,e4]!8", E: "[a3,d4,f#4]!8",
  F: "[g#3,b3,e4]@2 [g#3,b3,e4]@2 [g#3,b3,e4]@2 [g#3,b3,e4]@2 [g#3,b3,e4]@2 [g#3,b3,e4]@2 [g#3,b3,e4]@2 [g#3,b3,e4] ~", // E
  G: "[a3,d4,f#4]!3 a3 [a3,c#4,e4]!4, ~@3 [d4,f#4]@5", H: "[g#3,b3,e4]!8",
  I: "[a3,c#4,e4]@2 [a3,c#4,e4]!2 [a3,c#4,e4]@2 [a3,c#4,e4]@2 [a3,c#4,e4]@2 [a3,c#4,e4]@2 [a3,c#4,e4]@2 [a3,c#4,e4]@2", // A
  J: "[b3,d4,e4]@2 [b3,d4,e4]!2 [b3,d4,e4]@2 [b3,d4,e4]@2 [b3,d4,e4]@2 [b3,d4,e4]@2 [b3,d4,e4]@2 [b3,d4,e4]@2", // E7
  K: "[[a3,c#4,e4]@43 ~@5]/3", // A
})).s("gm_acoustic_guitar_nylon").gain(0.3)

// other · alto sax
const alto_sax = note(`<
  ~@5 A B C D@2 ~@3 E F G H@2 ~@3 I J K ~ L M N O A P C D@2 ~@11 A P C D@2 ~@3 A P C D@2 ~@3 I J K ~ L M N O A P C D@2
  ~@10
>`.pickRestart({
  A: "a3@2 ~ a3@2 ~@3", B: "~@4 a3@3 ~ b3@3 ~ c#4@3 ~", C: "d4@4 ~@2 d4@3 ~@3 a3@3 ~",
  D: "[g#3@3 ~ a3@2 b3@3 ~ g#3@3 ~ a3@5 ~@13]/2", E: "a3@4 ~@2 a3@3 ~@7", F: "~@4 a3@3 ~ b3@2 c#4@6",
  G: "d4@4 ~@2 d4@5 ~ a3@4", H: "[g#3@4 a3@3 ~ b3@2 g#3@4 a3@8 ~@10]/2", I: "d4 ~ d4 ~ d4@2 b3@5 ~@3 c#4@2",
  J: "d4@3 ~ d4 ~ d4@2 ~@2 e4@2 d4@2 ~@2", K: "d4@2 c#4@3 ~ c#4@9 ~", L: "~@3 c#4", M: "d4@3 ~ d4 ~ d4@3 ~ e4@2 d4@3 ~",
  N: "d4@2 c#4@3 ~ c#4@4 d4@2 c#4@4", O: "b3@10 c#4@2 b3@3 ~", P: "~@4 a3@3 ~ b3@2 ~@2 c#4@2 ~@2",
})).s("gm_alto_sax").gain(0.59)

// drums · kick
const kick = s("bd").struct("<~ [x ~@2 x ~ x ~ x]!80 x ~@2>").gain(0.4)

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

// drums · crash
const crash = s("cr").struct("<~@81 x ~@2>").gain(0.45)

// drums · ride
const ride = s("rd").struct("<~@5 [x!8]!72 ~@7>").gain(0.25)

// drums · guiro
const guiro = s("guiro:0").struct("<~ A@4 B@44 A@4 B@24 A C@3 D ~@2>".pickRestart({
  A: "x ~ x!3 ~ x ~@3 x!3 ~ x ~", B: "x ~ x!3 ~ x ~@3 x ~@3 x ~", C: "x ~ x!3 ~ x ~@3 x ~ x ~ x ~", D: "x",
})).gain(6.29)

// drums · guiro
const guiro_2 = s("guiro:4").struct("<~ [x ~@2 x!2 ~ x!2]!80 x ~@2>").gain(6.29)

stack(
  piano, bass, electric_guitar_clean, electric_guitar_clean_2, electric_guitar_clean_3, acoustic_guitar_nylon, alto_sax,
  kick, snare, crash, ride, guiro, guiro_2
)