0

I realize that there are many questions here concerning converting MIDI ticks to milliseconds (ex: How to convert midi timeline into the actual timeline that should be played, Midi Ticks to Actual PlayBack Seconds !!! ( Midi Music), Midi timestamp in seconds) and I have looked at them all, tried to implement the suggestions, but i am still not getting it.

(Did I mention I am a little "math phobic")

Can anyone help me work a practical example? I am using the Bass lib from un4seen. I have all the data I need - I just don't trust my calculations.

Bass Methods

Tick

// position of midi stream
uint64_t tick = BASS_ChannelGetPosition(midiFileStream, BASS_POS_MIDI_TICK)

PPQN

//The Pulses Per Quarter Note (or ticks per beat) value of a MIDI stream.
float ppqn;
BASS_ChannelGetAttribute(handle, BASS_ATTRIB_MIDI_PPQN, &ppqn);

Tempo

 //tempo in microseconds per quarter note.
 uint32_t tempo = BASS_MIDI_StreamGetEvent( midiFileStream, -1, MIDI_EVENT_TEMPO);

My Attempt at Calculating MS value for tick:

float currentMilliseconds = tick * tempo / (ppqn * 1000);

The value I get appears correct but I don't have any confidence in it since I am not quite understanding the formula.

printf("tick %llu\n",tick);
printf("ppqn %f\n",ppqn);
printf("tempo %u\n",tempo);
printf("currentMilliseconds %f \n", currentMilliseconds);

Example output:

tick 479
ppqn 24.000000
tempo 599999
currentMilliseconds 11974.980469 

Update

My confusion continues but based on this blog post I think I have the code right – at least the output seems accurate. Conversely, the answer provided by @Strikeskids below yields different results. Maybe I have an order of operations problem in there?

float kMillisecondsPerQuarterNote = tempo / 1000.0f;
float kMillisecondsPerTick = kMillisecondsPerQuarterNote / ppqn;
float deltaTimeInMilliseconds = tick * kMillisecondsPerTick;
printf("deltaTimeInMilliseconds %f \n", deltaTimeInMilliseconds);

.

float currentMillis = tick * 60000.0f / ppqn / tempo;
printf("currentMillis %f \n", currentMillis);

Output:

 deltaTimeInMilliseconds 11049.982422 
 currentMillis 1.841670 
Community
  • 1
  • 1
spring
  • 18,009
  • 15
  • 80
  • 160
  • 1
    You know that the tempo can change in the middle of the file? You cannot escape from using [even more math](http://stackoverflow.com/a/23071105/11654). – CL. Jul 13 '14 at 08:07
  • You already have microseconds per quarter note provided by BASS. Isn't that what you said you are looking for? – Brad Jul 13 '14 at 14:10
  • @Brad - no, I am trying to calculate the milliseconds for specific ticks – spring Jul 13 '14 at 16:42

2 Answers2

3

Tempo is in beats per minute. Because you want to be getting a time, you should have it in the denominator of your fraction.

currentTime = currentTick * (beats / tick) * (minutes / beat) * (millis / minute)

millis = tick * (1/ppqn) * (1/tempo) * (1000*60)

to use integer arithmetic efficiently do

currentMillis = tick * 60000 / ppqn / tempo

Strikeskids
  • 3,932
  • 13
  • 27
  • Sorry, I'm still not getting it. If you could, would you edit your answer using the vars I posted in my question? Seeing the specific vars used would help me to understand the formula you have described above and how it is applied. (welcome to my obtuse world... ;-) – spring Jul 13 '14 at 16:48
  • The first line is theoretical. The second line is the theoretic version transformed into your variables, and the third line has the variables reordered into the format you would write in code. – Strikeskids Jul 13 '14 at 20:16
  • Thanks. I've updated my question with a method and output from your example and from code and an explanation I found on this site (http://www.lastrayofhope.co.uk/2009/12/23/midi-delta-time-ticks-to-seconds/2/). The output from the two methods is very different and I fail to see why. Order of operations? – spring Jul 14 '14 at 17:30
3

This works:

float kMillisecondsPerQuarterNote = tempo / 1000.0f;
float kMillisecondsPerTick = kMillisecondsPerQuarterNote / ppqn;
float deltaTimeInMilliseconds = tick * kMillisecondsPerTick;
printf("deltaTimeInMilliseconds %f \n", deltaTimeInMilliseconds);
spring
  • 18,009
  • 15
  • 80
  • 160