Strudelify
The Force, Part I cover art

2004 · So Young but So Cold: Underground French Music 1977-1983

The Force, Part I

Droids

KeyE minorTempo138 bpm
0:00/0:00
// The Force, Part I — Droids
// 138 bpm, 4/4, key E minor. Source: midi.
// Generated by strudelify. One cycle = one bar.
// note: Full arrangement: all 217 bars on a 16-step grid, each part at one level. Source detail keeps the original performance.
setcpm(138/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, A@4 for four bars: edit a riff to change every repeat.

// bass · synth bass 1 · "SYNTH BASS"
const bass = note(`<
  A@2 B C A C D C@3 B@2 E@2 B@6 E@2 B@2 F G B@2 H I B@6 E@2 B@6 E@2 B@2 F I B@2 F I B@10 F J K E B@4 F J K E B@6 F@4 L@2
  F@6 L@2 F@2 E M F@2 E M F@2 B@4 E@2 B@6 E@2 B@18 N O@7 P O Q@2 P@4 Q@2 P@4 Q@2 R@2 S@2 T@4 U@8 V@2 U@6 V@2 U@2 W X Y
  W@2 X Y W U@4 V@2 U@10 Z ~@2
>`.pickRestart({
  A: "e2 b2 e2 b2 e2 b2 e2 b2", B: "e2 ~ b2 ~ e2 ~ b2 ~ e2 ~ b2 ~ e2 ~ b2 ~",
  C: "e2@2 b2 ~ e2@2 b2 ~ e2@2 b2 ~ e2@2 b2 ~", D: "e2@2 b2@2 e2@2 b2@2 e2@2 b2@2 e2@2 b2 ~",
  E: "d2 ~ a2 ~ d2 ~ a2 ~ d2 ~ a2 ~ d2 ~ a2 ~", F: "a1 ~ e2 ~ a1 ~ e2 ~ a1 ~ e2 ~ a1 ~ e2 ~",
  G: "c2 ~ g2 ~ c2@2 g2 ~ b1@2 f#2 ~ b1 ~ f#2 ~", H: "a1 ~ e2 ~ a1@2 e2 ~ a1@2 e2 ~ a1 ~ e2 ~",
  I: "c2 ~ g2 ~ c2 ~ g2 ~ b1 ~ f#2 ~ b1 ~ f#2 ~", J: "b1 ~ f#2 ~ b1 ~ f#2 ~ b1 ~ f#2 ~ b1 ~ f#2 ~",
  K: "c2 ~ g2 ~ c2 ~ g2 ~ c2 ~ g2 ~ c2 ~ g2 ~", L: "g1 ~ d2 ~ g1 ~ d2 ~ g1 ~ d2 ~ g1 ~ d2 ~",
  M: "f2 ~ c3 ~ f2 ~ c3 ~ e2 ~ b2 ~ e2 ~ b2 ~", N: "a3@2 a4@2 a3@2 a4@2 a3@2 a4 ~ a3@2 a4 ~",
  O: "a3@2 a4 ~ a3@2 a4 ~ a3@2 a4 ~ a3@2 a4 ~", P: "a3 ~ a4 ~ a3 ~ a4 ~ a3 ~ a4 ~ a3 ~ a4 ~",
  Q: "g3 ~ g4 ~ g3 ~ g4 ~ g3 ~ g4 ~ g3 ~ g4 ~", R: "e3 ~ e4 ~ e3 ~ e4 ~ e3 ~ e4 ~ e3 ~ e4 ~",
  S: "d3 ~ d4 ~ d3 ~ d4 ~ d3 ~ d4 ~ d3 ~ d4 ~", T: "a2 ~ a3 ~ a2 ~ a3 ~ a2 ~ a3 ~ a2 ~ a3 ~",
  U: "a2 ~ e3 ~ a2 ~ e3 ~ a2 ~ e3 ~ a2 ~ e3 ~", V: "g2 ~ d3 ~ g2 ~ d3 ~ g2 ~ d3 ~ g2 ~ d3 ~",
  W: "d3 ~ a3 ~ d3 ~ a3 ~ d3 ~ a3 ~ d3 ~ a3 ~", X: "f3 ~ c4 ~ f3 ~ c4 ~ f3 ~ c4 ~ f3 ~ c4 ~",
  Y: "d#3 ~ a#3 ~ d#3 ~ a#3 ~ d#3 ~ a#3 ~ d#3 ~ a#3 ~", Z: "a2 ~@15",
})).s("gm_synth_bass_1").gain(0.35).pan(0.2)

// bass · synth bass 2 · "SYNTH BASS"
const bass_2 = note(`<
  A B A B@5 C B@3 D@2 B@6 D@2 B@2 E F B@2 E F B@6 D@2 B@6 D@2 B@2 E F B@2 E F B@10 E G H I B@4 E G H I B@6 E@4 J@2 E@6
  J@2 E@2 I K L E I K E@2 B@4 D@2 B@6 D@2 B@18 ~@32 E@8 J@2 E@6 J@2 E@2 I M N I@2 M N I E@4 J@2 E@10 O ~@2
>`.pickRestart({
  A: "e1@2 e2 ~ e1@2 e2 ~ e1@2 e2 ~ e1@2 e2 ~", B: "e1 ~ e2 ~ e1 ~ e2 ~ e1 ~ e2 ~ e1 ~ e2 ~",
  C: "e1 ~ e2 ~ e1 ~ e2 ~ e1 ~ e2 ~ e1@2 e2 ~", D: "d1 ~ d2 ~ d1 ~ d2 ~ d1 ~ d2 ~ d1 ~ d2 ~",
  E: "a1 ~ a2 ~ a1 ~ a2 ~ a1 ~ a2 ~ a1 ~ a2 ~", F: "c2 ~ c3 ~ c2 ~ c3 ~ b1 ~ b2 ~ b1 ~ b2 ~",
  G: "b1 ~ b2 ~ b1 ~ b2 ~ b1 ~ b2 ~ b1 ~ b2 ~", H: "c2 ~ c3 ~ c2 ~ c3 ~ c2 ~ c3 ~ c2 ~ c3 ~",
  I: "d2 ~ d3 ~ d2 ~ d3 ~ d2 ~ d3 ~ d2 ~ d3 ~", J: "g1 ~ g2 ~ g1 ~ g2 ~ g1 ~ g2 ~ g1 ~ g2 ~",
  K: "f2 ~ f3 ~ f2@2 f3 ~ e2 ~ e3 ~ e2@2 e3 ~", L: "a1@2 a2 ~ a1@2 a2 ~ a1@2 a2 ~ a1@2 a2 ~",
  M: "f2 ~ f3 ~ f2 ~ f3 ~ f2 ~ f3 ~ f2 ~ f3 ~", N: "d#2 ~ d#3 ~ d#2 ~ d#3 ~ d#2 ~ d#3 ~ d#2 ~ d#3 ~", O: "a1 ~@7",
})).s("gm_synth_bass_2").gain(0.45).pan(0.7)

// other · clavinet
const clavinet = note(`<
  ~@64 A B C D E@2 F G A B C H E@5 I ~@28 J ~@11 K@8 L K@5 M K N ~@31 O P Q R S T R U V@2 Q W X R Q Y Z AA AB@2 AC AD AE
  AF AG AH AI AJ Q@2 AK AB Z AL AB@4 AM AB AN AB AM AB ~@3
>`.pickRestart({
  A: "a2@2 a3 e3 a2@2 a3 e3 a2@2 a3 e3 a2 e3 a3 e3", B: "b2@2 b3 f#3 b2@2 b3 f#3 b2@2 b3 f#3 b2 f#3 ~ f#3, ~@7 b3",
  C: "c3@2 c4 g3 c3@2 c4 g3 c3@2 c4 g3 ~ g3 c4 g3, ~@6 c3 ~",
  D: "d3@2 d4 a3 d3@2 d4 a3 d3@2 d4 a3 ~ a3 d4 a3, ~@12 d3@3 ~", E: "e3@2 e4 b3 e3@2 e4 b3 e3@2 e4 b3 e3 b3 e4 b3",
  F: "e3@2 e4 b3 e3@2 e4 b3 e3@2 e4 b3 ~ b3 e4 b3, ~@6 e3 ~",
  G: "e3@2 e4 b3 e3@2 ~ b3 e3@2 ~ b3 e3 ~ b3 e3, ~@6 e4@2 ~@2 e4@2 ~ e4@2 ~",
  H: "d3@2 d4 a3 d3@2 d4 a3 d3@2 d4 a3 d3 a3 d4 a3", I: "e3@2 e4 b3 e3@2 e4 b3 e3@2 e4 b3 e3 b3 e4 ~", J: "~@15 b2",
  K: "e2@2 e3 b2 e2@2 e3 b2 e2@2 e3 b2 e2 b2 e3 b2", L: "e2@2 e3 b2 e2@2 e3 b2 e2@2 e3 b2 e2 e3 b2@2",
  M: "e2@2 e3 b2 e2 ~ e3 b2 e2@2 e3 b2 e2@2 e3 b2", N: "e2 ~@7", O: "a1@2 a2 ~ g2 ~ a2 ~ a1 ~ a2 a1 ~ a1 g2 a2",
  P: "a1 ~ a2 ~ [a1,g2] ~ a2 ~ a1 ~ a2 a1 ~ a1 g2 a2", Q: "a1 ~ a2 ~ g2 ~ a2 ~ a1 ~ a2 a1 ~ a1 g2 a2",
  R: "a1 ~ a2 ~ a1 ~ a2 ~ a1 ~ a2 a1 ~ a1 g2 a2", S: "a1 ~ a2 a1 g2 ~ a2 ~ a1 ~ a2 a1 ~ a1 g2 a2",
  T: "a1 ~ a2 ~ [a1,b1,g2] ~ a2 ~ a1 ~ a2 a1 ~ a1 g2 a2", U: "a1 ~ a2 ~ a1 ~ a2 ~ a1 a2 ~ a1 g2 a1 a2 ~",
  V: "g1 ~ g2 ~ g1 ~ g2 ~ g1 ~ g2 g1 ~ g1 g2!2", W: "a1 ~ a2 ~ g2 ~ a2 ~ a1 a2 ~ a1 g2 a1 a2!2",
  X: "a1 ~ a2 ~ [a1,g2] ~ a2 ~@3 a2 a1 g2 a1 a2!2", Y: "a1 ~ a2 ~@3 a2 ~ a1 ~ a2 ~@2 a1 g2 a2",
  Z: "g1 ~ g2 ~@3 g2 ~ g1 ~ g2 g1 ~ g1 g2!2", AA: "g1 ~ g2 ~@3 g2 ~ [g1,a1] ~ g2 g1 ~ g1 g2!2",
  AB: "a1 ~ a2 ~@3 a2 ~ a1 ~ a2 a1 ~ a1 g2 a2", AC: "d2 ~ d3 ~ d2 ~ d3 ~ d2 ~ d3 d2 ~ d2 c3 d3",
  AD: "f2 ~ f3 ~ f2 ~ f3 ~ f2 ~ f3 f2 ~ f2 f3!2", AE: "d#2 ~ d#3 ~ d#2 ~ d#3 ~ d#2 ~ d#3 d#2 ~ d#2 d#3!2",
  AF: "d2 ~ d3 ~ d2 ~ d3 ~ d2 ~ d3 d2 c3 d2 d3 ~", AG: "d2 ~ d3 ~@3 d3 ~ d2 ~ d3 d2 ~ d2 d3!2",
  AH: "f2 ~ f3 ~@3 f3 ~ f2 ~ f3 f2 ~ f2 f3!2", AI: "d#2 ~ d#3 ~@3 d#3 ~ d#2 ~ d#3 d#2 ~ d#2 d#3!2",
  AJ: "~@2 d3 ~@3 d3 ~ d2 ~ d3 d2 ~ d2 d3!2", AK: "g1 ~ g2 ~@3 a2 ~ a1 ~ a2 a1 g2 ~ a2 ~",
  AL: "~ g1 g2 ~@3 g2 ~ g1 ~ g2 g1 ~ g1 g2!2", AM: "a1 ~ a2 ~@3 a2 ~ a1 ~ a2 ~@3 a2 ~",
  AN: "a1 ~ a2 ~ a1 ~ a2 ~ a1 ~ a2 ~@3 a2 ~",
})).s("gm_clavinet").gain(0.4).pan(0.1)

// other · pad poly · "POLY SYNTH"
const pad_poly = note(`<
  ~@64 A B C D E@4 A B C D F@6 ~@16 D G H@2 D G I@2 ~@23 J K@4 L@3 ~@15 H@2 M@2 H@2 N@2 M@2 O@2 P@2 Q@2 H@2 ~@20 R S T
  U@2 S T D V@2 ~@8 W@2 Q@2 X@2 H@2 ~
>`.pickRestart({
  A: "a2", B: "b2", C: "c3@15 ~", D: "d3@15 ~", E: "[e3@57 ~@7]/4", F: "[e3@83 ~@13]/6", G: "f3@7 ~ e3@8", H: "a2/2",
  I: "[a3@31 ~]/2", J: "~@3 d3", K: "[e3 e2]/4", L: "[e3@11 ~@5]/3", M: "[g2@31 ~]/2", N: "[g2@4 a2@27 ~]/2",
  O: "[e2@15 ~]/2", P: "[d2@29 ~ g2@2]/2", Q: "[a2@29 ~ g2@2]/2", R: "d3", S: "f3", T: "d#3", U: "d3/2",
  V: "[a2@5 ~@3]/2", W: "[a2@27 ~@3 g2@2]/2", X: "[a2@27 ~@3 g2 ~]/2",
})).s("gm_pad_poly").gain(0.5).pan(0.9)

// chords · synth strings 2 · "SYN STRING"
const synth_strings_2 = note(`<
  ~@8 A@6 B@8 C@3 D@4 E@8 F@7 G@5 H@4 I J@8 ~ K@3 L@7 M@2 N@6 O@4 P@8 Q@5 R S@4 T@6 U@2 V@8 W@4 ~@17 X@8 Y@7 Z@5 AA@5
  AB@8 ~@5 AC@7 AD@5 AE@5 AF@2 AG@7 X@8 ~@5
>`.pickRestart({
  A: "[[g3,b3]@61 ~@3 f#3@31 ~, e4@63 [a3,d4]@32 ~]/6", B: "[[b3,e4]@95 ~ f#3@31 ~, g3@93 ~@2 [a3,d4]@32 ~]/8",
  C: "[[g3,b3]@30 ~ c4@17, e4, ~@31 a3@15 ~@2]/3", // G
  D: "[g3@7 ~ d4@8 g3@31 ~ [a3,c4]@15 g3, ~ b3@5 ~@2, ~@4 f#3@3 ~ e4@24]/4", // Am
  E: "[~@8 [f#3,d4]@8 e4@95 [f#3,a3,d4]@17, ~ b3@13 ~@2, ~@16 g3@93 ~@19]/8", F: "[~@16 [g3,e4]@95 ~, ~@15 b3@96 ~]/7",
  G: "[[f#3,a3,d4]@31 [g3,b3]@30 ~@2 [a3,c4]@15 ~ [g3,c4,e4], ~@31 e4@47 ~@2]/5", // D G Am C
  H: "[~@8 f#3@7 ~ [g3,e4]@31 ~ c4@15 ~, ~@7 b3@39 ~ [a3,e4]@15 ~@2, ~@7 d4@8 ~@49]/4", // C A5
  I: "[c4,e4]@8 [f#3,b3,d4]@7 ~, g3@3 ~@5", J: "[g3,b3,e4]/8",
  K: "[~@16 c4@15 ~ f#3@15 e4, ~@15 [a3,e4]@15 ~ [b3,d4]@16 ~]/3", // A5 Bm
  L: "[[g3,c4]@15 [a3,d4]@16 ~ g3@61 ~@2 [a3,c4]@15 ~ [b3,d4], ~@15 f#3@14 ~@2 e4@80 ~, ~@31 b3@61 ~@20]/7", // C5 D5 Am Bm
  M: "[f#3@15 [c4,e4]@16 f#4, ~@15 g3@14 ~@3]/2", N: "[d4@15 ~ [g3,b3]@80, a3@13 ~@2 e4@81]/6",
  O: "[~@15 [a3,c4,e4]@49]/4", P: "[~@15 [b3,d4]@32 ~ [a3,c4]@80, ~@15 g3@31 ~ e4@81]/8",
  Q: "[~@15 [b3,d4]@32 [a3,c4,e4]@32 ~, ~@3 g3@6 ~@7]/5", R: "[a3,d4,f4]",
  S: "[[a3,c4,f4]@7 ~ [g3,b3]@8 [a3,c4]@31 ~ a3@15 [a3,c4,f4], ~@8 e4@39 [d4,f4]@16 ~]/4", // F G Am F Dm
  T: "[~@8 [g3,b3]@7 ~ a3@30 ~ [g3,b3]@49, ~ e4@11, ~@15 c4@32 ~@49]/6", U: "[~@15 [f#3,a3,d4]@17]/2",
  V: "[~@15 [g3,b3,e4]@96 ~ f#3@16, ~@111 [a3,d4]@17]/8", W: "[~@15 [g3,b3]@35 ~@14, ~@15 e4@41 ~@8]/4",
  X: "[a3,c4,e4]/8", Y: "[[b3,d4]@31 ~ e4@63 [g3,b3,d4]@17, g3@30 ~ c4@64 ~@17, ~@16 a3@31 ~@9]/7",
  Z: "[~@15 [a3,c4,e4]@64 ~]/5", AA: "[[g3,b3]@30 ~ [g3,b3]@31 ~ [f3,a3,d4]@17, d4@31 e4@32 ~@17]/5",
  AB: "[~@15 [a3,c4,e4]@113]/8", AC: "[[g3,b3,d4]@31 ~ [a3,c4]@80, ~@31 e4@81]/7",
  AD: "[~@15 [b3,d4]@32 ~ c4@31 ~, ~@15 g3@30 ~@2 [a3,e4]@31 ~@2]/5", // Bm A5
  AE: "[d4@16 c4@14 ~@2 f#3@15 ~ f3@30 ~@2, f4@31 a#3@13 ~@3 d4@32 ~, a3@30 ~ d#4@16 a3@30 ~@3]/5",
  AF: "[[a3,c4]@14 ~@2 f#3@15 a3, f4@15 d#4@16 ~, ~@4 a#3@3 ~]/2", // Am
  AG: "[d4@15 ~@65 b3@32, f3@14 ~ a3@63 ~ d4@32 ~, ~@8 [c4,e4]@32 g3@15 ~]/7", // C
})).s("gm_synth_strings_2").gain(0.35).pan(0.6)

// drums · kick
const kick = s("bd").struct("<~@4 A B A B C@106 D C@23 ~@34 E C@41 ~@3>".pickRestart({
  A: "x!2 ~@6", B: "x", C: "x!4", D: "x ~ x ~ x!2 ~@2", E: "x!2",
})).gain(0.8)

// drums · snare
const snare = s("sd").struct("<~@82 [~ x ~ x]!56 ~@36 [~ x ~ x]!40 ~@3>").gain(0.8)

// drums · hihat
const hihat = s("hh").struct("<~@32 A@24 ~@8 A@74 ~@4 B@32 A@39 C ~@3>".pickRestart({
  A: "x!8", B: "x!16", C: "x!7 ~",
})).gain(0.56)

stack(bass, bass_2, clavinet, pad_poly, synth_strings_2, kick, snare, hihat)