Hi everyone, I have been working with juce for a month or so right now. What I’m trying to do is recording any midi input and storing it into a midi file.
I understood how to create and write in a midi file, my problem is that the midi events I’m getting in the midi buffer have timestamps that I can’t understand because they just increase and decrease with no clear reason.
Because of the timestamps when I add the midi events in a MidiMessageSequence they get sorted based on their timestamp so what I record and save is in the wrong order compared to what I played.
Is there a way to save them in a MidiMessageSequence without them being sorted? Or do I just have to use something else?
This is the code where I store the midi Events in the midi message sequence:
void TestAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages){
for (const auto midiMessage : midiMessages) {
auto midiEvent = midiMessage.getMessage();
if(startRec){ mms.addEvent(midiEvent); } //mms is an instance of MidiMessageSequence
}
}
I’m doing it in the process block function, maybe I should do it in a different place but I don’t know where.
The timestamps in the processBlock MidiBuffer are for the current processing buffer so that events can be handled at sample accurate positions by the plugins.
You need to additionally keep track of the overall passing of time by counting samples and add your events into the recorded midi message sequence taking that into account.
So, possibly something like this, but I haven’t tested this for correctness…
void TestAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages){
for (const auto midiMessage : midiMessages) {
auto midiEvent = midiMessage.getMessage();
double adjustedpos = midiEvent.getTimeStamp() + sequencepositioncounter;
if(startRec){ mms.addEvent(midiEvent,adjustedpos); } //mms is an instance of MidiMessageSequence
}
// sequencepositioncounter is an int member variable that should be initialized to zero at beginning of recording
sequencepositioncounter += buffer.getNumSamples();
}
Hi thanks a lot for the fast answer!
The problem as I wrote in the previous message is that the timestamps also decrease and that’s why they are in the wrong order when stored in the MidiMessageSequence.
I’ll paste an example of what I get when printing the MidiMessages descriptions and timestamps.
Note on C4 Velocity 85 Channel 1 307
Note off C4 Velocity 85 Channel 1 259
Note on D4 Velocity 99 Channel 1 243
Note off D4 Velocity 99 Channel 1 437
Note on E4 Velocity 102 Channel 1 412
Note off E4 Velocity 102 Channel 1 147
Note on C4 Velocity 102 Channel 1 198
Note off C4 Velocity 102 Channel 1 130
As you can see timestamp values also decrease, and when stored in the MidiMessageSequence they are going to be sorted based on their timestamps.
By the way I tried your method but I’m not getting any audio inputs in the buffer so the sequencepositioncounter variable will not be increased.
What host is that happening in? That doesn’t seem like correct behavior.
edit : but if that’s really the case, then perhaps the audioprocessor playhead timing info could be used. 
I’m on Zorin OS (ubuntu based), but the fact that i’m not getting any audio samples is normal because I’m only sending midi inputs and not audio inputs.
What do you mean by audioprocessor playhead timing info?
Edit: I discovered that in the processBlock function each message’s timestamp will indicate the message’s time, as a number of samples from the start of the block.
So I thought about setting the timestamps to juce::Time::getMillisecondCounter()/1000 as it’s done in the handleIncomingMidiMessage function of the MidiInputCallback class.
The problem now I think has something to do with the midiFile actual saving, should I use the setTicksPerQuarterNote function or the setSmpteTimeFormat function? And what should I put as an argument to keep track of the actual real time between the midiEvents (so that they are not time streched)?