Strudelify

Closing Time

Semisonic

KeyA♭ majorTempo93 bpm
0:00/0:00
// Closing Time — Semisonic
// 93 bpm, 4/4, key Ab 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 105 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 29.
setcpm(93/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 · overdriven guitar
const overdriven_guitar = note("<~@62 A@2 B C B C B D B D ~@14 E ~ F ~ E ~ F ~ E ~ F ~ G ~@6>".pickRestart({
  A: "[~@8 a2!2 a2@2 ~@4, ~ g3@10 ~@5]/2", B: "~@5 [g2,d3,g3]!2 [g2,d3,g3]@3 ~@6", C: "~ [c2,g2,c3,e3] ~@2",
  D: "[c2,g2,c3,e3]!2 ~@2", E: "[b3,e4] ~ [d4,gb4]@2 d4@2 b4@8 ~@2, ~@3 g4@3 ~@2", F: "~ [a3,d4] [b3,e4] [d4,g4]@2 ~@3",
  G: "[b3,e4] ~ [d4,gb4]@2 d4@2 [a3,g4]@2 ~@8", // E5 D A7
})).s("gm_overdriven_guitar").gain(0.72).pan(0.3)

// chords · electric guitar clean
const electric_guitar_clean = note(`<
  A B A B A B A B A B A B A B A B A B A B A C D E D E D E D F A C A C A C A C A C A C A C A C D E D E D E D F ~@9 G@7
  H@2 A C A I@2 J K J K J K L M N O N O N O N O N O N O N P@3 Q R S@2
>`.pickRestart({
  A: "[g2,d3]@2 [g2,d3]@2 [g2,d3]@2 [g2,d3]!2 [d3,a3]!2 [d3,a3]@2 [d3,a3]@2 [d3,a3]!2", // G5 D5
  B: "[a2,e3]!2 [a2,e3]@2 [a2,e3]@2 [a2,e3]!2 [c3,g3]!2 [c3,g3]@2 [c3,g3]@2 [c3,g3]!2, ~ g3@5 ~@10", // A5 C5
  C: "[a2,e3]!2 [a2,e3]@2 [a2,e3]@2 [a2,e3]!2 [c3,g3]!2 [c3,g3]@2 [c3,g3]@2 [c3,g3]@2, ~ g3@5 ~@10", // A5 C5
  D: "[g2,d3,g3]@2 [g2,d3,g3] ~@2 [d3,a3,d4] [d3,a3,d4]@2", E: "[a2,e3,a3]@2 [a2,e3,a3] ~@2 [c3,g3,c4]!2 [b2,gb3,b3]",
  F: "[a2,e3,a3]@4 [a2,e3,a3]@2 ~@2 [c3,g3,c4]@2 [c3,g3,c4]@2 [c3,g3,c4]!2 [c3,g3,c4]@2", // A5 C5
  G: "[~@4 [c2,g2,c3] [d2,a2,d3] [e2,b2,e3] [g2,d3,g3]@2 ~ [g2,d3,g3]@3 [d2,gb2,d3,gb3]@2 [c2,g2,c3]@5 [b2,e3] [db3,gb3] [d3,g3] [g3,b3]@2 ~ [g2,d3,g3]@3 [d2,gb2,d3,gb3]@2 [c2,e3]@5 [g2,c3] [a2,d3] [b2,e3] [d3,g3]@2 ~ [g2,d3,g3]@3 [d2,gb2,d3,gb3]@2 [c2,g2,c3]@5 [b2,e3] [db3,gb3] [d3,g3] [g3,b3], ~@15 e3@4 ~@12 [g2,c3]@4 ~@12 e3@4 ~@5]/7", // C5 D5 E5 G5 D C5 E5 Gb5 …
  H: "[~@2 [g2,d3,g3]@3 [d2,gb2,d3,gb3]@2 [c2,e3]@5 [g2,c3] [a2,d3] [b2,e3] [d2,g2], ~@7 [g2,c3]@4 ~@5]/2", // G5 D C C5 D5 E5 G5 C5
  I: "[[a2,e3]@12 [g2,d3,g3]@2 [g2,d3,g3] ~]/2", J: "~ [d3,a3,d4] [d3,a3,d4]@2 [a2,e3,a3]@2 [a2,e3,a3] ~",
  K: "~ [c3,g3,c4]!2 [b2,gb3,b3] [g2,d3,g3]@2 [g2,d3,g3] ~", // C5 B5 G5
  L: "~@2 [d3,a3,d4]@2 [d3,a3,d4]@4 [a2,e3,a3]!2 ~ [a2,e3,a3]!2 ~ [a2,e3,a3]!2", // D5 A5
  M: "~ [a2,e3,a3] [c3,g3,c4] ~ [c3,g3,c4]!2 [c3,g3,c4]@2 [g2,d3,g3]@4 [g2,d3,g3]@2 [g2,d3,g3]!2", // A5 C5 G5
  N: "[a2,d3,a3]!2 [a2,d3,a3]@2 [a2,d3,a3]@4 [a2,e3,a3]@4 [a2,e3,a3]@2 [a2,e3,a3]!2", // D5 A5
  O: "[c3,g3,c4]!2 [c3,g3,c4]@2 [c3,g3,c4]@4 [g2,d3,g3]@4 [g2,d3,g3]@2 [g2,d3,g3]!2", // C5 G5
  P: "[[c3,g3,c4]!2 [c3,g3,c4]@2 [c3,g3,c4]@4 [g2,d3]@2 [g2,d3]@2 [g2,d3]@3 [g2,d3] d3 [d3,a3]!2 [d3,a3]@2 [d3,a3]@3 a3@2 [a2,e3]@2 [a2,e3]@2 [a2,e3]@2 ~ [a2,e3]!2 [c3,g3]!2 [c3,g3]@2 [c3,g3]@2 ~ [c3,g3]!2 [g2,d3]@2 [g2,d3]@2, ~@8 g3@27 ~@13, ~@16 g2@19 ~@13, ~@24 d3@11 ~@13]/3", // C5 G5 D5 A5 C5 G5
  Q: "[g2,d3]@2 ~ [g2,d3]!2 [d3,a3]!2 [d3,a3]@2 [d3,a3]@2 ~ [d3,a3]@2 [a2,e3]@2", // G5 D5 A5
  R: "[a2,e3]@2 [a2,e3]@2 ~ [a2,e3]!2 [c3,g3]!2 [c3,g3]@2 ~ [c3,g3]@2 [c3,g3]@2", S: "[~ [g2,d3,g3]@24 ~@7]/2",
})).s("gm_electric_guitar_clean").gain(0.72)

// chords · distortion guitar
const distortion_guitar = note(`<
  ~@22 A B A B A B A C ~@16 A B A B A B A C ~@9 D@2 E@2 F@2 E@2 G ~@4 H I J I J I J K L I M I N I O I P I M I N I Q ~@6
>`.pickRestart({
  A: "[g2,d3,g3]@4 [g2,d3,g3]@2 [g2,d3,g3]!4 [a2,d3,a3]@2 [a2,d3,a3]@4", // G5 D5
  B: "[a2,e3,a3]@4 [a2,e3,a3]@2 [a2,e3,a3]!4 [c3,g3,c4]@2 [c3,g3,c4]@4", // A5 C5
  C: "[a2,e3,a3]@4 [a2,e3,a3]@2 [a2,e3,a3]!2 [c3,g3,c4]@2 [c3,g3,c4]@2 [c3,g3,c4]!2 [c3,g3,c4]@2", // A5 C5
  D: "[~@8 [c3,g3,c4]@2 [d3,a3,d4]@2 [e3,b3,e4]@2 [g3,d4]@6 [g3,d4,g4]!3 [g3,d4,g4]@3 [d3,gb3,d4,gb4]@4 [c3,g3,c4,e4]@2, ~@7 g4@2 ~@7]/2", // C5 D5 E5 G5 D C
  E: "[[c3,g3,c4,e4]@4 [c3,g3,c4,e4]@4 [b3,e4]@2 [db4,gb4]@2 [d4,g4]@2 [g4,b4]@5 ~ [g3,d4,g4]!3 [g3,d4,g4]@3 [d3,gb3,d4,gb4]@4 [c3,g3,c4,e4]@2]/2", // C E5 Gb5 G5 G G5 D C
  F: "[[c3,g3,c4,e4]@4 [c3,g3,c4,e4]@4 [g3,c4]@2 [a3,d4]@2 [b3,e4]@2 [d4,g4]@5 ~ [g3,d4,g4]!3 [g3,d4,g4]@3 [d3,gb3,d4,gb4]@4 [c3,g3,c4,e4]@2]/2", // C C5 D5 E5 G5 D C
  G: "[c3,g3,c4,e4]@2 [c3,g3,c4,e4]@2 [g3,c4] [a3,d4] [b3,e4] [d3,g3]", H: "~@8 [g2,d3,g3]@4 [g2,d3,g3]@2 [g2,d3,g3]!2",
  I: "[g2,d3,g3]!2 [a2,d3,a3]@2 [a2,d3,a3]@4 [a2,e3,a3]@4 [a2,e3,a3]@2 [a2,e3,a3]!2", // G5 D5 A5
  J: "[a2,e3,a3]!2 [c3,g3,c4]@2 [c3,g3,c4]@4 [g2,d3,g3]@4 [g2,d3,g3]@2 [g2,d3,g3]!2", // A5 C5 G5
  K: "[g2,d3,g3]!2 [a2,d3,a3]@2 [a2,d3,a3]@4 [a2,e3,a3]!2 ~ [a2,e3,a3]!2 ~ [a2,e3,a3]!2", // G5 D5 A5
  L: "~ [a2,e3,a3] [c3,g3,c4] ~ [c3,g3,c4]!2 [c3,g3,c4]@2 [g2,d3,g3]@4 [g2,d3,g3]@2 [g2,d3,g3]!2", // A5 C5 G5
  M: "[a2,e3,a3,b3,e4] [a2,e3,a3] [c3,g3,c4,d4,gb4]@2 [d4,g4]@2 ~@2 [g2,d3,g3]@4 [g2,d3,g3]@2 [g2,d3,g3]!2, ~ [c3,g3,c4] ~@2, ~@3 b4@4 ~, ~@3 g4@3 ~@2", // Asus2 A5 Csus2 G5 C5
  N: "[a2,e3,g3,a3,c4] [a2,e3,a3] [c3,g3,a3,c4,d4]@2 [b3,e4]@2 ~@2 [g2,d3,g3]@4 [g2,d3,g3]@2 [g2,d3,g3]!2, ~ [c3,g3,c4] ~@2, ~@3 [d4,g4]@2 ~@3", // Am7 A5 Csus2 E5 G5 C5 G5
  O: "[a2,e3,a3,b3,e4] [a2,e3,a3] [c3,g3,c4,d4,gb4]@2 [d4,g4]@2 ~@2 [g2,d3,g3]@4 [g2,d3,g3]@2 [g2,d3,g3]!2, ~ [c3,g3,c4] ~@2, ~@3 [g4,b4]@2 ~@3", // Asus2 A5 Csus2 G5 C5 G
  P: "[c3,g3,c4]@2 [c3,g3,a3,c4,d4]@2 [c3,g3,b3,c4,e4] [c3,g3,c4] [c3,g3,c4]@2 [g2,d3,g3]@4 [g2,d3,g3]@2 [g2,d3,g3]!2, ~@3 [e4,g4]@2 ~@3", // C5 Csus2 Cmaj7 C5 G5 Em
  Q: "[a2,e3,a3,b3,e4] [a2,e3,a3] [c3,g3,c4,d4,gb4]@2 g4@2 a3@2 ~@8, ~ [c3,g3,c4,d4] ~@2", // Asus2 A5 Csus2
})).s("gm_distortion_guitar").gain(0.72).pan(0.7)

// bass · electric bass finger
const bass = note(`<
  ~@22 A B A B A B A B C D E F E F E F E F E F E F E F A B A B A B A B G ~@5 H I H I H I H I H I H I E F E J@2 K L K L K
  L K L K L K L K L K L K L K L K M@3 ~@4
>`.pickRestart({
  A: "g2!4 d3!4", B: "a2!4 c3!4", C: "g2@2 g2 ~@2 d3 d3@2", D: "a2@4 a2@2 ~@4 c3@2 c3@2 [f1,f2] [gb1,gb2], ~@7 c3",
  E: "g1 ~ g2 ~@2 [d2,d3] [d2,d3]@2, g2 ~@3, ~ g1@2 ~@5", // D
  F: "a1@2 ~@2 a2@2 ~@4 [c2,c3]@2 c3@2 [f1,f2] [gb1,gb2], a2@2 ~@5 c3, ~ a1@2 ~@3 c2@2", G: "bb2 ~@7", H: "g1!5 d2!3",
  I: "a1!5 c2!3", J: "[[a1,a2]@12 g2!4]/2", K: "d3!4 a2!4", L: "c3!4 g2!4", M: "[c3@2 c3@2 c3@2 c3@2 g2@27 ~@13]/3",
})).s("gm_electric_bass_finger").gain(0.72)

// other · piano
const piano = note(`<
  ~@2 A B A B A B A B A B A B A B A B A B A C ~@8 A B A B A B A B A B A B A B A C ~@8 D@6 A B A B ~@19 E F G H G H G H G
  H G H G H G I@2 J K L M@2
>`.pickRestart({
  A: "b4 g4 b4 g4 d5 g4 b4 g4", B: "b4 g4 b4 g4 c5 g4 b4 g4", C: "b4 g4 b4 g4 c5 g4 b4@2",
  D: "[bb4@4 ab4 bb4 c5 eb5@2 d5@2 c5@2 bb4 g4 bb4@2 f4 bb4@2 ab4 bb4 c5 eb5@2 d5@2 c5@2 bb4 g4 bb4@2 f4 bb4@2 ab4 bb4 c5 eb5@2 d5@2 c5@2 bb4 g4@2]/6",
  E: "g4 d4 g4 d4 ~@4", F: "~@4 b4 g4 b4 g4", G: "d5 g4 b4 g4 b4 g4 b4 g4", H: "c5 g4 b4 g4 b4 g4 b4 g4",
  I: "[c5@2 g4@2 b4@2 g4@2 b4@2 g4@2 b4@2 ~ g4@2 d5@2 g4@2 b4@2 ~ g4@2 b4@2 g4@2 b4@2]/2",
  J: "~ g4@2 c5@2 g4@2 b4@2 ~ g4@2 b4@2 g4@2", K: "b4@2 ~ g4@2 d5@2 g4@2 b4@2 ~ g4@2 b4@2",
  L: "g4@2 b4@2 ~ g4@2 c5@2 g4@2 ~ b4@2 g4@2", M: "[~ b4@25 ~@6]/2",
})).s("gm_piano").gain(0.72)

// chords · synth strings 1
const synth_strings_1 = note("<~@54 A@6 B@4 ~@8 C@2 D@3 ~@28>".pickRestart({
  A: "[[bb3,bb4]@4 ab4 bb4 c5 ~@2 d5@2 ~@2 bb4 g4 ~@2 f4 bb4@2 ab4 bb4 c5 ~@2 d5@2 ~@2 bb4 g4 ~@2 f4 bb4@2 ab4 bb4 c5 ~@2 d5@2 ~@2 bb4 g4@2, ~ ab3 eb4 c4 bb3 ab3 eb4 c4 bb3 ab3 eb4 c4, ~@7 eb5@2 ~@2 c5@2 ~@2 bb4@2 ~@6 eb5@2 ~@2 c5@2 ~@2 bb4@2 ~@6 eb5@2 ~@2 c5@2 ~@3]/6", // Bb
  B: "b4/4", C: "[~ d4@2 g4]/2", D: "[a4 d5@4 ~]/3",
})).s("gm_synth_strings_1").gain(0.61)

// drums · kick
const kick = s("bd").struct(`<
  ~@22 A B A C A B A D A@7 E A@7 F A B A C A B A D G H I@7 J B@3 K B@3 K A@3 G L M N M O M N P Q M N M O M N R S N M T U
  V W ~@6
>`.pickRestart({
  A: "x ~@3 x ~@4 x!2 ~ x ~@3", B: "x ~ x ~@2 x!2 ~", C: "x ~ x ~@2 x!3", D: "x ~ x ~ x!4",
  E: "x ~@3 x ~@4 x!2 ~ x ~ x ~", F: "x ~@3 x ~@3 x ~ x!5 ~", G: "x", H: "~@4 x!2 ~@2",
  I: "x ~ x!3 ~ x ~ x ~ x ~ x ~ x ~", J: "x!6 ~@2", K: "x!8", L: "~@2 x!2", M: "~ x!2 ~ x ~@3 x ~@3 x ~@3",
  N: "~ x!2 ~ x ~ x ~", O: "~ x!4 ~ x ~", P: "~@2 x ~ x ~@3 x!2 ~ x!2 ~ x!2", Q: "~ x!2 ~ x!3 ~ x ~@3 x ~@3",
  R: "~ x!2 ~ x ~@3 x!5 ~ x!2", S: "~ x!2 ~ x!2 ~@2 x ~@3 x ~@3", T: "~@2 x ~ x ~@3 x!5 ~ x!2",
  U: "x!3 ~ x!3 ~ x ~@3 x ~@3", V: "~ x!2 ~ x!4", W: "x ~ x!3 ~ x ~ x ~@7",
})).gain(0.72)

// drums · snare
const snare = s("sd").struct(`<
  ~@22 A@3 B A@3 C A@7 B A@7 D A@3 B A@3 C ~ A@8 E A@3 F A@3 F A@3 ~ G A@3 H A@2 I J A@3 H A@2 K L A@2 M N A O ~@6
>`.pickRestart({
  A: "~ x ~ x", B: "~@4 x ~@7 x ~ x!2", C: "~@4 x ~@3 x ~ x ~ x!3 ~", D: "~@4 x ~@5 x!5 ~",
  E: "x ~ x ~ x ~ x ~ x ~ x!5 ~", F: "~@6 x!2 ~ x ~@2 x!3 ~", G: "~@3 x", H: "~@4 x ~ x!2 ~@4 x ~@3",
  I: "~@4 x ~@3 x!2 ~ x!2 ~ x!2", J: "~ x!2 ~ x!3 ~@5 x ~@3", K: "~@4 x ~@3 x!5 ~ x!2", L: "~ x!2 ~ x!2 ~@6 x ~@3",
  M: "~@4 x ~@4 x!4 ~@2 x", N: "x!3 ~@2 x!2 ~@5 x ~@3", O: "x ~ x!3 ~ x ~ x ~@7",
})).gain(0.72)

// drums · low tom
const low_tom = s("lt").struct("<~@67 [~ x!2 ~@5] ~@3 [~ x!2 ~@5] ~@23 [~@4 x ~@2 x] [~ x ~@2] ~@8>").gain(0.72)

// drums · hihat
const hihat = s("hh").struct("<~@30 A@15 B ~@9 C D@7 E ~@8 A@3 ~@30>".pickRestart({
  A: "~ x!4 ~ x!2", B: "~ x!3 ~@4", C: "~@2 x ~ x ~ x!3 ~ x ~ x ~@3", D: "x ~ x ~ x ~ x!3 ~ x ~ x ~ x!2", E: "x",
})).gain(0.72)

// drums · mid tom
const mid_tom = s("mt").struct("<~@67 x ~@3 x ~@33>").gain(0.72)

// drums · open hat
const open_hat = s("oh").struct("<~@22 A@8 B@15 C A@8 D E ~@8 A@8 B@3 D F A@21 G ~@6>".pickRestart({
  A: "x!8", B: "x ~@4 x ~@2", C: "x ~@3 x!4", D: "x", E: "~@7 x", F: "~@4 x!4", G: "x!5 ~@3",
})).gain(0.72)

// drums · crash
const crash = s("cr").struct(`<
  ~@22 A ~@3 A ~@19 A ~@3 A ~@13 A ~ A ~ A ~ A ~@5 B ~@3 B ~@2 C D ~@3 B ~@2 E F ~@2 G H ~ I ~@6
>`.pickRestart({
  A: "x", B: "~ x", C: "~@8 x ~@2 x ~@2 x ~", D: "~ x ~@2 x ~@3 x ~@7", E: "~@4 x ~ x!2", F: "~ x ~@2 x ~@11",
  G: "~@4 x ~@2 x", H: "~ x!2 ~", I: "x!3 ~",
})).gain(0.72)

// drums · shaker
const shaker = s("sh").struct("<~@6 A@48 ~@2 A@19 B C A@21 D ~@6>".pickRestart({
  A: "x ~ x!3 ~ x!3 ~ x!3 ~ x!2", B: "x", C: "~@8 x ~ x!3 ~ x!2", D: "x ~ x!3 ~ x!2 ~@8",
})).gain(0.24)

stack(
  overdriven_guitar, electric_guitar_clean, distortion_guitar, bass, piano, synth_strings_1, kick, snare, low_tom,
  hihat, mid_tom, open_hat, crash, shaker
)