Midi / Sample synth loading and playback performance tips

I'd like some pointers on midi playback performance.

I'm seeing about 20-30% cpu usage from the audio engine when playing admittedly very hefty midi files (sample)
Loading times are also very long (1.2 seconds)
Here is my code

  1. debugging the loading process, it seems that the sequence.new(path) function itself takes a full second to complete. I suppose nothing can be done about that from my side? Perhaps pdc could convert midi into a proprietary sequence format so that it can be loaded into memory without parsing?
  2. To decrease the cpu usage, I re-encoded the instrument samples to 8-bit 22khz. They were 24-bit 44khz before (probably downsampled to 16 bit by pdc). I don't see a discernable difference in cpu usage. Is this expected?
  3. Does it make any sense for performance to merge tracks that have the same instrument mapped? ie. 4 drumtracks where the first has hi-hat, the second cymbals etc. Would it be beneficial to make a single track out of that? For the notes that would be playing at any given time, there would be no difference.

image

1 Like
  1. I'll file an issue to look at .mid loading time, but I won't be able to get to it until 1.13 is out. Don't want to hold that up any more.. From what I remember the loading code is pretty straightforward, and I'm chunking allocations so that it doesn't hit the allocator too much. It might be that we're calling the filesystem read() function for a byte or two at a time and the overhead there is slowing things down. I'll try buffering that at a higher level. I did that for JSON decoding a while back and it helped a lot, as I recall.

  2. I wouldn't expect a format change to make much difference. It doesn't have to move as much data from memory to the cpu, but it has to do a bit more work to convert it to 44kHz/16 bit once it gets there.

  3. I don't think that would make any practical difference.. On each update the system cycles through the tracks to check if it's time to play the next note, so you'd save a tiny bit of time there but I doubt it'd be enough that you'd ever notice.

For anyone reading this in the future, I had the same issue. Re-exporting my MIDI's from the initial program I made them in (beepbox) with another program (musecore) seemed to strip out about 90% of the file-size and load-times. (The largest file went from 88k to 8.1k, and the load-times for that song from 1.8s to 0.2s.)

I think this is because whole bunch of information stored in the file (like instrument information, pitch-bending, etc.) that the API doesn't really handle at the moment anyway. (Playing the original and the re-exported file back in timidity does seem to point in that direction anyway.)

If it later turns out I might need that information anyway, I think I'll switch to saving MIDI as separated tracks, so the loading spinner doesn't get stuck on-screen.

1 Like