Generating Sound [go.ramp.mul] and [go.ramp.div] abstractions - reset question

Steve Meyer's icon

I am trying to use the Generating Sound book objects to create a ramp-based multi-track/lane sequencer with polymeters. It is supposed to have the following functionality:

  • Each sequencer track produces a ramp

  • Each sequencer track ramp has an independent ramp frequency between 2 and 16 16th notes (this is the polymeter part)

  • A "super measure" is defined as the number of measures that can pass before all ramps resync/reset to 0.

I am having trouble getting the last bullet working. I cannot get [go.ramp.mul] and [go.ramp.div] to recognize a trigger from a [go.ramp.trig] object that corresponds to the "super measure."

See the attached patcher, that demonstrates my issue and has comments that (I hope) explain what I am trying to do. This patcher only has a single track/sequencer lane for the sake of simplicity. What I want to have happen is for the ramp in the bottom scope (labeled Seq Lane 1 Ramp) to reset with every trigger that you can see in the top-most scope (labeled Super Measure Trig).

Am I misinterpreting how the [go.ramp.mul] and [go.ramp.div] abstractions work?

Thanks,
Steve

Max Patch
Copy patch and select New From Clipboard in Max.

👽!t W∆s ∆lienz!👽's icon

Hi, not entirely sure i follow what you're trying to do, but i think if you want a different sloped ramp than your master 'phasor'(which seems to be running at the 'super-measure' frequency anyways) but one that still resyncs to that phasor, so that instead of this:

simply using the super-measure 'phasor' for the super-measure ramp

it might look like this where the ramp, even when it doesn't reach all the way to the top, resets with the super-measure trig:

with a differing(longer here) slope than the super-measure phasor might have, it still resets with the super-measure

i was able to get it to do that by adding this into my own version of the 'go.ramp.div' abstraction:

what that means is that i have to trick the 'syncing' function to see a phase of '0' as the 'newer phase(middle inlet)' because the 'newer phase' normally received there at the point where your super-measure trig attempts to reset, is not the slope you expect at that very point to allow it to reset all the way to 0.

you can either do what i've done and make a different version of your 'go.ramp.div' abstraction(rename it as your own) with those changes, or ...i'd suggest you copy/paste your own version anyways and then you can create extra outlets to snoop the exact values you might be getting right at that point(like use a 'latch' operator and output the slopes at different points to see why they behave the way they do and then you can understand the math better to adjust everything yourself, perhaps without even having to create the little hack i made)... either way, you can tell that when you send a reset into the third-inlet(of go.ramp.div), it's switching to get a 'newer phase' but that newer-phase isn't resetting things to 0; there may be something in the rounding/truncation there or the difference/subtraction operation before it that is causing the 'newer-phase' and the 'accumulate-phase' to both be the same at certain points when you actually need the 'newer-phase' to be 0 right at the reset point.

hope that all makes sense and helps 🍻

Steve Meyer's icon

Raja, thank you for taking a look at this and showing the modification. That is exactly what I was trying to achieve. I wanted the super measure to reset the sequencer ramp even when the sequencer ramp was not complete:

Intended behavior for sequencer lane 1 ramp: reset ramp to zero when super measure trig happens even if seq ramp has not completed.

For extra context, the goal is to allow all the sequencer ramps (this simplified example only has 1 for explanation's sake) to create polymeters that phase against each other for interesting rhythms, but all snap back to a starting point every N bars. The ramps coming out of the [gen~] object would then be driving independent [what~] objects that contain different rhythms.

Your explanation helps me to understand the comments in the original [go.ramp.div]. "Reset" in [go.ramp.div] seems to mean resetting the output phasor's frequency immediately rather than when the input phasor's ramp wraps back to zero. I was interpreting "reset" to refer to the ramp irrespective of frequency, meaning that it would reset the ramp back to zero.

👽!t W∆s ∆lienz!👽's icon

helps me to understand the comments in the original [go.ramp.div]. "Reset" in [go.ramp.div] seems to mean resetting the output phasor's frequency immediately rather than when the input phasor's ramp wraps back to zero

happy to help :) ya, that chapter really helps elucidate the basic relationship between slope, frequency, and phase(in this case, really shows the distinction between resetting the phase-accumulation to 0(altering the phase directly), and simply resetting how that phase-accumulation is scaled(altering only the slope/frequency by scaling the rate by which the phase changes))... i'd not studied the 'mul' and 'div' abstractions so closely yet(been making my own, based on the book's more basic description of using the accumulator to scale the slope with multiplication/division or offset with addition/subtraction, all then wrapped within 0 and 1, and then whenever i need a reset like here, i just sent a click directly into the right-inlet of a '+=' op; this context shows a more specific use-case where the timing of the parameter change is accounted for in terms of reset... i've never been that specific but it's really cool to see how it works), was good to get this practice. Cheers!