Help convert MidiTimeStamp from milliSeconds to Ticks

I am trying to take MidiEvents from the handleIncomingMidiMessage (MidiInput *source, const MidiMessage &message) and convert the timeStamps in to ticks so I can save it in a MIDIFile. “startTime” is just calculated when recording is started with (startTime = (Time::getMillisecondCounterHiRes() * .001);).

I’m also confused how to correctly change the timeStamp since the MidiMessage is const? I would also like to alter the miciChannel number, but I’m stuck for the same reason

[code]void PerformerManagerComponent::handleIncomingMidiMessage (MidiInput *source, const MidiMessage &message)
{
const int timeStamp = (int)((message.getTimeStamp() - startTime) * Time::getHighResolutionTicksPerSecond());

if(recState == true && playState == true)
{
	for (int i = 0; i < enabledMidiInputChannels.size(); i++)
	{
		if(source->getName() == enabledMidiInputChannels[i])
		{
			MidiMessage* const newOne = new MidiMessage (message);
			
			newOne->setTimeStamp (timeStamp);
			newOne->setChannel(i+1);
			
			midiSeqences[i]->addEvent(*newOne);
			midiSeqences[i]->updateMatchedPairs();
			
			DBG( String("Message: chn: ") + String(newOne->getChannel())
				+ String(" Note: ") + String(newOne->getNoteNumber() )
				+ String(" Vel: ") + String(newOne->getVelocity() )
				+ String(" T: ") + String(newOne->getTimeStamp()) ); 
			
		}
						
	}
}

}[/code]

The midi file makes the notes, but the time relationship is all weird. I tried to use this thread as a starting point http://www.rawmaterialsoftware.com/viewtopic.php?f=8&t=5473&hilit=MIDIFile

Which had me setting up the MidiSequencers in there like this

                // grab the BPM and add it to the XML file or however we are going to do this
		/*********************/	
		int microsecondsperquarter = 60.0*Time::getHighResolutionTicksPerSecond()/120;
	

		for(int i = 0; i < midiSeqences.size(); i++)
		{
			midiSeqences[i]->clear();
			midiSeqences[i]->addEvent(MidiMessage::timeSignatureMetaEvent(4, 4));
			midiSeqences[i]->addEvent(MidiMessage::tempoMetaEvent(microsecondsperquarter));
			midiSeqences[i]->addEvent(MidiMessage::midiChannelMetaEvent(i+1));
		}
1 Like

For anyone interested

I am currently trying to record data to a MIDI File in JUCE using an external clock source and having trouble. Here is a basic breakdown of the tricky bits

1)The midiCallback returns MidiMessages in seconds (with millisecond resolution). So message.getTimeStamp() returns a double that looks like 1234567.786
2)The tempoMetaEvent() requires an int that == the microseconds per quater note
3)setTicksPerQuarterNote(96) is what a MidiFile needs to understand time and is == to 96 ticks per quarter note
4)Time::getHighResolutionTicksPerSecond() == 1000000000 ( although I imagine it might change? it doesn’t seem to)
5)MidiClock == 24 clocks per quarter note

// find our startTime in seconds with millisecond resolution
startTime = (Time::getMillisecondCounterHiRes() * .001);

// find our microsecondsPerQuarter based off Tempo
microsecondsPerQuarter = 60.0*Time::getHighResolutionTicksPerSecond()/120; //120 is the BPM

//find our microsecondsPerQuarter based off the last two incoming midiClocks
double scaler = 24000000000.00;
microsecondsPerQuarter = (scaler * (message.getTimeStamp() - previousMessageStamp));
previousMessageStamp = message.getTimeStamp();

//find our midiMessage timeStamp in ticks based off the startTime (why do I need the .01??? arghh. I just messed around with the value till it worked, but that is ugly)
const int timeStamp = (int)(((message.getTimeStamp() - startTime)/(microsecondsPerQuarter * .01)) * Time::getHighResolutionTicksPerSecond());

1 Like