Strudelify
KeyD majorTempo135 bpm
0:00/0:00
// Perfect — Fairground Attraction
// 135 bpm, 4/4, key D 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: Full arrangement: all 122 bars on a 24-step grid, each part at one level. Source detail keeps the original performance.
setcpm(135/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.

// bass · acoustic bass
const bass = note(`<
  ~ A@2 B@2 A@2 B@2 A@2 C@2 A D E F G H I@2 G J I@2 K L M N G H O F A@2 B@2 A@2 B@2 A@2 C@2 A D E F G H I@2 G J I@2 K L
  M N G H O F P Q I R S T U V W X Y Z AA H I AB AC AD AE@2 AC AF AG AE AC@2 AH AI AJ AK AL AB G H I@2 G J I@2 K L M N G
  H O F G H AM AB G H AN AO@2
>`.pickRestart({
  A: "g1@4 d2 ~ e2 ~", B: "d2@4 a1 ~ b1 ~", C: "b1@4 f#1 ~ a1 ~", D: "a1@4 b1 ~ c#2 ~", E: "d2 ~ d2 ~ g1@2 a1@2",
  F: "d2 ~@7", G: "g1 b1 d2 b1", H: "a1 b1 c#2 e2", I: "d2 b1 a1 b1", J: "a1 b1 c#2 a1", K: "g1 b1 d2 e2",
  L: "f#1 f#2 e2 c#2", M: "b1 a1", N: "g1@7 ~", O: "g2!4 f#2 e2", P: "g1 e2 d2 e2", Q: "g1@4 ~ e2 d2@3 e2@3",
  R: "d2 f#2 a2 f#2", S: "g2@4 ~ e2 d2@3 e2@3", T: "g2 b1 d2 e2", U: "d2@2 ~ d2@3 f#2@3 a2@3",
  V: "d3@4 ~ d3 a2@3 f#2@2 ~", W: "g2 f#2 e2 d2", X: "g2 e2 d2 b1", Y: "d2 b1 a1 f#1", Z: "b1!2 f#1 a1",
  AA: "g1!2 b1 d2", AB: "d2 ~@11", AC: "g2@5 ~ b1@3 d2@3", AD: "g2@5 ~ b1@3 e2@3", AE: "d2@5 ~ a1@3 b1@3",
  AF: "g2@2 b1 e2", AG: "d2@2 a1 b1", AH: "b1@2 f#1 a1", AI: "b1@5 ~ f#1@3 a1@3", AJ: "g1@5 ~ b1@3 d2@3",
  AK: "a1@5 ~ c#2@3 e2@3", AL: "d2!2 g1 a1", AM: "g2@2 g2 ~ g2 ~ g2@2 f#2@2 e2@2",
  AN: "g2@4 g2@4 g2@2 ~@2 g2@4 ~ f#2@4 e2@3", AO: "[~@2 d2@41 ~@5]/2",
})).s("gm_acoustic_bass").gain(0.4)

// chords · acoustic guitar nylon
const acoustic_guitar_nylon = note(`<
  ~@15 A B C D E F C G H@2 C I J K C D L M ~@14 A N C D E F C G H@2 C I O K C D L M C@2 F@2 C@2 F@2 C@2 F P C D F Q ~@14
  A N C D E F C G H@2 C I J K C D L R C S L T C S U V@2
>`.pickRestart({
  A: "~@5 [b3,d4,g4] [b3,d4,g4]@2 ~ [c#4,e4,a4]@2 ~", B: "[a3,d4,f#4]@2 ~@4 [d3,f#3,c4,d4]@5 ~",
  C: "~@4 [b3,d4,g4] ~@5 [b3,d4,g4] ~@5 [b3,d4,g4] ~@5 [b3,d4,g4] ~", // G
  D: "~@4 [c#4,e4,a4] ~@5 [c#4,e4,a4] ~@5 [c#4,e4,a4] ~@5 [c#4,e4,a4] ~", // A
  E: "~@4 [d4,f#4,a4] ~@5 [d4,f#4,a4] ~@5 [d4,g4,b4] ~@5 [d4,g4,b4] ~", // D G
  F: "~@4 [d4,f#4,a4] ~@5 [d4,f#4,a4] ~@5 [d4,f#4,a4] ~@5 [d4,f#4,a4] ~", // D
  G: "~@4 [c#4,e4,a4] ~@5 [c#4,e4,a4] ~@5 [c#4,e4,a4] ~ [c#4,e4,a4]@4 [c#4,e4,a4] ~", // A
  H: "[~@4 [d4,f#4,a4] ~@5 [d4,f#4,a4] ~@5 [d4,g4,b4] ~@5 [d4,f#4,a4]@6 [d4,f#4,a4] ~@5 [d4,f#4,a4] ~@5 [d4,f#4,a4] ~ [d4,f#4,a4]@4 [d4,f#4,a4] ~]/2", // D G D
  I: "~@4 [a#3,c#4,f#4] ~@5 [a#3,c#4,f#4] ~@5 [a#3,c#4,f#4] ~@5 [a#3,c#4,f#4] ~", J: "[b3,d4,f#4] [a3,c#4,e4]",
  K: "[g3,b3,d4]", L: "[g3,b3,d4,e4] ~ [g3,b3,d4,e4] ~ [g3,b3,d4,e4] ~ [g3,b3,d4,e4] ~ [g3,b3,d4,e4] ~ [g3,b3,d4,e4] ~",
  M: "[f#3,a3,d4] ~@11", N: "[a3,d4,f#4]@2 ~@4 [f#3,c4,d4]@5 ~, ~@11 d3@10 ~@3", O: "[b3,d4,f#4]@12 [a3,c#4,e4]@11 ~",
  P: "~@4 [b3,d4,f#4] ~@5 [b3,d4,f#4] ~@5 [b3,d4,f#4] ~@5 [b3,d4,f#4] ~", Q: "[a3,d4,f#4] ~@23",
  R: "[f#3,a3,d4] ~@5 [c4,d4]@6, ~@11 [d3,f#3]@13", S: "~@4 [c#4,e4,a4] ~@5 [c#4,e4,a4] ~@5 [c#4,e4,a4] ~@7",
  T: "[d3,f#3,a3,d4] ~@5 [c4,d4]@6, ~@11 [d3,f#3]@13", // D Csus2 D
  U: "[g3,b3,d4,e4]@2 ~@2 [g3,b3,d4,e4]@2 ~@2 [g3,b3,d4,e4]@2 ~@2 [g3,b3,d4,e4]@2 ~@3 [g3,b3,d4,e4]@2 ~@2 [g3,b3,d4,e4]@2 ~", // Em7
  V: "[~@2 [e4,a4]@41 ~@5, ~ [f#3,b3]@42 ~@5]/2", // A5 B5
})).s("gm_acoustic_guitar_nylon").gain(0.25).pan(0.3)

// other · acoustic guitar steel
const acoustic_guitar_steel = note(`<
  ~ A B C D B@2 C D B@2 E@2 B F G ~@17 A B C D B@2 C D B@2 E@2 B F G ~@74
>`.pickRestart({
  A: "g2@3 ~@2 e3 d3@3 e3 ~@2", B: "g2@4 ~ e3 d3@3 e3 ~@2", C: "d3@3 ~@2 b2 a2@3 b2 ~@2", D: "d3@4 ~ b2 a2@3 b2 ~@2",
  E: "b2@4 ~ b2 f#2@3 a2 ~@2", F: "a2@5 ~ b2@2 ~ c#3 ~@2", G: "d3 ~@11",
})).s("gm_acoustic_guitar_steel").gain(0.4).pan(0.7)

// other · electric guitar clean
const electric_guitar_clean = note("<~@28 A@2 ~@30 A@2 ~@46 A@2 ~@12>".pickRestart({
  A: "[~@5 f#2 g2@2 g2 g2@2 g2@10 ~@3]/2",
})).s("gm_electric_guitar_clean").gain(0.35)

// other · electric guitar jazz
const electric_guitar_jazz = note("<~@64 A B@2 C@2 D E F G H I J@2 K L M ~@42>".pickRestart({
  A: "~@6 f#4 ~@2 d4 ~@2", B: "[f#4@2 e4@7 d4@2 b3@7 f#4 ~@2 d4 ~@2]/2", C: "[f#4@2 e4@7 b3@2 a3@12 d3]/2",
  D: "g3@4 ~ g3@6 d3", E: "g3@4 ~ g3@6 ~", F: "f#4@4 ~ f#4 a4 ~@2 g4 ~@2", G: "f#4 ~@2 f4@2 e4@6 ~",
  H: "g3@3 ~ b4@2 a4@3 ~ g4@2 b4@3 ~ a4@7 ~", I: "~@4 b4@2 a4@3 ~ g4@2 b4@3 ~ a4@7 ~",
  J: "[~@4 f#4@2 e4@3 ~ d4@2 e4@5 ~ d4@3 ~ f#4@19 ~ d3@5 ~]/2", K: "g2@3 ~ g2@2 g2@3 ~ g2@2 f#2@3 ~ g2@2 g2@3 ~ g2@2",
  L: "a2@3 ~ c3@5 ~ c3@2 a2@3 ~ f2@7 ~", M: "d3",
})).s("gm_electric_guitar_jazz").gain(0.48).pan(0.1)

// other · electric guitar jazz
const electric_guitar_jazz_2 = note("<~@64 A B@2 C@2 D@2 E F G H I@2 ~@2 J K ~@41>".pickRestart({
  A: "~@6 a4 ~@2 a4 ~@2", B: "[a4@2 a4@6 ~ a4@2 a4@7 a4 ~@2 a4 ~@2]/2", C: "[a4 ~ a4@6 ~ a4@2 a4@12 ~]/2",
  D: "~@2 g4 f4@2 ~ g4@2 f4@3 ~", E: "~@2 d5@3 ~ f#5 ~@2 e5 ~@2", F: "d5 ~@2 c#5@2 c5@7", G: "~@2 d5 d5@2 b4 d5@2 d5@4",
  H: "~@2 d5 d5@2 d5 d5@2 d5@4", I: "[~@2 a4 a4@2 a4 a4@3 a4 ~ a4@10 ~@3]/2", J: "~ [f#4,a4,d5]@3",
  K: "[f#4,a4,d5] ~@11", // D
})).s("gm_electric_guitar_jazz").gain(0.48).pan(0.9)

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

// drums · rim
const rim = s("rim").struct("<~@81 A@15 ~ A@10 ~@2 A@2 ~@2 A@2 ~@2 A@2 ~@3>".pickRestart({
  A: "~ x ~ x",
})).gain(0.4)

// drums · snare
const snare = s("sd").struct(`<
  ~ A@14 B C A@10 ~@2 A@2 D C A@14 B C A@10 ~@2 A@2 D C A@14 E C A@14 F C A@10 ~@2 A@2 D G A H D G A H I ~@2
>`.pickRestart({
  A: "x ~ x!2 ~ x!2 ~ x!2 ~ x", B: "x ~ x!2 ~ x!2 ~@2 x ~@2", C: "x", D: "x!6", E: "x!12", F: "x ~@2 x ~ x!2 ~@2 x ~@2",
  G: "x ~@2 x", H: "x ~ x!2 ~ x!2 ~ x!2 ~@2", I: "x!3 ~@3",
})).gain(0.35)

// drums · clap
const clap = s("cp").struct("<~@65 A@15 ~@17 A@10 ~@2 A@2 ~@2 A@2 ~@2 A@2 ~@3>".pickRestart({
  A: "~ x ~ x",
})).gain(0.4)

// drums · hihat
const hihat = s("hh").struct(`<
  ~ A@15 ~ A@10 ~@2 A@2 ~@2 A@15 ~ A@10 ~@2 A@2 ~@2 A@14 ~@2 A@14 ~@2 A@10 ~@2 A@2 ~@2 A@2 ~@2 A@2 ~@3
>`.pickRestart({
  A: "~ x ~ x",
})).gain(0.4)

// drums · low tom
const low_tom = s("lt").struct("<~@64 [~@3 x] ~@31 [~@3 x] ~@22 [~@7 x] [~ x ~@10] ~>").gain(0.35)

// drums · mid tom
const mid_tom = s("mt").struct("<~@119 [~@17 x ~@6] ~@2>").gain(0.4)

// drums · crash
const crash = s("cr").struct("<~@27 A B ~@30 A B ~@4 B ~@41 A B ~@7 C ~@3 D ~>".pickRestart({
  A: "x!2", B: "x", C: "~@3 x", D: "~ x ~@10",
})).gain(0.4)

// drums · high tom
const high_tom = s("ht").struct("<~@119 [~ x] ~@2>").gain(0.4)

stack(
  bass, acoustic_guitar_nylon, acoustic_guitar_steel, electric_guitar_clean, electric_guitar_jazz,
  electric_guitar_jazz_2, kick, rim, snare, clap, hihat, low_tom, mid_tom, crash, high_tom
)