As of 02/28/2022, I added some simple improvements and new features to MIDI to TidalCycles command-line converter (https://github.com/TylerMclaughlin/midi_to_tidalcycles).
Improvements
The tool works with Python 2 and python 3 versions of the midi
module (thanks @hellocatfood !)
Trailing zeros for null values (rests) are consolidated, e.g.,0.0!23
is now simplified to 0!23
.
Indenting has been improved, so now you can copy the large stacks representing MIDI output by the tool and more effortlessly define these unruly stacks as variables in let
statements.
New Features
Two additional functionalities, extracting unique chords and extracting melody sequences are described below (copied from the project's readme):
Extracting chords from MIDI
This functionality allows you to extract a 'library' of chords/voicings from a MIDI passage. The output format is tailored for use in the select
TidalCycles function (Conditions | Tidal Cycles).
This command extracts only the chords and ignores the rhythm, sustain, and velocity data of the MIDI file.
Duplicate chords found in the MIDI file are discarded.
The optional command-line argument after the MIDI file specifies the name of the produced library.
This example:
python src/extract_chords.py test_examples/jazz-chords_played-live_quadraphonic_125bpm.mid my_jazz_chord_library
produces the following copyable TidalCycles code:
-- 8 chords
let my_jazz_chord_library p = select p [n "[-8, -12, -5, -3]", n "[-4, -7, -10, -1]", n "[-3, -8, -5, 0]", n "[-4, -1, 2, -7]", n "[-5, -3, 4, 0]", n "[-4, 2, 5, -1]", n "[-3, 7, 0, 4]", n "[-1, 0, 4, 7]"]
where p
, the input to select
, is a float between 0 and 1 (or a pattern of floats!).
Extracting melodic sequences
This functionality extracts only the notes (and their velocities) in the order in which they are played in the MIDI file. The output format is two monophonic patterns: one for notes and one for amps (MIDI velocity between 0 and 1).
Why output a pattern of notes and a pattern of amplitudes? Patterns are a flexible starting point for composition.
They are a convenient input to the
variants of the nTake
and ampTake
functions I wrote (below). In addition to accepting patterns instead of a list, these variant functions also allow you to control the total number of notes or amplitudes to take. This can be used to limit the amount of "cross-rhythm chaos" that can happen when using a struct
function with N notes and nTake
with M != N notes, for example.
let patternToList pat = map value $ sortOn whole $ queryArc pat (Arc 0 1)
nT name amt p = nTake name (take amt (cycle (patternToList p)))
aT name amt p = ampTake name (take amt (cycle (patternToList p)))
This example command
python src/extract_melody.py test_examples/simple_legato_monophonic.mid
autogenerates the following copyable TidalCycles code:
nT "notez" 5 "0 2 3 5 2"
# aT "ampz" 5 "0.79 0.79 0.79 0.79 0.79"