Skip to content

Instantly share code, notes, and snippets.

@jarmitage
Created September 29, 2017 03:21
Show Gist options
  • Select an option

  • Save jarmitage/01f8bd13b11b9710b76231e6969c0eff to your computer and use it in GitHub Desktop.

Select an option

Save jarmitage/01f8bd13b11b9710b76231e6969c0eff to your computer and use it in GitHub Desktop.
MIDI copy/paste -> TidalCycles
{-
Importing MIDI to TidalCycles
Beethoven 7th Symphony II Allegretto
Time signature: 2/4
Key: C Major
Info: https://www.wikiwand.com/en/Symphony_No._7_(Beethoven)#/Second_movement
MIDI: http://www.kunstderfuge.com/beethoven/variae.htm#Symphonies
-}
{-
Opening sequence MIDI imported and copied from Logic Pro. Columns left-to-right:
- Position (bar, beat, submeasure, decimal)
- Status (event type)
- Channel
- Number
- Value
- Length/info (same format as position?)
- First two bars of Contrabassi, raw paste:
5 1 1 1 Note 13 A1 50 0 0 3 200
5 2 1 1 Note 13 A1 50 0 0 1 200
5 2 3 1 Note 13 A1 50 0 0 1 200
6 1 1 1 Note 13 G♯1 50 0 0 3 200
6 2 1 1 Note 13 G♯1 50 0 0 3 200
- Tidy spacing and separate types with commas
5 1 1 1, Note, 13, A1, 50, 0 0 3 200
5 2 1 1, Note, 13, A1, 50, 0 0 1 200
5 2 3 1, Note, 13, A1, 50, 0 0 1 200
6 1 1 1, Note, 13, G♯1, 50, 0 0 3 200
6 2 1 1, Note, 13, G♯1, 50, 0 0 3 200
- This MIDI starts in bar 5 so let's subtract 5 from the first column
- Replace the special character '♯' with 's'
- We do not need the 'Note' and 'Channel' info right now
0 1 1 1, A1, 50, 0 0 3 200
0 2 1 1, A1, 50, 0 0 1 200
0 2 3 1, A1, 50, 0 0 1 200
1 1 1 1, Gs1, 50, 0 0 3 200
1 2 1 1, Gs1, 50, 0 0 3 200
- Take the first column (note position info; bar, beat, submeasure, decimal)
0 1 1 1
0 2 1 1
0 2 3 1
1 1 1 1
1 2 1 1
-}
-- Column 1: create a pattern with events equal to total number of bars
"[[~] [~]]"
-- Column 2: subdivide each 'bar' by total number of 'beats'
"[[~ ~] [~ ~]]"
-- Column 3: subdivide each 'beat' by total submeasures
"[[~ [~ ~]] [~ ~]]"
-- Column 4: no additional onset position info in this case
-- This rhythm is the main motif of the whole symphonic movement! Let's define it as a note pattern
let motif = "[[0 [0 0]] [0 0]]"
{-
Now we can add our actual note data
0 1 1 1, A1
0 2 1 1, A1
0 2 3 1, A1
1 1 1 1, Gs1
1 2 1 1, Gs1
-}
let contrabassi = "[a1 gs1]"
{-
Before we listen, let's pick a tempo for 'Allegretto'
https://www.wikiwand.com/en/Tempo#/Italian_tempo_markings
"Allegretto – by the mid 19th century, moderately fast (112–120 bpm); see paragraph above for earlier usage"
Ok...
"One striking example is that Allegretto hastened as a tempo from the 18th to the 19th century: originally it was just above Andante, instead of just below Allegro as it is now."
Ok...
"Andante – at a walking pace (76–108 bpm)"
Alright!
-}
cps (76/120)
d1 $ n (motif + contrabassi) # s "superpiano" # octave "6"
-- Err. We forgot our motif is two bars long! Let's formalise this code structure a bit...
do
let motif = "[[0 [0 0]] [0 0]]/2"
contrabassi = "[a1 gs1 ]/2"
d1 $ n (motif + contrabassi)
# s "superpiano"
# octave "6"
{-
That's better but it's a bit loud for the first two bars
What do we have left?
0 1 1 1, A1, 50, 0 0 3 200
0 2 1 1, A1, 50, 0 0 1 200
0 2 3 1, A1, 50, 0 0 1 200
1 1 1 1, Gs1, 50, 0 0 3 200
1 2 1 1, Gs1, 50, 0 0 3 200
- Velocity (50)
- Length
-}
-- Velocity can be expressed as (50/127) or roughly "0.4"
-- Length expressed as a 'sustain' pattern using the same motif structure, but this time we can simplify it a bit
do
let bars = slow 2
motif = bars $ "[[0 [0 0]] [0 0]]"
contrabassi = bars $ "[a1 gs1 ]"
duration = bars $ "[[1 0.5 ] 1 ]"
d1 $ n (motif + contrabassi)
# s "superpiano"
# octave "6"
# velocity "0.4"
# sustain duration
{-
Sounds a little bare...
Let's grab the other parts, viole and violoncelli
5 1 1 1 Note 11 E3 50 0 0 3 200
5 1 1 1 Note 12 C3 50 0 0 3 200
5 2 1 1 Note 11 E3 50 0 0 1 200
5 2 1 1 Note 12 C3 50 0 0 1 200
5 2 3 1 Note 11 E3 50 0 0 1 200
5 2 3 1 Note 12 C3 50 0 0 1 200
6 1 1 1 Note 11 E3 50 0 0 3 200
6 1 1 1 Note 12 B2 50 0 0 3 200
6 2 1 1 Note 11 E3 50 0 0 3 200
6 2 1 1 Note 12 B2 50 0 0 3 200
- Viole:
0 1 1 1, E3, 50, 0 0 3 200
0 2 1 1, E3, 50, 0 0 1 200
0 2 3 1, E3, 50, 0 0 1 200
1 1 1 1, E3, 50, 0 0 3 200
1 2 1 1, E3, 50, 0 0 3 200
- Violoncelli
0 1 1 1, C3, 50, 0 0 3 200
0 2 1 1, C3, 50, 0 0 1 200
0 2 3 1, C3, 50, 0 0 1 200
1 1 1 1, B2, 50, 0 0 3 200
1 2 1 1, B2, 50, 0 0 3 200
Everything is the same here except the notes, so...
-}
do
let bars = 2
motif = "[[0 [0 0]] [0 0]]"
viole = "[e3 ]"
violoncelli = "[c3 b2 ]"
contrabassi = "[a1 gs1 ]"
duration = "[[1 0.5 ] 1 ]"
d1 $ slow bars
$ stack [
n (motif + viole),
n (motif + violoncelli),
n (motif + contrabassi)
]
# s "superpiano"
# octave "6"
# velocity "0.4"
# sustain duration
{-
How do we expand this to do more bars?
-}
do
let bars = 8
motif = fast (bars/2) $ "[[0 [0 0]] [0 0]]"
duration = fast (bars/2) $ "[[1 0.5 ] 1 ]"
viole = "[e3 e3 e3 e3 [e3 [e3 fs3]] g3 g3 [g3 ~]]"
viole2 = "[~ ~ ~ ~ [~ [~ d3]] e3 [d3 [c3 d3]] [e3 ~]]"
violoncelli = "[c3 b2 b2 c3 c3 c3 [b2 [a2 b2]] [c3 ~]]"
contrabassi = "[a1 gs1 e1 a1 a1 g1 g1 [c2 ~]]"
d1 $ slow bars
$ stack [
n (motif + viole),
n (motif + viole2),
n (motif + violoncelli),
n (motif + contrabassi)
]
# s "superpiano"
# octave "7"
# velocity "0.4"
# sustain duration
{-
And that's it! One of the most famous motifs in romantic music.
Now go build a parser and do this properly...
-}
hush
@john-d-murphy
Copy link

This is wonderful. Thank you for posting this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment