Nested Tempi

Example directory (scamp): examples/Tutorial/11_nested_tempi

Download: 11_nested_tempi.zip

Music running with nested tempi: a trombone plays a cyclic quarter-note pattern on the session’s accelerating pulse, while a trumpet, forked onto a child clock, plays a similar eighth-note pattern. After a few beats, while the overall session is still accelerating, the trumpet clock starts decelerating to half speed. The music is then notated two ways: nested_tempi.py transcribes from the session’s point of view so that the trombone plays straight quarter notes, while the trumpet shows a written-out deceleration from eighth to quarter notes; nested_tempi_child_clock.py records from the trumpet clock’s point of view, yielding plain eighth notes in the trumpet and more complex rhythmic notation in the trombone.

Topics: Time & clocks › Advanced

score
nested_tempi.py: Recorded from the session/master clock.
from scamp import *
import itertools

s = Session()

trumpet = s.new_part("trumpet", default_spelling_policy="c phrygian")
trombone = s.new_part("trombone", default_spelling_policy="c phrygian", clef_preference="bass")

trumpet_note_pattern = itertools.cycle([67, 72, 67, 68])
trombone_note_pattern = itertools.cycle([60, 55, 48, 49, 48])


# A forked function runs on its own child clock, nested under the session that forked it.
def trumpet_part():
    # play the trumpet figure in eighth notes until the session reaches beat 3
    while s.beat < 3:
        trumpet.play_note(next(trumpet_note_pattern), 1, 0.5)

    # slow this child clock to half its current rate over the next 7 beats of the parent
    # note that this doesn't necessarily mean that we will land on the beat in this child clock
    # `align_to=MetricPhaseTarget(0)` is what ensures that that happens.
    set_rate_target(0.5, Moment.after_time(7), align_to=MetricPhaseTarget(0))

    # keep playing eighth notes until the session reaches beat 16
    while s.beat < 16:
        trumpet.play_note(next(trumpet_note_pattern), 1, 0.5)


# speed the whole session up to 100 BPM over its first 14 beats
s.set_tempo_target(100, Moment.after_beats(14))
s.fork(trumpet_part)
# transcribe from the session's main timeline -- the default when no clock is given
s.start_transcribing()

# play the trombone figure in quarter notes until the session reaches beat 16
while s.beat < 16:
    trombone.play_note(next(trombone_note_pattern), 1, 1)

# Stop recording and show the result
performance = s.stop_transcribing()
performance.to_score(time_signature="3/4").show()
score
nested_tempi_child_clock.py: Recorded from the forked child clock.
from scamp import *
import itertools

s = Session()

trumpet = s.new_part("trumpet", default_spelling_policy="c phrygian")
trombone = s.new_part("trombone", default_spelling_policy="c phrygian", clef_preference="bass")

trumpet_note_pattern = itertools.cycle([67, 72, 67, 68])
trombone_note_pattern = itertools.cycle([60, 55, 48, 49, 48])


# A forked function runs on its own child clock, nested under the session that forked it.
def trumpet_part():
    # play the trumpet figure in eighth notes until the session reaches beat 3
    while s.beat < 3:
        trumpet.play_note(next(trumpet_note_pattern), 1, 0.5)

    # slow this child clock to half its current rate over the next 7 beats of the parent
    # note that this doesn't necessarily mean that we will land on the beat in this child clock
    # `align_to=MetricPhaseTarget(0)` is what ensures that that happens.
    set_rate_target(0.5, Moment.after_time(7), align_to=MetricPhaseTarget(0))

    # keep playing eighth notes until the session reaches beat 16
    while s.beat < 16:
        trumpet.play_note(next(trumpet_note_pattern), 1, 0.5)


# speed the whole session up to 100 BPM over its first 14 beats
s.set_tempo_target(100, Moment.after_beats(14))
# fork returns the child clock it created, which we hand to the transcriber below
trumpet_clock = s.fork(trumpet_part)
# transcribe from the trumpet clock's timeline, so the same music is notated against its tempo curve
s.start_transcribing(clock=trumpet_clock)

# play the trombone figure in quarter notes until the session reaches beat 16
while s.beat < 16:
    trombone.play_note(next(trombone_note_pattern), 1, 1)

# Stop recording and show the result
performance = s.stop_transcribing()
performance.to_score(time_signature="3/4").show()