Strudelify

Same Old Lang Syne

Dan Fogelberg

KeyF majorTempo106 bpm
0:00/0:00
// Same Old Lang Syne — Dan Fogelberg
// 106 bpm, 4/4, key F major. Source: midi.
// Generated by strudelify. One cycle = one bar.
// note: Tempo changes preserved in elapsed time; displayed bars use the dominant tempo.
// note: Full arrangement: all 116 bars on a 24-step grid, each part at one level; ghost notes are separate "_soft" parts. Source detail keeps the original performance.
setcpm(106/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 · piano · "Staff-3"
const piano = note(`<
  A B C D C B E F G@2 C H C I E J K@2 C H C L@2 J M@2 N@2 O@2 P J K@2 C H C B E J K@2 C H C B E J Q R S T@2 R U@2 V B C
  D C B E F W B C D C B E X Q R S T@2 R Y@2 Z AA AB@3 AC@2 AD@2 AE@5 AF AG@4 AH AI AJ@3 AK@4 AL@5 ~@3
>`.pickRestart({
  A: "~@3 g4 c5 [d5,g5] [e5,g5] d5", B: "c5@3 [d5,g5]@3 d5 [e5,g5]@5 c5@6 c5@6",
  C: "[b4,d5]@2 [c5,e5] g4 c5 [d5,g5] [e5,g5] d5", D: "c5@3 [d5,g5]@3 [d5,g5]@9 d5 e5 d5 c5@6, ~@5 g5 ~@2",
  E: "c5 [b4,d5] [a4,c5]@3 a4 [b4,d5]@2", F: "[c5,e5] [a4,c5]@2 a4 f5 [g4,f5] [g4,d5] [d4,b4]",
  G: "[g4@3 [d4,f4]@3 g4@3 ~@3 c5@3 [d5,g5]@3 [e5,g5]@3 d5@3 c5@3 [d5,g5]@3 d5 [e5,g5]@5 c5@12, ~ e4@4 ~@3, ~@3 g4@7 ~@6]/2", // Dm G5 Em G5 Em
  H: "c5 [d5,g5] [d5,g5]@3 g5 c5@2", I: "c5@3 [d5,g5]@3 d5 [e5,g5]@5 c5@12",
  J: "[c5,e5] ~@2 f3 a3 c4 d4 b3, ~ [a4,c5]@2 ~@5, ~@2 c4@3 g3@2 ~", // C Am
  K: "[g4@3 d4@3 g4@3 ~@3 c5@3 [d5,g5]@3 [e5,g5]@3 d5@3 c5@3 [d5,g5]@3 d5 [e5,g5]@5 c5@12, ~ e4@4 ~@3, ~@3 g4@7 ~@6]/2", // G5 Em G5 Em
  L: "[c5@3 [d5,g5]@3 d5 [e5,g5]@5 c5@15 [b4,d5]@3 [a4,c5]@9 a4@3 [b4,d5]@6]/2", // G5 Em Bm Am Bm
  M: "[g4@3 d4@3 g4@3 ~@2 c5@4 [d5,g5]@3 [e5,g5]@3 d5@2 c5@4 [d5,g5]@3 d5 [e5,g5]@5 c5@12, ~ e4@4 ~@3, ~@3 g4@7 ~@6]/2", // G5 Em G5 Em
  N: "[[b4,d5]@6 [c5,e5]@3 g4@3 c5@3 d5@2 g5 [e5,g5]@3 d5@5 ~ [d5,g5]@3 [d5,g5]@9 d5 e5 d5 c5@6, ~@26 c5@2 ~@11 g5@3 ~@6]/2", // Bm C Em G5
  O: "[[b4,d5]@6 [c5,e5]@3 g4@3 c5@3 [d5,g5]@3 [c5,g5]@2 d5@3 c5@3 [d5,g5]@4 d5 [e5,g5]@5 c5@12]/2", // Bm C G5 C5 G5 Em
  P: "[a4,c5] [b4,d5] [a4,c5]@3 a4 b4 d5", Q: "g4 d4 [a3,c4,e4]@3 [e3,c4] c4 d4",
  R: "d4 e4 [d4,g4,b4]@2 [c4,f4,a4] [a3,c4,f4]@3", S: "[c4,a4]@2 [b3,g4]@2 [c4,a4] [d4,g4,b4]@3",
  T: "[[b3,d4,g4]@3 [b3,d4,g4]@2 [c4,e4,a4]@10 c5@3 b4@4 g4@4 e4@4 [a3,c4,e4]@9 [e3,c4]@3 c4@3 d4@3]/2", // G Am C
  U: "[[c4,a4]@6 [b3,d4,g4]@9 [b3,d4,g4]@6 [a3,c4]@6 [b3,d4]@3 [c4,e4,a4]@9 b4@2 ~ g4@6, ~@41 a4@2 ~@5]/2", // F G Am Bm Am
  V: "[b3,d4] g3 [c4,e4] g4 c5 [d5,g5] [e5,g5] d5", W: "g4 [d4,f4] [c4,e4] g4 c5 [d5,g5] [e5,g5] d5",
  X: "[c5,e5] [a4,c5]@2 f3 a3 c4 d4 b3, ~@5 g3@2 ~", Y: "[[c4,a4] [a3,c4,f4]@2 [b3,d4,g4]@2 [d4,g4,b4]@2 ~]/2",
  Z: "~@3 g3 b3 d4 ~ g3", AA: "c4@3 [d4,g4]@3 [e4,g4]@3 ~ [d4,g4]@3 c4@3 d4@3 [e4,g4]@5",
  AB: "[~ [c4,g4]@3 [c4,g4]@6 ~ [d4,g4]@9 ~@3 g3@3 c4@2 d4 [d4,g4]@3 [e4,g4]@3 d4@3 ~ c4@3 a3@3 [d4,g4]@9 c4@2 ~ c4@6 ~ [b3,d4]@3 g3@3 [g3,c4,e4]@2, ~@28 a3 ~@7]/3", // C5 G5 Em G5 Bm C
  AC: "[~ g3@3 c4@3 [d4,g4]@3 [e4,g4]@3 [d4,g4]@3 c4@3 ~ d4@3 [c4,e4]@6 [b3,d4]@6 [c4,e4]@6 c4@3 ~ d4@3]/2", // G5 Em G5 C Bm C
  AD: "[[c4,e4]@6 c4@3 d4@9 e4@3 c4@2 d4@2 ~@3 f3@3 a3@3 [a3,c4]@3 d4@3 b3@3 g4@3 d4@2, ~@25 c4@9 ~@14]/2", // C Am
  AE: "[~@2 [c4,e4,g4]@24 [b3,d4]@19 [b3,d4,g4]@6 [c4,e4,g4]@25 [d4,g4]@10 ~ e4 d4 c4@6 [b3,d4]@6 [g3,c4,e4]@3 g3@3 ~ c4@3 [d4,g4]@3 [e4,g4]@3 [d4,g4]@3]/5", // C Bm G C G5 Bm C G5 …
  AF: "c4@3 d4@3 [c4,e4]@6 [b3,d4]@6 ~ [c4,e4]@5", // C Bm C
  AG: "[~ c4@3 d4@3 [c4,e4]@10 [a3,c4]@3 ~ [b3,d4]@6 [c4,e4]@7 ~ [f3,a3]@14 [g3,b3]@16 [f3,a3,c4]@16 [f3,a3,d4]@8 [c4,d4,f4,a4]@7]/4", // C Am Bm C F G F Dm …
  AH: "~ [b3,d4,e4,g4]@12 [a3,b3,c4,e4]@4 [a3,b3,c4,e4]@7", AI: "~ [e3,g3,c4]@8 [f3,a3,d4]@12 [f3,a3,c4]@3",
  AJ: "[~ [f3,a3,b3,d4]@8 [c4,f4,a4]@8 [b3,d4,e4,g4]@12 ~ [g3,b3,c4,e4]@4 [g3,a3,c4,e4]@8 [b3,c4,e4,g4]@8 [c4,f4,a4]@22]/3", // Bm7b5 F Em7 Cmaj7 Am7 Cmaj7 F
  AK: "[~ [b3,d4,f4,a4]@4 [b3,c4,e4,g4]@6 [g3,b3,c4,e4]@2 [g3,b3,c4,e4]@4 [e3,g3,c4]@4 [f3,ab3,b3,d4]@6 [f3,ab3,c4]@2 [f3,ab3,b3,d4]@4 eb4@2 d4@2 [f3,a3,c4]@6 d4 c4 [a3,c4,e4,g4]@3, ~@33 [e3,ab3,b3]@4 ~@11]/4", // Bm7b5 Cmaj7 C Fdim Fm Fdim F Am7 …
  AL: "[~@2 [b3,d4,g4]@8 [f3,ab3,c4,eb4]@8 ~ [ab3,c4,d4,f4]@20 b3 [b3,d4] [b3,d4,eb4] ~ [b3,d4,e4,g4]@64 ~@13]/5", // G Fm7 Dm7b5 Bm B Em7
})).s("gm_piano").gain(0.4)

// chords · string ensemble 2 · "Staff-4"
const string_ensemble_2 = note("<A@6 B@16 C@8 B@16 D@6 E@8 F@2 B@8 D@6 G@6 H@5 I J ~@7 K@5 L@7 M@5 ~@3>".pickRestart({
  A: "[~ [g3,c4]@4 [e3,a3]@4 [g3,c4]@4 [e3,a3]@4 [g3,c4]@4 [e3,a3]@3]/6", // C5 A5 C5 A5 C5 A5
  B: "[~ [b2,d3,b3] [d3,gb3,a3,c4]@8 [c3,f3,a3]@4 [b2,d3,g3]@4 [g3,c4]@8 [e3,a3]@8 [g3,c4]@8 [e3,a3]@8 [g3,c4]@8 [e3,a3]@6]/8", // Bm D7 F G C5 A5 C5 A5 …
  C: "[~ [b2,d3,b3] [d3,gb3,a3,c4]@8 [c3,f3,a3]@4 [d3,g3,b3]@4 [g3,c4]@8 [e3,a3]@8 [g3,c4]@8 [e3,a3]@8 [g3,c4]@8 [e3,a3]@6]/8", // Bm D7 F G C5 A5 C5 A5 …
  D: "[~@3 [b2,d3,b3]@3 [d3,gb3,a3,c4]@24 [c3,f3,a3]@12 [b2,d3,g3]@12 [e3,a3,c4]@24 [c3,f3,a3]@24 [b2,d3,g3]@24 [c3,e3,a3]@12 b3@4 g3@2]/6", // Bm D7 F G Am F G Am
  E: "[~ e3@2 [c3,e3,a3]@12 [c3,f3,a3]@12 [d3,g3,b3]@12 [c3,g3,a3]@6 [d3,g3,b3]@6 [g3,c4]@12 [e3,a3]@12 [g3,c4]@12 [e3,a3]@9]/8", // Am F G Am7 G C5 A5 C5 …
  F: "[~ [g3,c4]@4 [e3,a3]@3]/2", // C5 A5
  G: "[~@2 e3@4 [c3,e3,a3]@24 [c3,f3,a3]@24 [d3,g3,b3]@12 [e3,g3,c4]@12 [d3,g3,b3]@24 ~@12 c4@25 a3@5]/6", // Am F G C G
  H: "[~@14 g3@6 c4@25 a3@19 g3@6 c4@25 a3@6 g3@6 a3@12 ~]/5", I: "d4", J: "~ f3@12 g3@11",
  K: "[~@11 f3@15 ~@15 f3@16 ~@16 c3@32 d3@15, ~@11 g3@63 ~@46]/5",
  L: "[~ g3@16 c3@16 ~ a3@8 g3@8 f3@24 g3@8 c3@32 ab3@24 e3@8 f3@22]/7", M: "[~@2 g3@8 bb3@32 ~ [c3,c4]@64 ~@13]/5",
})).s("gm_string_ensemble_2").gain(0.32)

// bass · electric bass pick · "Staff-6"
const bass = note("<~@40 A@2 B@4 C@2 D@2 E@4 F@4 B@4 C@2 A@2 B@4 C@2 G@2 E@4 H@2 I@7 J K@3 ~@25>".pickRestart({
  A: "[g1@2 c2@3 c2 c2@4 a1@3 a1 a1@2]/2", B: "[b1@2 c2@3 c2 c2@4 a1@3 a1 a1@2]/2", C: "[b1@2 gb1@8 f1@3 f1 g1@2]/2",
  D: "[g1 a1@4 f1@2 f1]/2", E: "[f1 g1@4 a1@4 a1@4 f1@2 f1]/4", F: "[f1@2 g1@8 a1@8 c2@3 c2 c2@4 a1@3 a1 a1@2]/4",
  G: "[g1@2 a1@3 a1 a1@4 f1@4 f1@2]/2", H: "[f1 g1@4 ~@3]/2", I: "[~@18 c2@25 a1@25 c2@25 a1@25 c2@25 a1@25]/7",
  J: "gb1", K: "[~ f1@25 c2@25 ~@21]/3",
})).s("gm_electric_bass_pick").gain(0.4)

// drums · kick
const kick = s("bd").struct("<~@24 A B@27 A B@2 C A B@19 A B D ~@37>".pickRestart({
  A: "~@2 x ~@2 x ~@2", B: "~ x!2 ~@2 x ~@2", C: "~ x!2 ~ x ~@3", D: "~ x!2 ~@5",
})).gain(0.4)

// drums · snare
const snare = s("sd").struct("<~@24 A@27 ~ A@3 ~ A@19 ~ A@2 ~@38>".pickRestart({
  A: "~@3 x",
})).gain(0.4)

// drums · hihat
const hihat = s("hh").struct(`<
  ~@23 A B C B C B C B D E D F D G D G D E D F D G D G@3 D@2 H F D G I J D G D G D G D G D G D G D G D@3 F H F D K ~@37
>`.pickRestart({
  A: "~ x", B: "~@5 x ~ x", C: "~ x ~@3 x ~@2", D: "~ x ~ x ~ x ~ x", E: "~@3 x ~ x ~ x", F: "~@2 x!2 ~ x ~ x",
  G: "~ x!3 ~ x ~ x", H: "~ x ~ x ~ x ~@2", I: "~ x ~ x!2 ~ x ~", J: "x ~ x!2 ~ x ~ x", K: "x!2 ~@6",
})).gain(0.4)

// drums · hihat · soft notes
const hihat_soft = s("hh").struct("<A B@22 C ~@57 D E F G H I J K ~@27>".pickRestart({
  A: "~ x", B: "x!2", C: "x", D: "x ~@12 x ~@10", E: "~ x ~@12 x ~@9", F: "~@2 x ~@12 x ~@8", G: "~@3 x ~@12 x ~@7",
  H: "~ x ~@2 x ~", I: "~@5 x ~@11 x ~@6", J: "~ x ~ x", K: "~@7 x ~@11 x ~@4",
})).gain(0.08)

// drums · low tom
const low_tom = s("lt").struct("<~@32 [~ x ~@6] ~@7 [~ x ~@6] ~@75>").gain(0.4)

// drums · mid tom
const mid_tom = s("mt").struct(`<
  ~@23 A B ~@6 C D ~@5 E C D ~@3 E ~ E ~@3 E F G ~ E ~@3 E ~@16 H G ~ E ~@37
>`.pickRestart({
  A: "~@4 x ~@2 x", B: "x!2 ~@6", C: "~@18 x ~ x!2 ~@2", D: "x", E: "~ x ~@6", F: "~@3 x ~@18 x ~", G: "~ x ~@10",
  H: "~@11 x",
})).gain(0.4)

// drums · open hat
const open_hat = s("oh").struct(`<
  A ~@23 B ~ C ~ C ~ C ~ B ~ C ~ B ~ D ~ B ~ C ~ D ~ D B@2 ~ A@2 B ~ D ~ C ~ D ~ B ~ B ~ B ~ B ~ B ~ B ~ B ~ C ~ B ~ E
  ~@37
>`.pickRestart({
  A: "x", B: "~ x", C: "~ x ~@2 x ~@3", D: "x!2", E: "~ x ~@6",
})).gain(0.4)

// drums · high tom
const high_tom = s("ht").struct("<~@23 A ~@7 B ~@5 C ~ B ~@3 C ~ C ~@3 C@2 D ~ C ~@3 C ~@17 D ~ C ~@38>".pickRestart({
  A: "~@4 x ~@2 x", B: "~@3 x!2 ~@3", C: "~@7 x", D: "~@3 x",
})).gain(0.4)

// drums · ride bell
const ride_bell = s("rd").struct("<[~ x ~@2] ~@115>").gain(0.4)

// drums · crash
const crash = s("cr").struct(`<
  ~@23 A B ~ B ~ B ~ B ~ B ~ B ~ B ~ B ~ B ~ B ~ B ~ B@3 ~@2 C B ~ B ~ B ~ B ~ B ~ B ~ B ~ B ~ B ~ B ~ B ~ B C B ~ B
  ~@10 D ~@26
>`.pickRestart({
  A: "~ x", B: "~ x ~@2", C: "~@3 x", D: "~ x ~@10",
})).gain(0.4)

stack(
  piano, string_ensemble_2, bass, kick, snare, hihat, hihat_soft, low_tom, mid_tom, open_hat, high_tom, ride_bell, crash
)

More by Dan Fogelberg