One .mid to rule them all 🎶

i dont know how everyone else is doing music, I just started playing with the audio library of the SDK. but as a noob, i've found a cool work flow that might work for someone else, or maybe you guys can tell me what i could be doing better.

I work in Ableton for music. It can export midi files, but not as multi-track midi files. This was going to be pretty annoying and clunky to work with, as to compose any decently complex music I'd have hundreds of separate midi files. Workable, but not efficient.

Enter "midisox"

midisox is a command-line tool that lets you manipulate midi files. The feature I'm interested in is merge. Merge takes an arbitrary amount of input.mid files, and gives you one output.mid that is the "merged" version of all the inputs, put into separate tracks in a single midi file.

The pd.sound library lets you assign a track within a midi sequence to an instrument. This means you can:

  • lay out the midi for an entire song, with separate tracks, in the DAW of your choice
    • you'll want to name the tracks something that will sort (01_drums, 02_leadSynth, etc)
    • sorting is essential to know what tracks to assign to what instruments later
  • export those midi files to some folder
  • run midisox with the -M option, signifying merge, on that folder with something like
midisox -M ~/myMidiFolder/* outputMidi.mid
  • use the SDK to assign instruments to the various tracks
  local midi = 'sounds/output.mid'
  s = sfx.sequence.new(midi)
  local ch00 = sfx.channel.new()

  local track1 = s:getTrackAtIndex(1)
  local newInst1 = newinst(1)
  track1:setInstrument(newInst1)
  local track2 = s:getTrackAtIndex(2)
  local newInst2 = newinst(1)
  track2:setInstrument(newInst2)
  ch00:addSource(newInst1)
  ch00:addSource(newInst2)
  s:setTempo(920)
  s:setLoops(1, s:getLength()+300, 0)
  s:play()

BOOM :boom: composing multi-track, multi-instrument songs in a DAW which reduce down to one midi file. maybe that's the norm, but for me it felt like a breakthrough.

side notes

  • all midi files should be stretched over the entire length of the song, which musicians tend to not do for various reasons. but this will keep everything lined up rhythmically as it lays out in your DAW
  • i wish BPM was more of a built-in feature. the SDK tends to use "steps per second" which is totally unfamiliar to me, and ive worked in music my whole life so it makes me feel dumb.
  • musicsox was pretty easy to get going, just ran these commands and read the (pretty short) documentation
brew install luarocks
luarocks install midi
luarocks install luaposix
luarocks install midisox
3 Likes

"steps" are how time is represented in .mid files so I used that when I first implemented sequences, because it was the only way to create sequences. I wish it had occurred to me to convert that to something that makes real-world sense when I added API for working with sequences in code. :person_facepalming: I'll add functions that use beat counts instead and deprecate the step nonsense. Thanks for pointing that out!

1 Like

i totally see why it was implemented in steps. makes sense. but yeah, BPM would be more accessible.

1 Like