Tempo question

  • Follow


Hi,

well, this is probably a trivial question, but as I'm not pretty sure, I'd
like to have your opinions.

So, this is a GM (format 1) multitrack file. Let's say we have 2 midi
tracks A and B

- The header says :

ticks per quarter note = 250

- Track A looks like this (offset = relative offset, in ticks) :

Offset 0000 # Tempo = 500000
Offset 1000 # Tempo = 250000   ' change tempo

So, the initial rate is 500000 / 250 = 2000 microseconds per tick (2 millis)
At offset 1000 (this means after 2000 millis), the rate drops down to 1000
microseconds per tick (1 milli)

- Track B looks like this :

Offset 0500 # NoteOn(X)
Offset 1500 # NoteOff(X)

Now the question : how long should the X note be played ?

Intuitively, I would say the first 500 ticks (offset 500 to 1000)
should be played with the first tempo value, and the last 500
(offset 1000 to 1500) with the second tempo. The X note
will thus last 500*2 + 500 = 1500 millis.

Is that right ? And is this supposed to be the interpretation
of every midi file decoder on earth ?

Another interpretation would be to only consider the tempo at
the time the NoteOn event occured : in this case, the X note
will last 2000 millis. This interpretation seems easier to handle
by a decoder, as in this case, every note duration only depends
on the current tempo : it doesn't have to be recalculated for all
running notes every time the tempo value changes.

So what ?

Tx !

Michel


0
Reply Michel 3/6/2007 11:11:24 PM

In article <45edf523$0$2947$ba620e4c@news.skynet.be>,
 "Michel" <dix@freegates.be> wrote:

> Hi,
> 
> well, this is probably a trivial question, but as I'm not pretty sure, I'd
> like to have your opinions.
> 
> So, this is a GM (format 1) multitrack file. Let's say we have 2 midi
> tracks A and B
> 
> - The header says :
> 
> ticks per quarter note = 250
> 
> - Track A looks like this (offset = relative offset, in ticks) :
> 
> Offset 0000 # Tempo = 500000
> Offset 1000 # Tempo = 250000   ' change tempo
> 
> So, the initial rate is 500000 / 250 = 2000 microseconds per tick (2 millis)
> At offset 1000 (this means after 2000 millis), the rate drops down to 1000
> microseconds per tick (1 milli)
> 
> - Track B looks like this :
> 
> Offset 0500 # NoteOn(X)
> Offset 1500 # NoteOff(X)
> 
> Now the question : how long should the X note be played ?
> 
> Intuitively, I would say the first 500 ticks (offset 500 to 1000)
> should be played with the first tempo value, and the last 500
> (offset 1000 to 1500) with the second tempo. The X note
> will thus last 500*2 + 500 = 1500 millis.
> 
> Is that right ? And is this supposed to be the interpretation
> of every midi file decoder on earth ?

I think this is correct and is how I do it in my own app.
> 
> Another interpretation would be to only consider the tempo at
> the time the NoteOn event occured : in this case, the X note
> will last 2000 millis. This interpretation seems easier to handle
> by a decoder, as in this case, every note duration only depends
> on the current tempo : it doesn't have to be recalculated for all
> running notes every time the tempo value changes.

I don't think so because the decoder doesn't know how long a note should 
play - it just waits for a note off. I don't think it really needs to do 
any timing calculations. So it all depends on the device sending the 
data. This device needs to always account for the current tempo because 
it is usually possible to change the play back speed in real time (thus 
modifying the tempo) as well.
> 
> So what ?
> 
> Tx !
> 
> Michel

hth,

Peter
www.fracturedsoftware.com
Rondo - MIDI for your Mac
0
Reply Peter 3/7/2007 12:53:55 AM


Michel schrieb:
> Intuitively, I would say the first 500 ticks (offset 500 to 1000)
> should be played with the first tempo value, and the last 500
> (offset 1000 to 1500) with the second tempo. 

correct

 > The X note
> will thus last 500*2 + 500 = 1500 millis.  Is that right ?

yes

> And is this supposed to be the interpretation
> of every midi file decoder on earth ?

yes

1.  find the number of units with constant tempo range
2.  calculate times of each range separately
3.  sum up all range times to a total time

> Another interpretation would be to only consider the tempo at
> the time the NoteOn event occured : in this case, the X note
> will last 2000 millis. This interpretation seems easier to handle
> by a decoder, as in this case, every note duration only depends
> on the current tempo : it doesn't have to be recalculated for all
> running notes every time the tempo value changes.

that would be potentially wrong interpretation, all tempos are important 
(each unit has a certain tempo, not important when tempos were changed 
in song).

A decoder must interpretate anything from beginning till end of song 
(all tracks parallel), so you always have current tempo, current unit, 
current command, current time, current beat etc.  Decoding from a random 
position in a midi file track is not possible (due to possible running 
status).

Rounding during calculation should be avoided that could cause a wrong 
song duration time for larger number of units when summing up rounded 
milliseconds.

free midinote/midi2txt commandline utilities could help you to analyse 
midi file time calculation  (downlood at http://www.gnmidi.com )

G�nter

0
Reply Guenter 3/7/2007 11:51:50 AM

"Peter" :

>> Is that right ? And is this supposed to be the interpretation
>> of every midi file decoder on earth ?
>
> I think this is correct and is how I do it in my own app.
>>
>> Another interpretation would be to only consider the tempo at
>> the time the NoteOn event occured : in this case, the X note
>> will last 2000 millis. This interpretation seems easier to handle
>> by a decoder, as in this case, every note duration only depends
>> on the current tempo : it doesn't have to be recalculated for all
>> running notes every time the tempo value changes.
>
> I don't think so because the decoder doesn't know how long a note should
> play - it just waits for a note off. I don't think it really needs to do
> any timing calculations. So it all depends on the device sending the
> data. This device needs to always account for the current tempo because
> it is usually possible to change the play back speed in real time (thus
> modifying the tempo) as well.

Yes, but this requires a tick-after-tick check at the thread level. So, it
doesn't allow a program to send 'scheduled events' (this means to let its
thread sleep during a fixed amount of time before doing the next job,
because it has nothing to do in the meanwhile : this saves CPU and
prevents my old computer's fan to run frenetically !), as future tempo
changes (which have not been read yet) may affect the already
scheduled timings. On the other hand, as you sayed, it allows really
easy real time inputs on the very same thread (external inputs might
also be done in a different thread, but in this case they could not
change the tempo, neither the current note status in the first thread).

You will also have to do such backwards time calculations if your
program displays, eg, a time chart of a midi file (unless you also
go for a tick-per-tick iteration, which is heavy and most of the time
useless !).

Michel



0
Reply Michel 3/7/2007 3:21:34 PM

"Guenter Nagler" :

> A decoder must interpretate anything from beginning till end of song (all
> tracks parallel), so you always have current tempo, current unit, current
> command, current time, current beat etc.  Decoding from a random position
> in a midi file track is not possible (due to possible running status).

Sure. If we want to go ahead or back in a file and start at a random
position, we have to decode the skipped parts anyway. But this can
be done very quickly, as the program can read these parts as a single
block, without passing the events to a timer thread (which we must do
if these parts have to be played).

I noticed that decoders are (very !) often erratic when dealing with
time calculations in such conditions. As an example, I runned the
following (very simple) file with the latest version of Windows
Media Player :

- header :
192 ticks per quarter note
- track A :
Offset 0000 # Tempo = 3840000
Offset 1000 # Tempo = 1920000
- track B :
Offset 0000 # Program(49)
Offset 0500 # NoteOn(75, 127)
Offset 1500 # NoteOff(75, 127)

The theoretical overall duration of this file is 30 seconds,
and the note should be played after 10 seconds. This is what
happens with WMP when I start playing the file from its
beginning (offset 0). But when I start playing it at time
offset = 9 seconds, the note won't be played before...
offset = 19 seconds, and will continue to be to played
even after the 30 seconds limit ! (if I start it at
offset = 5 seconds, then the note starts playing at
offset = 15 seconds)

As the midi default value for the tempo is only 500000,
I can guess that, even while starting at 9 seconds, WMP
has read and taken the first tempo (which is at offset 0)
into account, which it must do. But it messed up all its
calculations !

Michel



0
Reply Michel 3/7/2007 3:21:41 PM

Michel schrieb:
> 
> - header :
> 192 ticks per quarter note
> - track A :
> Offset 0000 # Tempo = 3840000
> Offset 1000 # Tempo = 1920000
> - track B :
> Offset 0000 # Program(49)
> Offset 0500 # NoteOn(75, 127)
> Offset 1500 # NoteOff(75, 127)
> 
> The theoretical overall duration of this file is 30 seconds,
> and the note should be played after 10 seconds. This is what
> happens with WMP when I start playing the file from its
> beginning (offset 0). But when I start playing it at time
> offset = 9 seconds, the note won't be played before...
> offset = 19 seconds, and will continue to be to played
> even after the 30 seconds limit ! (if I start it at
> offset = 5 seconds, then the note starts playing at
> offset = 15 seconds)
> 
> As the midi default value for the tempo is only 500000,
> I can guess that, even while starting at 9 seconds, WMP
> has read and taken the first tempo (which is at offset 0)
> into account, which it must do. But it messed up all its
> calculations !

there are problems in WMP media interfaces (e.g. MCI) since some years 
that were never repaired by Microsoft. It delivers wrong current playing 
position and total time for midifiles with tempo changes during song.

This was also the reason that I had to rewrite GNMIDI player using low 
level player functions (calculate timing self) some years ago, because 
for karaoke purposes the wrong timing information delivered by Windows 
was inacceptable.

I tried to inform Microsoft about this problem 2 years ago but they 
ignored it.

Also the first tempo must be considered independent on the position 
where you  start to play. If not then it could play same part with 
different tempi depending on the start position, which is nonsense.

Guenter
http://www.gnmidi.com

0
Reply Guenter 3/9/2007 10:57:20 AM

5 Replies
136 Views

(page loaded in 0.088 seconds)

11/27/2012 10:21:07 AM


Reply: