Timing [Topic]

Timing in Common Music is generally expressed in terms of beats, i.e. a rhythmic duration of 1.0 does not necessarily map to 1 second (although it often will). Rather, translation into time and the syntax-dependent specifics of the time format to use is under control of the current output stream. Thus, although time information will most always be expressed locally, with respect to a container or item stream, timing as a whole and time warping is global to the system (cf. the figure below).



Figure: Interrelationships between container-based and global timing in Common Music.

Tempo and Global Time Warping

Several Common Music constructs such as in-tempo, tempo, rhythm and rhythms, make use of a tempo reference that typically defaults to the value of *standard-tempo*. Although names and units (bpm) of these "tempo" arguments suggest an implicit beat-to-time conversion at this time, it is important to note that this is not the case. The result of

(rhythm 'q 76)

is still interpreted as being in beats, as it would be intuiively in (rhythm 'q). Hence, tempo arguments allow one to express beat-based quantities in terms of "native" units of streams in temporal proportion to the global beat-based tempo, not in absolute values.

tempo objects, on the other hand, allow the user to time-warp output globally and dynamically, while preserving the beat-based format. tempo objects across all containers output side-effect the global time management. For streams based on raw (real) time, tempo objects side-effect the beat slot in output streams as well as the global *standard-tempo*. For streams supporting a logical, beat-based time format, such as MIDI files, tempo objects are translated in appropriate tempo change messages and output on the stream.

Finally, all time-related quantities are scaled globally by the value stored in the stream's timescale slot, that is,

Stella [Top-level]: open <stream> timescale 1.25

will slow down all musical output over <stream> by a ratio of 5/4.

Input

Musical data containing logical time information may be input using the import command in one of four ways:

  1. Logical Time Format ("beats")
    1. with translation of tempo changes to tempo objects
    2. just beats without time translation
  2. Real Time Format ("raw")
    1. with import of tempo changes
    2. just raw time without tempo changes
Note that only 1.a. and 2.b. allow import and re-export without time distortion: 1.b. would result in time distortions if the source contains at all tempo changes and 2.a. would warp the tempo twice if re-output.

Import format 1.a. is the default for MIDI files.

Examples:

Example 1: Using csound syntax with output to a csound score file:

Stella [Top-Level]: (defobject i1 (csound-note)
		      ((ins :initform 'i1) dur)
		      (:parameters ins time dur))

#<STANDARD-CLASS I1>
Stella [Top-Level]: (thread csound-test ()
		      (object tempo bpm 30 rhythm 0)
		      (dotimes (i 2) (object i1 rhythm .5 dur 1))
		      (object tempo bpm 60 rhythm 1)
		      (dotimes (i 2) (object i1 rhythm .5 dur 1))
		      (object tempo bpm 120 rhythm 2)
		      (dotimes (i 2) (object i1 rhythm .5 dur 1)))

#<THREAD: Csound-Test>
Stella [Top-Level]: open /tmp/test.sco play nil
Stream: #<File: "/tmp/test.sco">
Stella [Top-Level]: mix csound-test 0
Stella [Top-Level]: (shell "cat /tmp/test.sco")
; Common Music output of 21-May-98 1:56:39

s
i1 0.0 1
i1 0.999 1
i1 2.999 1
i1 3.499 1
i1 5.0 1
i1 5.249 1
e
0
Stella [Top-Level]:

Example 2: Using MIDI syntax with output to a MIDI file:

Stella [Top-Level]: (thread test ()
		      (object tempo bpm 30)
		      (dotimes (i 2)
			(object midi-note
                                rhythm .5 note (+ 60 i) duration 1))
		      (object tempo bpm 60 rhythm 1)
		      (dotimes (i 2)
			(object midi-note
                                rhythm .5 note (+ 62 i) duration 1))
		      (object tempo bpm 120 rhythm 2)
		      (dotimes (i 2)
			(object midi-note
                                rhythm .5 note (+ 64 i) duration 1)))
#<THREAD: Test>
Stella [Top-Level]: tlist test 0
Test
    0.00    1. #<Tempo 30 bpm (2.000 s)>
            2. #<MIDI-NOTE | 60| 0.500|     1| 64| 0|>
    0.50    3. #<MIDI-NOTE | 61| 0.500|     1| 64| 0|>
    1.00    4. #<Tempo 60 bpm (1.000 s) rhythm 1.000>
    2.00    5. #<MIDI-NOTE | 62| 0.500|     1| 64| 0|>
    2.50    6. #<MIDI-NOTE | 63| 0.500|     1| 64| 0|>
    3.00    7. #<Tempo 120 bpm (0.500 s) rhythm 2.000>
    5.00    8. #<MIDI-NOTE | 64| 0.500|     1| 64| 0|>
    5.50    9. #<MIDI-NOTE | 65| 0.500|     1| 64| 0|>
Stella [Top-Level]: open /tmp/test.midi play nil 
Stream: #<File: "/tmp/test.midi">
Stella [Top-Level]: mix test 0
Stella [Top-Level]: (midifile-print "/tmp/test.midi")

File: /tmp/test.midi 
Format: 0
Tracks: 1
Division: 480

Track 0, length 84
         0 #<Tempo Change: 2000.0 ms>
         0 #<Note-On: 0 60 64>
       240 #<Note-On: 0 61 64>
       240 #<Note-Off: 0 60 127>
         0 #<Tempo Change: 1000.0 ms>
       240 #<Note-Off: 0 61 127>
       240 #<Note-On: 0 62 64>
       240 #<Note-On: 0 63 64>
       240 #<Note-Off: 0 62 127>
         0 #<Tempo Change: 500.0 ms>
       240 #<Note-Off: 0 63 127>
       720 #<Note-On: 0 64 64>
       240 #<Note-On: 0 65 64>
       240 #<Note-Off: 0 64 127>
       240 #<Note-Off: 0 65 127>
Stella [Top-Level]: 

Example 3: Using import to import a MIDI file:

Stella [Top-Level]: import /tmp/test.midi time-format :raw meta nil
Stella [Top-Level]: tlist 1 0
From-Test
    0.00    1. #<MIDI-NOTE | C4| 1.000| 2.000| 0.504| 0|>
    1.00    2. #<MIDI-NOTE |CS4| 2.000| 1.500| 0.504| 0|>
    3.00    3. #<MIDI-NOTE | D4| 0.500| 1.000| 0.504| 0|>
    3.50    4. #<MIDI-NOTE |DS4| 1.500| 0.750| 0.504| 0|>
    5.00    5. #<MIDI-NOTE | E4| 0.250| 0.500| 0.504| 0|>
    5.25    6. #<MIDI-NOTE | F4| 0.500| 0.500| 0.504| 0|>
Stella [Top-Level]: import /tmp/test.midi time-format :raw meta t
Stella [Top-Level]: tlist 2 0
From-Test-1
    0.00    1. #<Tempo Change: 2000.0 ms>
    0.00    2. #<MIDI-NOTE | C4| 1.000| 2.000| 0.504| 0|>
    1.00    3. #<MIDI-NOTE |CS4| 1.000| 1.500| 0.504| 0|>
    2.00    4. #<Tempo Change: 1000.0 ms>
    3.00    5. #<MIDI-NOTE | D4| 0.500| 1.000| 0.504| 0|>
    3.50    6. #<MIDI-NOTE |DS4| 0.500| 0.750| 0.504| 0|>
    4.00    7. #<Tempo Change: 500.0 ms>
    5.00    8. #<MIDI-NOTE | E4| 0.250| 0.500| 0.504| 0|>
    5.25    9. #<MIDI-NOTE | F4| 0.500| 0.500| 0.504| 0|>
Stella [Top-Level]: import /tmp/test.midi time-format :beats meta nil
Stella [Top-Level]: tlist 3 0
From-Test-2
    0.00    1. #<MIDI-NOTE | C4| 0.500| 1.000| 0.504| 0|>
    0.50    2. #<MIDI-NOTE |CS4| 1.500| 1.000| 0.504| 0|>
    2.00    3. #<MIDI-NOTE | D4| 0.500| 1.000| 0.504| 0|>
    2.50    4. #<MIDI-NOTE |DS4| 2.500| 1.000| 0.504| 0|>
    5.00    5. #<MIDI-NOTE | E4| 0.500| 1.000| 0.504| 0|>
    5.50    6. #<MIDI-NOTE | F4| 1.000| 1.000| 0.504| 0|>
Stella [Top-Level]: import /tmp/test.midi time-format :beats meta t
Stella [Top-Level]: tlist 4 0
From-Test-3
    0.00    1. #<Tempo 30.0 bpm (2000 ms, 2 s) rhythm 0.0>
    0.00    2. #<MIDI-NOTE | C4| 0.500| 1.000| 0.504| 0|>
    0.50    3. #<MIDI-NOTE |CS4| 0.500| 1.000| 0.504| 0|>
    1.00    4. #<Tempo 60.0 bpm (1000 ms, 1 s) rhythm 1.0>
    2.00    5. #<MIDI-NOTE | D4| 0.500| 1.000| 0.504| 0|>
    2.50    6. #<MIDI-NOTE |DS4| 0.500| 1.000| 0.504| 0|>
    3.00    7. #<Tempo 120.0 bpm (500 ms, 1/2 s) rhythm 2.0>
    5.00    8. #<MIDI-NOTE | E4| 0.500| 1.000| 0.504| 0|>
    5.50    9. #<MIDI-NOTE | F4| 1.000| 1.000| 0.504| 0|>
Stella [Top-Level]: 

See Also:

csound [Syntax], csound-score-file [Class], event-stream [Class], import [Command], in-tempo [Function], MIDI [Syntax], midi-file [Class], open [Command], play [Command], rhythm [Function], rhythms [Macro], *standard-tempo* [Variable], tempo [Class], tempo [Macro]


Last Modified: 7-Jun-1998