i’ve been messing around with a rewrite of
pattern_time which cleans up its methods a bit and captures some of the things I’ve been baking into cheat codes 2. prompted by @okyeron’s ping and my own feeling of “stuckness”, i figured it’d be good to the WIP state to snag feedback + help cleaning it up and getting it wrapped
this is not release-ready or for general use – expect dragons
:rec(state), where 1 is start and 0 is stop
:play(state), where 1 is start and 0 is stop
:overdub(state), where 1 is on and 0 is off
:loop(state), where 1 is looping playback and 0 is 1-shot playback
.rec_statereturns 1 (recording) or 0 (not recording)
.play_statereturns 1 (playing) or 0 (not playing)
.overdub_statereturns 1 (overdub enabled) or 0 (overdub disabled)
.loop_statereturns 1 (looping playback) or 0 (1-shot playback)
.record_pendingreturns true or false, depending on
sync record to clock?param
.start_pendingreturns true or false, depending on
sync launch to clock?param
.namereturns the name of the pattern (see param note)
when adding a pattern to a script, we’ll use
longPatternName = pattern_time.new("name"), where the “name” is passed to the new PATTERNS param menu.
if pattern time is added to a script, a
PATTERNS param menu is created and inherits the names of the script’s patterns. if no name is provided *
sync record to clock? /
*alias*_sync_recording: use the global clock to sync pattern recording to start on beat and record for a fixed number of beats
—> rec duration (beats) /
*alias*_rec_duration: set the number of beats that the clock-synced recording should last (up to 256 beats)
- —> rec duration (beats) /
sync launch to clock? /
*alias*_sync_start: wait until a clock event before launching pattern playback
—> timing /
*alias*_launch_timing: wait till next beat or next bar to launch pattern playback?
- —> timing /
*alias*_quantization: turn quantization on/off
passive stuff, all working in the background
as a recording is being made (
:rec_event), each entry commits the
.time between itself and the event before it. after this is calculated, that duration is divided by
clock.get_beat_sec() to give us
after the recording is committed,
:calculate_quantum is automatically called, which rounds the
.time_beats to the nearest eighth note value. this is committed as an entry’s
as the pattern plays back, it is either using the
.quantum to determine when to move to the next event (using either
:quantize(1) is executed, then the metro that drives unquantized playback stops and the clock-synced
:quantized_advanced function takes over.
what happens is basically a “runner” system – since our quantum is measured in 1/8th notes, we total how many 1/8th steps an event should last for and a runner keeps apace at an 1/8th note count – so if an event’s duration is 3 quantum, the runner will have to reach 3 before moving onto the next event in the pattern.
most of this feels really solid, but i would love some eyes on the quantization stuff. in the above repo, i’ve included a revised copy of earthsea that uses the proposed changes. on the grid: 1,1 is record start; 1,2 is playback; 1,3 is overdub; 1,7 is loop enable; 1,8 is clear.
- if you keep maiden open while recording a pattern, you’ll see a printout of the calculated quantum and time total. oddly, when clamping recording to 8 beats at 120 bpm, you’ll see a record time total of
4.0003619194031(which is passable) and a
quantum total: 8.375. could use some help debugging this.
- quantization also just doesn’t feel right for earthsea, where expressive + dynamic timing is much more critical. 1/16th notes felt ineffective, 1/4 notes a bore, but 1/8th doesn’t 100% gel either…
- things also get wiggly when overdubbing comes into play, since note-ons and note-offs can become confused. i can’t tell how much of this could be mitigated in
pattern_timeand how much should be handled by the script.
also, none of what i’m sharing has to be the baseline – if someone can approach things from a totally different angle with more desirable results, that’d be super! i just could use some extra hands + brains on this challenge and figured sharing some work might help