I’m building a midi sequencer that works as a tracktion_engine::Plugin
. Inside the applyToBuffer()
function, I locate an array of MidiMessages
, find one that matches the time index, and then swap it into the midi buffer. It looks something like this:
void SequencerPlugin::applyToBuffer(const te::AudioRenderContext& context)
{
if (const auto eventArray = getEvents()) // type: std::shared_ptr<const std::vector<Event>>
for (auto event : *eventArray)
if (event->getTimeIndex() <= context.playhead.getPosition())
context.bufferForMidiMessages->swapWith(event->getMidiMessageArray());
}
(Note: There are a lot of things that probably look fishy about this code, but please bare with me for the moment. I’ve been very careful to ensure that allocation, de-allocation and locking never happen inside this function, even though it might not seem so in the simplified code I’ve typed out here.)
My question is: would it be a Bad Idea to use a std::map<double, Event>
as a container, rather than a std::vector<Event>
?
I would want to do this because:
- It would mean that all off the events would be sorted by time index, and the audio thread could locate the right ones without having to iterate over the whole array.
- It would make some other parts of my code a lot neater (i.e. the parts where I am populating the Events, not shown here).
Again, the audio thread would only have access to a std::shared_ptr<const std::map<double, Event>>
, so it could only read from the map, never alter it.
I’m asking this question because I know that iterating over a map is a lot slower than iterating over an array, and I’m wondering if it’s a bad idea to do this from the audio thread.