Midi

Beatsearch provides functionality to import polyphonic rhythm patterns from MIDI files. The MIDI files should comply to the General MIDI Level 1 Percussion Key Map. Custom MIDI drum mappings are also allowed, but require a bit more work. The MIDI import/export functionality is found in the beatsearch.rhythm.MidiRhythm class. For example, to import a MIDI file called rumba.mid:

from beatsearch.rhythm import MidiRhythm

rhythm = MidiRhythm("rumba.mid")

MIDI drum mappings

A drum mapping is represented as a beatsearch.rhythm.MidiDrumMapping object, which is essentially a collection of beatsearch.rhythm.MidiDrumKey objects. beatsearch.rhythm.MidiDrumKey is a struct-like class which holds information about a single key within a MIDI drum mapping. Each drum key holds information about its frequency-band, the decay-time and the MIDI pitch. To load a MIDI drum loop with a custom mapping, you could do:

from beatsearch.rhythm import MidiRhythm, MidiDrumKey, FrequencyBand, DecayTime, create_drum_mapping

CustomMapping = create_drum_mapping("CustomMapping", [
   MidiDrumKey(60, FrequencyBand.LOW, DecayTime.NORMAL, "Kick", key_id="kck"),
   MidiDrumKey(62, FrequencyBand.MID, DecayTime.NORMAL, "Snare", key_id="snr"),
   MidiDrumKey(64, FrequencyBand.MID, DecayTime.NORMAL, "Tom", key_id="tom"),
   MidiDrumKey(66, FrequencyBand.HIGH, DecayTime.SHORT, "Hi-hat", key_id="hht"),
   MidiDrumKey(70, FrequencyBand.HIGH, DecayTime.LONG, "Crash", key_id="crs")
])

rhythm = MidiRhythm("loop.mid", midi_mapping=CustomMapping)

Instrumentation reduction

For analytical purposes it’s sometimes useful to reduce the instrument count of the drum patterns. This can be done setting the MidiRhythm constructor’s midi_mapping_reducer_cls parameter. The MIDI mapping reducer must be a subclass of MidiDrumMappingReducer or None for no instrumentation reduction. Beatsearch provides the following instrumentation reducers:

FrequencyBandMidiDrumMappingReducer

When this reducer is applied, the instrumentation will be reduced down to three streams, based on the frequency-band of the MIDI drum keys.

  • LOW
  • MID
  • HIGH

DecayTimeMidiDrumMappingReducer

When this reducer is applied, the instrumentation will be reduced down to three streams, based on the decay-time of the MIDI drum keys.

  • SHORT
  • NORMAL
  • LONG

UniquePropertyComboMidiDrumMappingReducer

When this reducer is applied, the instrumentation will be reduced down to nine streams. One stream per unique [frequency-band, decay-time] combination.

  • LOW.SHORT
  • LOW.NORMAL
  • LOW.LONG
  • MID.SHORT
  • MID.NORMAL
  • MID.LONG
  • LONG.SHORT
  • LONG.NORMAL
  • LONG.LONG

Example

To load a MIDI rhythm and reduce it down to three instruments: LOW, MID and HIGH, you could do:

from beatsearch.rhythm import MidiRhythm, FrequencyBandMidiDrumMappingReducer

rhythm = MidiRhythm(
    "./rumba.mid",
    midi_mapping_reducer_cls=FrequencyBandMidiDrumMappingReducer
)

Rhythm corpus

We can use the beatsearch.rhythm.MidiRhythmCorpus class to load multiple MIDI files. For example, load all the MIDI files in a directory called LOOPS, you could do:

from beatsearch.rhythm import MidiRhythmCorpus

rhythms = MidiRhythmCorpus("./LOOPS")

beatsearch.rhythm.MidiRhythmCorpus also provides functionality to export its rhythms as MIDI files to a given directory with the beatsearch.rhythm.MidiRhythmCorpus.export_as_midi_files() method. This can be useful, for example, to reduce the instrumentation of all the MIDI files in a particular directory.

from beatsearch.rhythm import MidiRhythmCorpus, FrequencyBandMidiDrumMappingReducer

loops = MidiRhythmCorpus(
    "./LOOPS",
    midi_mapping_reducer=FrequencyBandMidiDrumMappingReducer
)

loops.export_as_midi_files("./LOOPS/reduced")