Patterns that change every cycle
By the end of this chapter, every fourth bar ends in a tom fill, and a pedal hi-hat every three sixteenth notes turns against the beat, and starts a bar with it again only every third bar.
The piece so far
Everything Swing, groove and other transforms built, without its render. This chapter adds two patterns and changes none.
import subsequence
import subsequence.constants.instruments.gm_drums as gm_drums
composition = subsequence.Composition(bpm=120, seed=1)
swing = subsequence.Groove.swing(percent=57)
@composition.pattern(channel=10, beats=4, drum_note_map=gm_drums.GM_DRUM_MAP)
def drums (p):
p.hit_steps("kick", [0, 4, 8, 12], velocity=110)
p.hit_steps("snare", [4, 12], velocity=100)
p.ghost_fill("snare", density=0.5, velocity=(20, 40), bias="before")
p.groove(swing)
@composition.pattern(channel=10, beats=4, drum_note_map=gm_drums.GM_DRUM_MAP)
def hats (p):
p.hit_steps("hi_hat_closed", range(16))
p.velocity_shape(low=40, high=90)
p.groove(swing)
@composition.pattern(channel=10, beats=4, drum_note_map=gm_drums.GM_DRUM_MAP)
def euclidean_snare (p):
p.euclidean("snare_2", pulses=5, velocity=60).rotate(2).groove(swing)
A pattern runs again every cycle
A pattern is not a loop recorded once and played back. It is a function, and Subsequence runs it again before every cycle, fresh. That is why the ghost notes land somewhere new in every bar: p.ghost_fill chooses again each time the function runs.
Each time, p carries what is happening at that moment. Two of the simplest things it knows are p.cycle, how many times this pattern has run before, and p.bar, which bar of the piece is about to play, both counted from 0. This pattern, in a composition of its own called counting, prints them each time it runs:
counting = subsequence.Composition(bpm=120, seed=1)
@counting.pattern(channel=10, beats=4, drum_note_map=gm_drums.GM_DRUM_MAP)
def counter (p):
print("cycle", p.cycle, "bar", p.bar, "last of four", p.bar_cycle(4).last)
p.hit_steps("kick", [0])
counting.render(bars=4, filename="counting.mid")
cycle 0 bar 0 last of four False
cycle 3 bar 3 last of four True
cycle 4 bar 4 last of four False
Four bars rendered, and the function ran five times: Subsequence builds each cycle a beat before it plays, so by the end of the fourth bar it had already built the fifth.
A fill every fourth bar
p.bar_cycle(4) says where the bar about to play sits in a cycle of four bars. Its .last is True on the fourth bar of every four, and False on the other three. if runs the lines indented under it only when what follows it is true, so this pattern places a tom fill on the fourth bar of every four, and nothing at all on the rest:
@composition.pattern(channel=10, beats=4, drum_note_map=gm_drums.GM_DRUM_MAP)
def fill (p):
if p.bar_cycle(4).last:
p.sequence(steps=[12, 13, 14, 15], pitches=["high_tom", "high_mid_tom", "low_tom", "low_floor_tom"], velocities=[100, 90, 90, 110])
p.groove(swing)
p.sequence places a note on each step it is given, with the pitch and velocity in the same place in their own lists: the high tom on step 12, the high mid tom on step 13, and so on down to the low floor tom on the last sixteenth note of the bar. .first is True on the first bar of every four.
p.every is a shorter way to do something every so many cycles, and it counts the pattern's cycles rather than bars: in a pattern two bars long, p.every(4, ...) acts every eight bars.
A line three sixteenth notes long
A pattern does not have to be a bar long. This one is three sixteenth notes long, and plays a pedal hi-hat at its start:
@composition.pattern(channel=10, beats=0.75, reschedule_lookahead=0.75, drum_note_map=gm_drums.GM_DRUM_MAP)
def pedal_hats (p):
p.hit_steps("hi_hat_pedal", [0], velocity=80)
composition.render(bars=4, filename="patterns-that-change.mid")
In piece.py, add fill and pedal_hats below the other patterns.
beats=0.75makes it three quarters of a beat long, three sixteenth notes, so it comes round every three sixteenth notes.reschedule_lookahead=0.75tells Subsequence to build each cycle three quarters of a beat before it plays. It builds a beat ahead unless told otherwise, and a pattern shorter than a beat cannot be built further ahead than it lasts, so Subsequence refuses one without this.- It takes no groove, so its hits stay exactly three sixteenth notes apart. A groove counts its steps from the start of the piece, so it would move each hit that falls on the second or fourth sixteenth of a beat.
Its hits fall three sixteenth notes apart and cross the beat, meeting it on every third beat:
1 1.000 note G#2 (44) velocity 80 length 0.083
1 1.750 note G#2 (44) velocity 80 length 0.083
1 2.500 note G#2 (44) velocity 80 length 0.083
1 3.250 note G#2 (44) velocity 80 length 0.083
1 4.000 note G#2 (44) velocity 80 length 0.083
Sixteen hits later, three bars on, they start the bar together with the kick again. The fourth bar ends in the fill:
4 1.000 note G#2 (44) velocity 80 length 0.083
4 4.000 note D3 (50) velocity 100 length 0.083
4 4.292 note C3 (48) velocity 90 length 0.083
4 4.500 note A2 (45) velocity 90 length 0.083
4 4.792 note F2 (41) velocity 110 length 0.083