Platform SDK: DirectX

Clock Time vs. Music Time

[C++]

In DirectX for C++, the time returned by the master clock is a 64-bit value defined as type REFERENCE_TIME. Reference time is measured in units of approximately 100 nanoseconds, 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.)

When a performance is initialized, it starts keeping an internal clock. You can retrieve the current performance time in both reference time and music time by using the IDirectMusicPerformance::GetTime method.

The IDirectMusicPerformance::AdjustTime method can be used to make small changes to the performance time. Most applications do not need to do this, but it can be useful when synchronizing to another source.

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 made 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 start time can be affected, or the segment might not start on the desired boundary. In the first case, in which the conversion to music time is done immediately, the start time (in reference time) is advanced if the tempo speeds up and delayed if the tempo slows down. In the second case, in which conversion is made 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 start time (in reference time) is calculated when the segment is cued. However, 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 plays 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. In this case, because music is already playing and the tempo might change, the conversion to music time is not made immediately. Then you cue segment C with the DMUS_SEGF_QUEUE flag so that it starts immediately after segment A finishes, at 15 seconds. At 20 seconds segment B starts playing and interrupts segment C.

[Visual Basic]

In DirectX for Visual Basic, the time returned by the master clock is a Long, representing units of approximately one millisecond. The value returned by DirectMusicPerformance.GetClockTime is relative to an arbitrary start point.

Music time is also a Long. 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 768 times for each quarter-note. You can retrieve the current music time by using DirectMusicPerformance.GetMusicTime.

To convert between the two kinds of time in a performance, you can use the DirectMusicPerformance.MusicToClockTime and DirectMusicPerformance.ClockToMusicTime methods.

When a segment is cued to play by a call to DirectMusicPerformance.PlaySegment and the start time is given in clock time, DirectMusic must convert the start time to music time. If no primary segment is currently playing, the conversion is made 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 start time can be affected, or the segment might not start on the desired boundary. In the first case, in which the conversion to music time is made immediately, the start time (in reference time) is advanced if the tempo speeds up and delayed if the tempo slows down. In the second case, in which conversion is made 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 lFlags parameter of PlaySegment), the start time (in clock time) is calculated when the segment is cued, However, 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 CONST_DMUS_SEGF_FLAGS), the startTime 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 plays 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. In this case, because music is already playing and the tempo might change, the conversion to music time is not made immediately. Then you cue segment C with the DMUS_SEGF_QUEUE flag so that it starts immediately after segment A finishes, at 15 seconds. At 20 seconds segment B starts playing and interrupts segment C.