Strudelify
When Doves Cry cover art

Purple Rain

When Doves Cry

Prince

KeyA minorTempo125 bpm
0:00/0:00
// When Doves Cry — Prince
// 125 bpm, 4/4, key A minor. Source: midi.
// Generated by strudelify. One cycle = one bar.
// note: Full arrangement: all 179 bars on a 16-step grid, each part at one level; ghost notes are separate "_soft" parts. Source detail keeps the original performance.
setcpm(125/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 · piano
const piano = note(`<
  ~@7 A B C D A B C D ~@16 E F E F E G E G E G E H E H I ~ J K L M N O P D Q R Q R Q R S T E U E G E H E F E H V G E W I
  X Y Z AA AB N AC N AD ~@24 P D P D P D P D P D P D P D P D P D P D P D P D P D P D P D P D P D P D ~@12 AE AF AG AH AI
  AJ AK AG AL AG@2 AH@2 AM ~@6
>`.pickRestart({
  A: "[a4,c5,f5]@2 ~@4 [a4,c5,e5] ~ [g4,b4,d5]@2 ~@6", B: "[a4,c5,f5]@2 ~ [a4,c5,e5]@2 ~ [a4,c5,e5] ~ [g4,b4,d5] ~@7",
  C: "[a4,c5,f5]@2 ~@2 [a4,c5,e5] ~ [a4,c5,e5] ~ [g4,b4,d5]@2 ~@6", // F Am G
  D: "[a4,c5,f5]@2 ~ [a4,c5,e5]@2 ~ [a4,c5,e5] ~ [g4,b4,d5]@2 ~@6", E: "a5 ~ e5 ~ g5 ~ e5 ~ a5 ~ e5 ~ g5 ~ e5 ~",
  F: "a5 ~ e5@2 g5 ~ e5 ~@3 e5 ~@3 e5 ~", G: "a5 ~ e5@2 g5@2 e5 ~@3 e5 ~@3 e5 ~",
  H: "a5 ~ e5 ~ g5 ~ e5 ~@3 e5 ~@3 e5 ~", I: "a5 ~ e5 ~ g5 ~ e5 ~ a5 ~ e5@2 g5 ~ e5 ~",
  J: "[c5,f5]@2 ~@4 [a4,c5,e5] ~ [g4,b4,d5]@2 ~@6, a4 ~@15", // F5 Am G
  K: "[a4,c5,f5] ~@2 [c5,e5] ~@2 [a4,c5,e5] ~ [g4,b4,d5]@2 ~@6, ~@3 a4@2 ~@11", // F C Am G
  L: "[a4,c5,f5]@2 ~@2 [a4,c5,e5] ~ [a4,c5,e5] ~ [g4,b4,d5] ~@7", // F Am G
  M: "[a4,f5]@2 ~ [a4,c5,e5] ~@2 [a4,c5,e5] ~ [g4,b4,d5] ~@7, c5 ~@15", N: "[a4,c5,f5] ~@5 [a4,c5,e5] ~ [g4,b4,d5] ~@7",
  O: "[a4,c5,f5]@2 ~ [a4,c5,e5] ~@2 [a4,c5,e5] ~ [b4,d5]@2 ~@6, ~@8 g4 ~@7", // F Am Bm
  P: "[a4,c5] ~@5 [a4,c5,e5] ~ [g4,b4] ~@7, f5 ~@3 d5 ~@3", Q: "a4 ~ c5 ~ e5 ~ a4 ~ c5 ~ e5 ~ a4 ~ c5 ~",
  R: "e5 ~ a4 ~ c5 ~ e5 ~ c5 ~@7", S: "a4 ~ c5 ~ e5 ~ a4@2 c5 ~ e5@2 c5 ~@3",
  T: "~@2 g5 ~ f#5 ~ f5 ~ e5 ~ d#5 ~ d5 ~ c#5 ~", U: "a5 ~ e5 ~ g5@2 e5 ~@3 e5 ~@3 e5 ~",
  V: "a5 ~ e5 ~ g5 ~ e5 ~ a5 ~ e5 ~ g5@2 e5 ~", W: "a5 ~ e5 ~ g5 ~ e5@2 ~@2 e5@2 ~@2 e5 ~",
  X: "a5 ~ e5 ~ g5@2 e5@2 ~@2 e5 ~@3 e5 ~", Y: "[a4,f5]@2 ~@3 [a4,c5,e5] ~@2 [g4,b4,d5] ~@7, c5 ~@15",
  Z: "[a4,c5,f5]@2 ~ [c5,e5] ~@2 [a4,c5,e5] ~ [g4,b4,d5] ~@7, ~@3 a4@2 ~@11", // F C Am G
  AA: "[a4,c5,f5]@2 ~@2 [a4,c5,e5] ~ [a4,c5,e5] ~ [g4,b4] ~@7, ~@4 d5 ~@3", // F Am G
  AB: "[c5,f5] ~@2 [a4,c5,e5] ~@2 [a4,c5,e5] ~ [g4,b4,d5] ~@7, a4 ~@7", // F5 Am G
  AC: "[a4,c5,f5] ~@2 [a4,c5,e5] ~@2 [a4,c5,e5] ~ [g4,b4,d5] ~@7", // F Am G
  AD: "[a4,f5]@2 ~ [a4,c5,e5] ~@2 [a4,c5,e5] ~ [g4,b4,d5]@2 ~@6, c5 ~@15", // Dm Am G
  AE: "[c5,f5] ~@5 [a4,c5,e5] ~ [g4,b4,d5] ~@7, a4 ~@7", // F5 Am G
  AF: "[a4,c5,f5]@2 ~ [a4,c5,e5]@2 [a4,c5,e5] ~@2 [g4,b4,d5] ~ e5@2 g5@2 e5 ~", // F Am G
  AG: "a5@2 e5@2 g5@2 e5 ~ a5@2 e5@2 g5@2 e5 ~", AH: "a5@2 e5@2 g5@2 e5 ~ a5 ~ e5@2 g5@2 e5 ~",
  AI: "a5@2 e5@2 g5@2 e5 ~ a5@2 e5@2 g5@2 e5@2", AJ: "a5@2 e5 ~ g5@2 e5 ~ a5@2 e5@2 g5@2 e5 ~",
  AK: "a5 ~ e5@2 g5@2 e5 ~ a5@2 e5@2 g5@2 e5 ~", AL: "a5 ~ e5@2 g5@2 e5 ~ a5 ~ e5@2 g5@2 e5 ~",
  AM: "a5 ~ e5 ~ g5@2 e5 ~ a5@2 e5@2 g5@2 e5 ~",
})).s("gm_piano").gain(0.41)

// bass · fretless bass · "Bass"
const bass = note(`<
  ~@15 A@2 B C D@2 E F G H I C H@2 I C H J I C H@2 I C H@2 I C H@2 I C ~@8 D K B F G H L C M@2 N C H@2 I C H@2 E C H@2 I
  O ~@8 P@2 Q R P@2 Q R P@2 Q R P@2 Q R ~@44 P Q@2 R P Q@2 R P Q@2 R P Q@2 R P Q@2 R P Q@2 R P Q@2 R ~@4
>`.pickRestart({
  A: "a1 ~@5 a1 ~@9, a2@11 ~@5", B: "g1@3 ~@3 g1@3 ~@7, g2@11 ~@5", C: "g#1 ~@2 g#1 ~@4, g#2@11 ~@5",
  D: "a1@3 ~@3 a1@3 ~@7, a2@11 ~@5", E: "g1@2 ~@4 g1@3 ~@7, g2@11 ~@5", F: "g#1@2 ~@4 g#1@3 ~@7, g#2@11 ~@5",
  G: "a1@3 ~@3 a1@2 ~@8, a2@11 ~@5", H: "a1 ~@2 a1 ~@4, a2@11 ~@5", I: "g1 ~@2 g1 ~@4, g2@11 ~@5",
  J: "a1@2 ~@3 a1@2 ~@9, a2@11 ~@5", K: "a1@3 ~@2 a1@3 ~@8, a2@11 ~@5", L: "g1@2 ~@6 g1 ~@7, g2@11 ~@5",
  M: "a1@2 ~@4 a1@3 ~@7, a2@11 ~@5", N: "g1@3 ~@3 g1@2 ~@8, g2@11 ~@5", O: "g#1@2 ~@4 g#1 ~@9, g#2@11 ~@5",
  P: "a2@11 ~@5", Q: "g2@11 ~@5", R: "g#2@11 ~@5",
})).s("gm_fretless_bass").gain(0.36)

// chords · drawbar organ · "Organ"
const drawbar_organ = note(`<
  ~@87 A B C D A B C D A B C D ~@4 A B C E A B C E ~@24 F@8 ~@4 G H I J K L M N O P Q R S T U V W T X Y Z AA AB AC AD AE
  AF AG ~@4
>`.pickRestart({
  A: "[c4,e4,a4]@11 ~@5", B: "[a3,d4,f4,a4]@11 ~@5", C: "[b3,d4,g4]@11 ~@5", D: "[c4,e4,g#4]@11 ~@5",
  E: "c4@5 ~@3 b3@5 ~@3, [e4,g#4]@11 ~@5", F: "[a4,a5]/8",
  G: "~@2 [e4,a4,c5,e5]@3 ~ [e4,a4,c5,e5]@3 ~ [e4,a4,c5,e5]@2 ~@2 [e4,a4,c5,e5]@2", // Am
  H: "~ [d4,f4,a4,d5] ~ [d4,f4,a4,d5] ~ [d4,f4,a4,d5] ~ [d4,f4,a4,d5]", // Dm
  I: "~@2 [d4,g4,b4,d5]@3 ~ [d4,g4,b4,d5]@3 ~ [d4,g4,b4,d5]@3 ~ [d4,g4,b4]@2, ~@14 d5 ~", // G
  J: "~ [c4,e4,g4] ~ [b3,e4,g4] ~ [b3,e4,g4,b4] ~ [b3,e4,g4,b4], ~@6 b4 ~@9", // C Em
  K: "~@3 [e5,a5,c6] ~ [e5,a5,c6] ~ [e5,a5,c6]", L: "~@2 [d5,g5,b5]@2 ~@2 [d5,g5,b5]@2 ~@2 [d5,g5,b5] ~@5",
  M: "~@2 [c5,f5,a5]@2 ~@2 [f5,a5] ~@3 [c5,f5,a5] ~@3 [c5,f5,a5] ~, ~@3 c5 ~@4", // F
  N: "~ [d5,g5,b5] ~ [d5,g5,b5] ~@2 [d5,g5,b5] ~", // G
  O: "~@2 [e5,a5,c6]@2 ~@2 [e5,a5,c6]@2 ~@2 [e5,a5,c6]@2 ~@2 [e5,a5,c6] ~", // Am
  P: "~ [d5,g5,b5] ~ [d5,g5,b5] ~ [d5,g5,b5] ~ [d5,b5], ~@14 g5 ~", Q: "~@3 [c5,f5,a5] ~ [c5,f5,a5] ~ [c5,f5,a5]",
  R: "~@2 [d5,g5,b5]@2 ~@2 [d5,g5,b5]@2 ~@2 [d5,g5,b5]@2 ~@2 [d5,g5,b5] ~", S: "[a4,c5,e5]@15 ~", T: "[a4,d5,f5]@7 ~",
  U: "[g4,b4,d5]@7 ~", V: "[e4,c5]@7 ~@9", W: "[a4,c5,e5]@7 ~", X: "[g4,d5]@13 ~@3", Y: "~@8 [e4,g4,b4]@5 ~@3",
  Z: "[a4,c5]@7 ~", AA: "[d5,f5]@7 ~", AB: "[g4,b4,d5]@13 ~@3", AC: "[e4,a4,c5]@6 ~@2 [e4,g4,b4]@5 ~@3",
  AD: "a4@13 ~@3", AE: "[a4,d5]@7 ~", AF: "[g4,b4,d5]@3 ~", AG: "[e4,a4,c5]@3 ~ [e4,g4,b4]@3 ~",
})).s("gm_drawbar_organ").gain(0.36)

// chords · drawbar organ · "Organ" · soft notes
const drawbar_organ_soft = note("<~@150 A ~@11 B ~@2 C D E F ~@2 G H ~@6>".pickRestart({
  A: "~ c5 ~@6", B: "a4@3 ~ [e4,g4,b4]@3 ~", C: "b4@13 ~@3", D: "[e4,a4,c5]@3 ~@5", E: "e5@7 ~", F: "a4@7 ~",
  G: "[c5,e5]@13 ~@3", H: "f5@13 ~@3",
})).s("gm_drawbar_organ").gain(0.26)

// other · overdriven guitar · "Guitar"
const overdriven_guitar = note("<A@3 B C@3 D ~@103 E@2 F@2 G H I J K L@3 M N O P Q R S@4 T U V@3 ~@41>".pickRestart({
  A: "[b3 ~ d4 [d4,e4] c4 ~ b3 ~ g3@2 b3 ~ c4 ~@27 f#3@3 ~ a3 f#3 ~ a3, e3@7 e3@8 ~@9, ~@2 g3@6 ~@7 f#4@31 ~@2, ~@16 b3@27 b3@3 b3@2]/3", // Dsus2
  B: "~@2 a3@2 ~ a3 ~@2 a3 ~@2 a3 ~@2 a3 b3, ~ b3@2 ~ b3@2 ~ b3@2 ~ b3@2 ~ b3@2 ~",
  C: "[a3 ~@2 a3 ~ a3 ~ b3@13 b2@2 ~@2 [a2,a3]@5 ~ [a2,a3]@5 ~ [a2,a3]@5 ~ [a2,a3]@5 ~, ~ b3!2 ~@21]/3", // A
  D: "[a2,a3]@4 ~@2 a2@5 ~@5", E: "[e4@25 d4@3 e4@4]/2", F: "[d4@13 c4 b3 c4@6 ~ a3@3 ~ a3!2 c4@2 e4@2]/2",
  G: "d4@4 c4 ~ a3 ~@3 a3 ~ c4@2 e4@2, ~@11 a3@2 ~@3", H: "d4@4 c4 ~ a3 ~ a3!2 ~ c4@3 e4@2",
  I: "d4@2 c4 ~ c4@2 e4@2 d4@2 ~ c4@3 a3@2, ~@3 a3@2 ~@5 a3@2 ~@4",
  J: "~ a3@2 b3@2 ~ d4 ~ d4 [e4,f4] f4 g4 ~ [g4,b4,c5] ~@2, ~@5 c4@2 e4@2 ~@2 a4@4 ~", // Fmaj7 Cmaj7
  K: "c5@3 c5@2 c5@2 ~ c5@2 ~ c5@2 ~ c5@2", L: "[c5@2 d5@4 c5@4 b4@4 a4@4 d5@4 c5@4 b4@4 a4@4 d5@4 c5@4 b4@3 a4@2 ~]/3",
  M: "e5@12 ~ d5 c5@2", N: "d5@14 c5!2", O: "c5@4 d5@2 a4@6 ~ g4 g4@2", P: "c5@3 d5@2 ~ a4@6 a4 c5@2 ~",
  Q: "a5@8 ~ a5@2 ~ a5@3 ~", R: "a5@2 ~ a5@2 ~ a5@2 a5@2 ~ a5@2 ~ a5 ~",
  S: "~@2 e5 d5 e5 d5 ~ g5@3 e5 d5 e5 d5 e5@2, g5@2 ~ e5 ~@4",
  T: "~@2 e5 d5 e5 d5 e5@2 d5 e5 c5 d5 b4 c5 a4 b4, g5 ~@3", U: "g4 ~ f4 g4 e4 f4 d4 e4 c4 d4 b3 c4 a3 b3 g3 b3",
  V: "[[a3,a4]@19 ~@5]/3", // A
})).s("gm_overdriven_guitar").gain(0.36)

// other · overdriven guitar · "Guitar" · soft notes
const overdriven_guitar_soft = note("<~@3 A B ~@2 C@2 D@2 E F ~@166>".pickRestart({
  A: "f#3 ~@2 f#3 ~@2 f#3 ~@2 f#3 ~@2 f#3@2 f#3 ~", B: "~ f#3 ~@2 f#3@2 f#3 ~@9",
  C: "[~@6 a3@5 ~@2 [a2,a3]@5 ~@2 [a2,a3]@5 ~ [a2,a3]@5 ~]/2", // A
  D: "[~ [a2,a3]@5 ~ [a2,a3]@5 ~@2 [a2,a3]@5 ~@2 [a2,a3]@5 ~@2 [a2,a3]@4]/2", E: "~@3 [a2,a3]@5 ~@2 [a2,a3]@4 ~@2",
  F: "~ [a2,a3]@4 ~@3 [a2,a3]@3 ~@5", // A
})).s("gm_overdriven_guitar").gain(0.2)

// other · pad poly · "Synthesizer"
const pad_poly = note("<~@151 A@2 B C D E F G ~@16 H I J K>".pickRestart({
  A: "[d5 b4 c5 a4 b4 g4 e5 g5 f5 e5 d5 c5 d5 b4 c5 d5 f5 d5 e5 d5 c5 d5 b4 c5 d5 e5 g5 a5 g5 f5 e5 d5, ~@15 e5@2 ~@15]/2",
  B: "f5!2 d5 e5 c5 d5 b4 c5 a4 b4 a4 b4 c5 d5 e5 f5, g5 ~@7", C: "a5 g5 f5 e5 d5 c5 b4 g4 a4 b4 c5 d5 e5 f5 g5 g#5",
  D: "a5 g5!2 e5 c5 d5 b4 c5 a4 b4 g4 a4!2 b4 c5 e5", E: "f5 g5 a5 b5 c6 b5!2 a5 g5 a5 f5 g5 e5 f5 [e5,f5] e5",
  F: "e5 c5 d5 b4 c5 a4 b4 g4 f4 g4 a4 b4 c5 d5 e5 f5", G: "g5 a5 b5 c6 a5 b5 c6 d6 b5 c6 d6 e6!2 f6 g#6 a6",
  H: "a3 ~ a3 ~ b3 ~ b3 ~ c4 ~ c4 ~ d4 ~ d4 ~",
  I: "[e4,a4] g#4 [e4,a4] b4 [f4,a4] b4 [f4,c5] b4 [g#4,c5] d5 [g#4,c5] d5 [g#4,e5] f5 [g#4,g5] g#5", // A5 F F5 G# C#m G#maj7
  J: "[a4,a5] g#5 [a4,a5] b5 [b4,a5] b5 [b4,c6] b5 [c5,c6] d6 [c5,c6] d6 [d#5,e6] f6 [d#5,g6] g#6", K: "[e5,a6] ~@15",
})).s("gm_pad_poly").gain(0.41)

// drums · rim
const rim = s("rim").struct(`<
  ~@2 A B A B A B A B A B@2 A B@3 C B A B A B A B A B A B A B A B A B A B@5 A B A B A B A B A B A B A B A B A B A B A
  B@3 A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B D B A B A
  B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B A B@2 ~@3
>`.pickRestart({
  A: "~@2 x!3 ~@3", B: "~ x ~@2", C: "~@3 x!2 ~@3", D: "~@4 x!2 ~@2 x ~@7",
})).gain(0.41)

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

// drums · snare
const snare = s("sd").struct("<~ [~@3 x] [~ x ~ x]!173 [~ x ~@2] ~@3>").gain(0.51)

// drums · low tom
const low_tom = s("lt").struct("<~@2 [~ x ~@6]!174 ~@3>").gain(0.51)

// drums · mid tom
const mid_tom = s("mt").struct("<~@2 [~@3 x ~@4]!173 ~@4>").gain(0.51)

// drums · high tom
const high_tom = s("ht").struct("<~@2 x!174 ~@3>").gain(0.51)

stack(
  piano, bass, drawbar_organ, drawbar_organ_soft, overdriven_guitar, overdriven_guitar_soft, pad_poly, rim, kick, snare,
  low_tom, mid_tom, high_tom
)

More by Prince