Reference Time vs. Music Time

Reference time is the time returned by the master clock. It is a 64-bit value defined as type REFERENCE_TIME. Reference time is measured in units of 100 nanoseconds, more or less, so the clock ticks about 10 million times each second. The value returned by the IReferenceClock::GetTime method is relative to an arbitrary start time.

Music time is a 32-bit value defined as type MUSIC_TIME. It is not an absolute measure of time but is relative to the tempo. The clock is started when the performance is initialized, and ticks DMUS_PPQ times for each quarter-note. (DMUS_PPQ is currently defined as 768.)

To convert between the two kinds of time in a performance, you can use the IDirectMusicPerformance::MusicToReferenceTime and IDirectMusicPerformance::ReferenceToMusicTime methods.

When a segment is cued to play by a call to IDirectMusicPerformance::PlaySegment and the start time is given in reference time, DirectMusic must convert the start time to music time. If no primary segment is currently playing, the conversion is done immediately, based on the current tempo. Otherwise, if another segment is playing, the start time of the cued segment is not converted to music time until the start time has been reached.

If the tempo is changed before the segment starts playing, the actual start time can be affected, or the segment might not start on the desired boundary. In the first case, where the conversion to music time is done immediately, the actual start time (in reference time) will be advanced if the tempo speeds up and delayed if the tempo is slowed down. In the second case, where conversion is done at start time, a change in tempo can mean that the segment does not start at correct resolution boundaries. For example, if the segment is supposed to start on a measure boundary (as indicated in the dwFlags parameter of PlaySegment), the actual start time (in reference time) is calculated when the segment is cued, but if the tempo then changes, a measure boundary might not fall at that time.

When a primary segment is passed to PlaySegment with the DMUS_SEGF_QUEUE flag (see DMUS_SEGF_FLAGS), the i64StartTime parameter is ignored and the segment is cued to play after any primary segments whose start times have already been converted. If a previously cued segment is still stamped in reference time, that segment will play at its designated time, perhaps interrupting another segment.

An example should make this clearer. Say you have three segments, each 10 seconds in length. You cue segment A to play 5 seconds from now. Because no primary segment is currently playing, the start time is immediately converted to music time. At 6 seconds you cue segment B to play at 20 seconds of reference time. In this case, because music is already playing and the tempo might change, the conversion to music time is not done immediately. Then you cue segment C with the DMUS_SEGF_QUEUE flag, so that it will start immediately after segment A finishes, at 15 seconds. At 20 seconds segment B will start playing and interrupt segment C.