Strudelify

Like an Angel Passing Through My Room

ABBA

KeyF majorTempo54 bpm
0:00/0:00
// Like an Angel Passing Through My Room — ABBA
// 53.5 bpm, 4/4, key F major. Source: midi.
// Generated by strudelify. One cycle = one bar.
// note: metre changes (4/4 at bar 1, 3/4 at bar 5, 4/4 at bar 6, 3/4 at bar 7, ...) are rendered on a constant 4/4 grid of one bar per cycle
// note: Full arrangement: all 49 bars on a 32-step grid, each part at one level. Source detail keeps the original performance.
setcpm(53.5/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 · music box
const music_box = note(`<
  ~@3 A B C D E F G H I J K L M N O P Q R C D E F G H I J K L M N O P Q S@2 T U V W@2 Q X Y Z ~@2
>`.pickRestart({
  A: "~ a5@2 c5@2 bb5@2 ~@2 c5 f5@2 ~@3 c5, ~@7 f5@2 ~@3 f5@2 g5@2, ~@8 c6@4 ~ c5@2 ~",
  B: "~@5 c5 f5@2 ~@5 c5 f5 c5, a5@2 bb5@2 c6@4 ~ c5@2 c5@2 ~@3, ~ c5@2 f5@2 ~@3 f5@2 g5@2 bb5@2 a5@2",
  C: "a4!2 c5!2 [g4,bb4] bb4!2 c5, c4 ~", D: "d5 d4 g4 a4 c5 bb4!3",
  E: "d5@2 d5@2 [g4,bb4,d5]@3 c5 a4@2 bb4@2 ~@2 c4@2, ~@2 c5!2", F: "f4 g4 bb4 a4 c5!2 f5!2, ~@2 f4 d5",
  G: "bb4@2 bb4@2 [a4,d5]@3 d5 bb4@2 c5@2 d5@2 d4@2, g4 ~ g4@2", H: "g4 a4 c5 bb4 [b3,g4] [c4,a4]!2 [b3,g4]",
  I: "[b3,g4] [c4,a4] c4 b3 [c4,a4] [d4,bb4]!2 [c4,a4], ~ a4 ~@2", // Em F Gm F
  J: "[c4,a4] [d4,bb4] d4 c4 ~@2 a4!2, ~ bb4 [c4,f4]@2", K: "c5@4 ~ c5@3 bb4@4 c5@4 d5@4 d4@4 g4@4 a4@4",
  L: "c5@2 bb4@2 bb4@2 bb4@2 d5@2 d5@2 [g4,bb4,d5]@3 c5", M: "c5@16 bb4@14 a4 bb4", N: "c5!2 f5!2 a4@3 bb4, f4 d4",
  O: "c5 d4 bb4 a4 bb3@2 bb4 a4", P: "~@2 g3 a3 bb3 c4 d4 c4, g4 ~",
  Q: "[bb3,g4] [c4,a4]!2 [bb3,g4]!2 [c4,a4]!2 [bb3,g4]", R: "a3@2 a4 c5 c4 bb4 a4 a3, f4 ~",
  S: "[a3@2 a4 bb4 c5 c4 a4 ~ [c5,e5,g5]@8, f4@4 ~@3 g4@9]/2", T: "g5@3 f5 [f4,a4]@4, [a4,c5] ~",
  U: "g4 a4!2 g4!2 a4!2 bb4, [bb3,d4] ~", V: "[c4,a4]@2 ~ bb4 c5 c4 a4 g4, ~ a4 ~@2",
  W: "[[c5,e5]@8 ~@3 f5 [f4,a4]@4, g5@11 ~@5, ~@2 [bb4,d5] ~]/2", X: "~ a4 c5 g4 f4 a4 c5 g4, [a3,c4,f4] ~@3",
  Y: "f4 a4 c5 g4 f4 a4 c5 g4", Z: "f4 a4 c5 g4 f4 a4 c5 ~",
})).s("gm_music_box").gain(0.31)

// other · cello
const cello = note("<~@32 A B C D E F G H E I J K L@4 ~>".pickRestart({
  A: "a2@2 bb2 g2", B: "gb2", C: "g2 f2", D: "e2 c3", E: "f3 ~@31", F: "e3 c3", G: "f3 ~@15 d3@16",
  H: "g3@8 f3 ~@7 e3@16", I: "c3 bb2", J: "bb2 a2", K: "g3@2 e3 c3", L: "[f3@97 ~@31]/4",
})).s("gm_cello").gain(0.25)

// other · oboe
const oboe = note("<~@13 A B C D E F G H I J K L M N O P Q R C S T F U V W X Y Z AA@2 U AB@3 ~@2>".pickRestart({
  A: "~@2 bb4 c5 d5 d4 g4 a4", B: "c5 bb4 ~@6", C: "c5@16 bb4@14 a4 bb4", D: "g4@4 ~@3 bb4",
  E: "c5 d4 bb4 a4 bb3@2 bb4 a4", F: "~@2 g3 a3 bb3 c4 d4 c4, g4 ~", G: "bb3 ~@7", H: "~@2 a4 c5 c4 bb4 a4 a3, f4 ~",
  I: "a4!2 c5!2 bb4!3 c5", J: "d5 d4 g4 a4 c5 bb4!3", K: "d5@2 d5@2 d5@3 c5 c5@4 ~@2 c4@2, ~@3 c5",
  L: "f4 g4 bb4 a4 c5!2 f5!2", M: "bb4@2 bb4@2 d5@3 d5 bb4@2 c5@2 d5@2 d4@2", N: "g4 a4 c5 bb4 g4 a4!2 g4",
  O: "g4 a4 a4@2 a4 bb4!2 a4", P: "a4 bb4 bb4@2 ~@2 a4!2, ~ f4", Q: "c5@4 ~ c5@3 bb4@4 c5@4 d5@4 d4@4 g4@4 a4@4",
  R: "c5@2 bb4@2 bb4@2 bb4@2 d5@2 d5@2 d5@3 c5", S: "c5!2 f5!2 a4@3 bb4", T: "c5 d4 bb4 a4 g4@2 bb4 a4",
  U: "g4 a4!2 g4!2 a4!2 g4", V: "~@2 a4 bb4 c5 c4 a4 ~, f4 ~", W: "g5", X: "g5@3 f5 a4@4", Y: "g4 a4!2 g4!2 a4!2 bb4",
  Z: "a4@2 a4@2 c5 c4 a4 g4", AA: "[g5@11 f5 a4@4]/2", AB: "[f4@95 ~]/3",
})).s("gm_oboe").gain(0.12)

// chords · string ensemble 1 · "Strings"
const string_ensemble_1 = note("<~@20 A B C D E F G H I J K L M N O P Q@2 R S T U@2 P V@3 ~@2>".pickRestart({
  A: "~@2 a4 c5 c4 bb4 a4 a3", B: "a4!2 c5!2 [g4,bb4] bb4!2 c5, c4 ~", C: "d5 d4 g4 a4 c5 bb4!3",
  D: "d5@2 d5@2 [g4,bb4,d5]@3 c5 a4@2 bb4@2 ~@2 c4@2, ~@2 c5!2", E: "f4 g4 bb4 a4 c5!2 f5!2, ~@2 f4 d5",
  F: "bb4@2 bb4@2 [a4,d5]@3 d5 bb4@2 c5@2 d5@2 d4@2, g4 ~ g4@2", G: "g4 a4 c5 bb4 [b3,g4] [c4,a4]!2 [b3,g4]",
  H: "[b3,g4] [c4,a4] c4 b3 [c4,a4] [d4,bb4]!2 [c4,a4], ~ a4 ~@2", // Em F Gm F
  I: "[c4,a4] [d4,bb4] d4 c4 ~@2 a4!2, ~ bb4 [c4,f4]@2", J: "c5@4 ~ c5@3 bb4@4 c5@4 d5@4 d4@4 g4@4 a4@4",
  K: "c5@2 bb4@2 bb4@2 bb4@2 d5@2 d5@2 [g4,bb4,d5]@3 c5", L: "c5@16 bb4@14 a4 bb4", M: "c5!2 f5!2 a4@3 bb4, f4 d4",
  N: "c5 d4 bb4 a4 bb3@2 bb4 a4", O: "~@2 g3 a3 bb3 c4 d4 c4, g4 ~",
  P: "[bb3,g4] [c4,a4]!2 [bb3,g4]!2 [c4,a4]!2 [bb3,g4]", Q: "[a3@2 a4 bb4 c5 c4 a4 ~ [c5,e5,g5]@8, f4@4 ~@3 g4@9]/2",
  R: "g5@3 f5 [f4,a4]@4, [a4,c5] ~", S: "g4 a4!2 g4!2 a4!2 bb4, [bb3,d4] ~", T: "[c4,a4]@2 ~ bb4 c5 c4 a4 g4, ~ a4 ~@2",
  U: "[[c5,e5]@8 ~@3 f5 [f4,a4]@4, g5@11 ~@5, ~@2 [bb4,d5] ~]/2", V: "[[a3,c4,f4]@95 ~]/3",
})).s("gm_string_ensemble_1").gain(0.12)

// drums · shaker
const shaker = s("sh").struct("<[~@8 x!8] [x!16]!47 [x!2 ~@14]>").gain(0.4)

stack(music_box, cello, oboe, string_ensemble_1, shaker)

More by ABBA