Strudelify

Midnight Lady

Chris Norman

KeyD♭ majorTempo71 bpm
0:00/0:00
// Midnight Lady — Chris Norman
// 71 bpm, 4/4, key C# major. Source: midi.
// Generated by strudelify. One cycle = one bar.
// note: metre changes (4/4 at bar 1, 3/4 at bar 19, 4/4 at bar 19) are rendered on a constant 4/4 grid of one bar per cycle
// note: pitch bends are ignored
// note: duplicate parts dropped: ch 7 "FRETLESS" fretless bass (copy of ch 2 "PICK BASS" electric bass pick)
// note: Full arrangement: all 87 bars on a 16-step grid, each part at one level. Source detail keeps the original performance.
setcpm(71/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 · electric bass pick · "PICK BASS"
const bass = note(`<
  ~@30 A B C D E F G A H I J K D L B C I L M G N L M C N A B O D E N P Q D N C R S L M C I L T Q D I P Q S I U R V N@2 W
>`.pickRestart({
  A: "eb2@2 ~@4 db2 d2 eb2 eb2@2 ~@5", B: "f1@2 ~@4 eb2 e2 f1 f1@2 ~@5", C: "gb1@2 ~@4 e2 f1 gb1 gb1@2 ~@5",
  D: "ab1@2 ~@4 gb1 g1 ab1 ab1@2 ~@5", E: "ab1@2 ~@6 ab1@3 ~ ab1@4", F: "db2@3 ~@3 b1 c2 db2!2 ~@6",
  G: "gb1@2 ~@4 e2 f1 gb1!2 ~@6", H: "ab1 ~@5 gb1 g1 ab1!2 ~@6", I: "db2@2 ~@4 b1 c2 db2 db2@2 ~@5",
  J: "gb1 ~@5 e2 f1 gb1!2 ~@6", K: "eb2 ~@5 db2 d2 eb2!2 ~@6", L: "bb1@2 ~@4 ab1 a1 bb1 bb1@2 ~@5",
  M: "f1@3 ~@3 eb2 e2 f1 f1@2 ~@5", N: "db2@3 ~@3 b1 c2 db2 db2@2 ~@5", O: "gb1@3 ~@3 e2 f1 gb1 gb1@2 ~@5",
  P: "gb1@2 ~@4 e2 f1 gb1 gb1@3 ~@4", Q: "eb2@3 ~@3 db2 d2 eb2 eb2@3 ~@4", R: "eb2@3 ~@3 db2 d2 eb2 eb2@2 ~@5",
  S: "ab1@3 ~@3 gb1 g1 ab1 ab1@2 ~@5", T: "f1@3 ~@3 eb2 e2 f1 f1@3 ~@4", U: "gb1@3 ~@3 e2 f1 gb1 gb1@3 ~@4",
  V: "ab1@3 ~@3 gb1 g1 ab1 ab1@3 ~@4", W: "db2@13 ~@3",
})).s("gm_electric_bass_pick").gain(0.41)

// chords · piano · "A.PIANO 1"
const piano = note(`<
  ~@2 A B C D E F C G H I J K L I J K M N O P ~@13 Q R@2 S Q T U V W X O P ~@13 Y Z AA AB AC AD@2 AE ~@8 AF AG AH AI AJ
  AK@2 AL AM ~ AN
>`.pickRestart({
  A: "[db5,db6]@3 ~ [db5,db6]@8 [eb5,eb6]@4", B: "[f5,f6]@2 [c5,c6]@5 ~", C: "[ab4,ab5] [bb4,bb5]@2 [c5,c6]",
  D: "[db5,db6]@4 [ab4,ab5]@11 ~", E: "~ [db5,db6]@2 [eb5,eb6]", F: "[f5,f6]@4 [c5,c6]@9 ~@3",
  G: "[db5,db6]@3 ~ [ab4,ab5]@4 ~ f4 ab4 db5 f5 ab5 db6 f6", H: "bb4@2 c5@2 db5@2 db5 db5@6 ~ db5@2, ab6 ~@15",
  I: "eb5@3 db5 c5@4 f4@7 ~", J: "f4@2 ab4@2 bb4@2 bb4 bb4@6 ~ bb4@2", K: "c5@3 bb4 ab4@4 db4@6 ~@2",
  L: "bb4@2 c5@2 db5@2 db5 db5@6 ~ db5@2", M: "[db5,db6]@2 [eb5,eb6] f6, ~@6 f5 ~", N: "[c5,c6]@5 ~ [ab4,ab5]@2",
  O: "[bb4,bb5]@2 [c5,c6] [db5,db6]", P: "[ab4,ab5]@5 f4 ab4 db5 f5 ab5 db6 f6 ab6 ~@3",
  Q: "[f5,ab5,db6,f6]@6 ~@6 [f5,ab5,db6,f6]@3 ~", // Db
  R: "[[gb5,bb5,db6,gb6]@7 ~@5 [db6,gb6]@3 ~ [bb5,eb6,gb6]@5 ~@7 [gb5,bb5,eb6,gb6]@3 ~, ~@11 [gb5,bb5]@3 ~ gb5@2 ~@15]/2", // Gb Gb5 Ebm Gb
  S: "[ab5,c6,eb6,ab6]@6 ~@6 [ab5,c6,eb6,ab6]@3 ~", T: "[gb5,bb5,db6,gb6]@6 ~@6 [gb5,bb5,db6,gb6]@3 ~",
  U: "[gb5,bb5,eb6,gb6]@9 ~@3 [eb5,gb5,bb5,eb6]@3 ~", V: "[ab5,c6,eb6,ab6]@7 ~@9",
  W: "[db5,db6]@8 [eb5,eb6]@4 [f5,f6]@3 ~", X: "[c5,c6]@11 ~ [ab4,ab5]@4",
  Y: "[f5,ab5,db6,f6]@7 ~@5 [f5,ab5,db6,f6]@3 ~", Z: "[gb5,bb5,db6,gb6]@8 ~@4 [bb5,db6,gb6]@3 ~, ~@11 gb5@3 ~@2",
  AA: "[gb5,bb5,eb6,gb6]@10 ~ eb5 [gb5,bb5,eb6]@4", AB: "[ab5,c6,eb6,ab6]@5 ~@11",
  AC: "[f5,ab5,db6,f6]@9 ~@3 [db6,f6]@3 ~, ~@11 [f5,ab5]@4 ~", // Db Fm
  AD: "[[gb5,bb5,db6,gb6]@11 ~ [gb5,bb5,db6,gb6]@3 ~ [gb5,bb5,eb6]@10 ~ eb5 [gb5,bb5]@4, ~@15 eb5@10 ~@3 eb6@2 ~@2]/2", // Gb Ebm Gb
  AE: "[ab5,c6,eb6,ab6]@3 ~", AF: "[ab5,db6,f6]@9 ~@3 [f5,ab5,db6,f6]@4, f5 ~@15",
  AG: "[gb5,bb5,db6,gb6]@9 ~@3 [gb5,bb5,db6,gb6]@3 ~", AH: "[gb5,bb5,eb6,gb6]@8 ~@3 eb5 [gb5,bb5,eb6]@3 ~",
  AI: "[c6,eb6,ab6]@3 ~@5, ab5 ~@3", AJ: "[f5,ab5,db6,f6]@8 ~@4 [f5,ab5,db6,f6]@3 ~",
  AK: "[[gb5,bb5,db6,gb6]@8 ~@4 [gb5,bb5,db6,gb6]@3 ~ [gb5,bb5,eb6]@9 ~@2 eb5 [gb5,bb5,eb6]@3 ~, ~@15 eb5@10 ~@7]/2", // Gb Ebm
  AL: "[c6,eb6,ab6]@5 ~@3, ab5 ~@15", AM: "[f5,ab5,db6,f6]@5 ~@3", AN: "[f5,ab5,db6,f6] ~",
})).s("gm_piano").gain(0.24)

// chords · synth strings 2 · "SYN STR 2"
const synth_strings_2 = note(`<
  A@2 B@7 C@3 D@6 E F G@2 H@2 I J@3 K@2 L M N O@2 P N Q R P N S T U@2 N V@3 W@4 K@2 X M N Y@3 Z@2 AA@2 AB@2 T U@2 N AC@3
  AD AA@2 AB@2 AE@2 AF@2 AG@4
>`.pickRestart({
  A: "[~ [f2,f3]@7]/2", // F
  B: "[~@4 [bb3,db4]@16 [ab3,c4]@15 ~ [gb3,bb3,db4]@16 [ab3,db4,f4]@15 ~ [bb3,db4]@16 [ab3,c4]@16 [gb3,bb3,db4]@12, ~@4 f3@31 ~@17 f3@47 ~@13]/7", // Bbm Ab Gb Db Bbm Ab Gb
  C: "[~ ab3@4 bb3@4 [f3,ab3,c4]@3, ~ [f3,db4]@8 ~@3, ~@4 f4@11 ~@33]/3", // Fm Db
  D: "[~@4 [gb3,bb3]@16 ab3@16 bb3@16 [ab3,c4]@16 [gb3,bb3,db4]@16 [f3,ab3,db4]@9 ~@3, ~ db4@12 ~@11, ~@5 f3@12 ~@7]/6", // Gb Ab Gb Db
  E: "[f3,bb3,db4]", F: "[f3,ab3,c4]", G: "[[gb3,bb3] [f3,ab3], db4@31 ~]/2", H: "[[bb3,db4] [ab3,c4], f3@31 ~]/2",
  I: "[gb3,bb3,db4]", J: "[[ab3,db4,f4]@15 ~ [bb3,db4]@16 [ab3,c4]@16, f3@47 ~]/3", K: "[[gb3,bb3] [f3,ab3], db4]/2",
  L: "[gb3,bb3]@7 ~, eb4", M: "[f3,ab3,c4,f4]", N: "[gb3,bb3,db4,gb4]", O: "[[ab3,eb4,ab4], c4@15 ~]/2",
  P: "[f3,ab3,db4,f4]", Q: "[gb3,eb4,gb4], bb3@7 ~", R: "[ab3,c4,eb4,ab4]@15 ~", S: "[gb3,bb3,eb4,gb4]",
  T: "[ab3,c4,eb4,ab4]", U: "[[bb3,db4]@16 [ab3,c4]@15 ~, [f3,f4]]/2",
  V: "[[ab3,db4,f4] [bb3,db4] [ab3,c4], f3@47 ~]/3", W: "[[gb3,bb3] ab3 bb3 [ab3,c4], db4@3 ~, ~@16 f3@47 ~]/4",
  X: "[eb3,gb3,bb3,eb4]", Y: "[[c4,eb4,ab4]@2 [db4,f4], ab3, ~@16 f3@7 ~]/3", Z: "[db4 eb4, [gb3,bb3,gb4]]/2",
  AA: "[[c4,eb4,ab4] [f3,db4,f4], ab3@31 ~]/2", AB: "[db4@16 eb4@15 ~, [gb3,bb3,gb4]]/2",
  AC: "[ab3@15 ~ bb3@16 [ab3,c4]@16, [f3,f4], db4@2 ~]/3", AD: "[gb3,bb3,db4,eb4]",
  AE: "[[c4,eb4,ab4]@16 [f3,db4,f4]@15 ~, ab3]/2", AF: "[[bb3,db4,gb4] [bb3,eb4,gb4], gb3]/2",
  AG: "[[c4,eb4,ab4]@16 [f3,db4,f4]@45 ~@3, ab3@61 ~@3]/4", // Ab Db
})).s("gm_synth_strings_2").gain(0.31)

// other · acoustic guitar steel · "STEEL GTR"
const acoustic_guitar_steel = note(`<
  ~@22 A B C D A B C D E B C F G D C H F D C H F A I C J A B C D A B C D E B C F K D C H F D C H F A B C D A B C L D C H
  F D C H F D@2 M
>`.pickRestart({
  A: "db4 f3 bb3 f3 db4 f3 bb3 f3", B: "c4 f3 ab3 f3 c4 f3 ab3 f3", C: "db4 gb3 bb3 gb3 db4 gb3 bb3 gb3",
  D: "db4 f3 ab3 f3 db4 f3 ab3 f3", E: "bb3 eb3 gb3 eb3 bb3 eb3 gb3 eb3", F: "eb4 ab3 c4 ab3 eb4 ab3 c4 ab3",
  G: "eb4@2 ab3@2 c4@2 ab3@2 f4@2 ab3@2 eb4@2 ab3 ~", H: "eb4 gb3 bb3 gb3 eb4 gb3 bb3 gb3",
  I: "c4 f3 ab3 f3 c4 bb3 ab3 f3", J: "db4 f3 ab3 f3 db4 f3 ab3 ~", K: "eb4@2 ab3@2 c4@2 ab3@2 eb4@2 ab3@3 ~ ab3@2",
  L: "eb4 ab3 c4 ab3 f4 ab3 eb4 ab3", M: "db4@7 ~@9",
})).s("gm_acoustic_guitar_steel").gain(0.31).pan(0.2)

// drums · kick
const kick = s("bd").struct("<~@30 [x ~@2 x!2 ~@3]!4 x [x ~@2 x!2 ~@3]!24 x [x ~@2 x!2 ~@3]!26 x>").gain(0.51)

// drums · rim
const rim = s("rim").struct("<~@30 [~ x ~ x]!4 ~@9 [~ x ~ x]!12 ~@32>").gain(0.51)

// drums · snare
const snare = s("sd").struct("<~@35 [~ x ~ x]!8 ~@12 [~ x ~ x]!4 ~ [~ x ~ x]!26 ~>").gain(0.51)

// drums · low tom
const low_tom = s("lt").struct("<~@35 x ~@10 [~ x] ~@13 x ~@26>").gain(0.46)

// drums · hihat
const hihat = s("hh").struct("<~@30 [x!8]!4 x [x!8]!24 x [x!8]!26 x>").gain(0.31)

// drums · mid tom
const mid_tom = s("mt").struct("<~@34 [~@8 x ~@3 x ~@2 x] ~@24 [~@8 x ~@3 x ~@2 x] ~@27>").gain(0.46)

// drums · high tom
const high_tom = s("ht").struct("<~@34 [~ x ~@2 x ~@11] ~@11 [~@3 x ~@4] ~@12 [x!2 ~@2 x ~@11] ~@27>").gain(0.46)

// drums · crash
const crash = s("cr").struct("<~@35 x ~@24 x ~@15 x ~@9 x>").gain(0.46)

// drums · tambourine
const tambourine = s("tb").struct("<~@4 A@5 ~@5 B A@2 ~ C@3 ~@4 D C@4 D@4 ~@16 D@9 ~ E@26 ~>".pickRestart({
  A: "~ x", B: "x!2", C: "~ x ~@2", D: "~@3 x", E: "~ x ~ x",
})).gain(0.46)

// drums · cabasa
const cabasa = s("cabasa:4").struct(`<
  ~@30 A B C B D C B@2 A C A C E ~@12 C B F B D C A C B C B C A C A C@2 G C@2 H F B A B@2 A@5 ~
>`.pickRestart({
  A: "x ~ x!3 ~ x!3 ~ x!3 ~ x ~", B: "x ~ x!3 ~ x!3 ~ x ~ x ~ x!2", C: "x ~ x!3 ~ x!3 ~ x!3 ~ x!2", D: "x",
  E: "x ~ x!3 ~ x ~ x ~ x!3 ~ x ~", F: "x ~ x ~ x ~ x!3 ~ x!3 ~ x!2", G: "x ~ x!3 ~ x ~ x ~ x!3 ~ x!2",
  H: "~@2 x!3 ~ x!3 ~ x!3 ~ x!2",
})).gain(1.56)

// drums · shaker
const shaker = s("sh").struct(`<
  ~@30 A B C B D C B@2 A C A C E ~@12 C B F B D C A C B C B C A C A C@2 G C@2 H F B A B@2 A@5 ~
>`.pickRestart({
  A: "x ~ x!3 ~ x!3 ~ x!3 ~ x ~", B: "x ~ x!3 ~ x!3 ~ x ~ x ~ x!2", C: "x ~ x!3 ~ x!3 ~ x!3 ~ x!2", D: "x",
  E: "x ~ x!3 ~ x ~ x ~ x!3 ~ x ~", F: "x ~ x ~ x ~ x!3 ~ x!3 ~ x!2", G: "x ~ x!3 ~ x ~ x ~ x!3 ~ x!2",
  H: "~@2 x!3 ~ x!3 ~ x!3 ~ x!2",
})).gain(0.26)

stack(
  bass, piano, synth_strings_2, acoustic_guitar_steel, kick, rim, snare, low_tom, hihat, mid_tom, high_tom, crash,
  tambourine, cabasa, shaker
)