[SOLVED] stop a gen phasor after one period

    Gen

    brendan mccloskey
    Sep 13 2015 | 11:51 am
    Max Patcher
    In Max, select New From Clipboard.
    Show Text
    Hi I could end up wasting an entire afternoon on this; I've been tinkering with accum, counter, += etc. But gen phasor is pretty simple, right? How can I reset a phasor to zero frequency (and phase?) after it has completed ONE cycle? I intend to send it a frequency (=length) value, it executes that ramp and then returns to zero and stops, awaiting a new or repeated frequency value. Here's a wrong example:
    Thanks Brendan

    • brendan mccloskey's icon
      brendan mccloskey
      Sep 13 2015 | 11:55 am
      . . . . it's for a simple one-shot envelope generator source.
      Share
    • brendan mccloskey's icon
      brendan mccloskey's icon
      brendan mccloskey
      Sep 13 2015 | 2:20 pm
      SOLVED
      Max Patcher
      In Max, select New From Clipboard.
      thanks to an old thread where vichug provided this (in a different context), and thanks to his annotations I hacked it.
      It allows for a one shot 0. --> 1. --> 0. phasor ramp, that waits at 0. Now I can make all sorts of nice sample accurate envelopes. Brendan
    • bertrandfraysse's icon
      bertrandfraysse's icon
      bertrandfraysse
      Sep 17 2015 | 10:01 pm
      Max Patcher
      In Max, select New From Clipboard.
      Here is another slightly different version, I think it's a little better CPU wise.
    • bertrandfraysse's icon
      bertrandfraysse's icon
      bertrandfraysse
      Sep 17 2015 | 10:41 pm
      another version with gate and retrig mode.
      when retrig mode is 0, it allows the ramp to reach 1 even if it receives a new trig. it's made with the codebox, but don't worry, it's not that complicated, and more practical.
      Max Patcher
      In Max, select New From Clipboard.
      I hope this can be of any help to you.
    • vichug's icon
      vichug's icon
      vichug
      Sep 18 2015 | 5:40 am
      well..; happy to have been unknowingly of some help at some point anyway :)
    • brendan mccloskey's icon
      brendan mccloskey's icon
      brendan mccloskey
      Sep 18 2015 | 12:12 pm
      :)
      I tend to hold on to patches like these, never know when they'll come in handy, so thanks again.
    • brendan mccloskey's icon
      brendan mccloskey's icon
      brendan mccloskey
      Sep 18 2015 | 12:16 pm
      Bertrand, those are very economical and transparent, many thanks.
      Brendan
    • bertrandfraysse's icon
      bertrandfraysse's icon
      bertrandfraysse
      Sep 26 2015 | 3:09 pm
      thanks brendan, nice to be of some help.
      there's one little mistake, for timing accuracy, you need to change this (accum (1, trig)
      to (accum (1, trig)
    • Likemushi's icon
      Likemushi's icon
      Likemushi
      Sep 27 2015 | 2:59 pm
      hey! no its ugly , but
      { "patcher" : { "fileversion" : 1, "appversion" : { "major" : 7, "minor" : 0, "revision" : 5, "architecture" : "x86", "modernui" : 1 } , "rect" : [ 54.0, 92.0, 640.0, 480.0 ], "bglocked" : 0, "openinpresentation" : 0, "default_fontsize" : 12.0, "default_fontface" : 0, "default_fontname" : "Arial", "gridonopen" : 1, "gridsize" : [ 15.0, 15.0 ], "gridsnaponopen" : 1, "objectsnaponopen" : 1, "statusbarvisible" : 2, "toolbarvisible" : 1, "lefttoolbarpinned" : 0, "toptoolbarpinned" : 0, "righttoolbarpinned" : 0, "bottomtoolbarpinned" : 0, "toolbars_unpinned_last_save" : 0, "tallnewobj" : 0, "boxanimatetime" : 200, "enablehscroll" : 1, "enablevscroll" : 1, "devicewidth" : 0.0, "description" : "", "digest" : "", "tags" : "", "style" : "", "subpatcher_template" : "", "boxes" : [ { "box" : { "format" : 6, "id" : "obj-7", "maxclass" : "flonum", "numinlets" : 1, "numoutlets" : 2, "outlettype" : [ "", "bang" ], "parameter_enable" : 0, "patching_rect" : [ 332.0, 190.0, 50.0, 22.0 ], "style" : "" }
      } , { "box" : { "id" : "obj-5", "maxclass" : "scope~", "numinlets" : 2, "numoutlets" : 0, "patching_rect" : [ 284.0, 297.0, 130.0, 130.0 ], "style" : "" }
      } , { "box" : { "id" : "obj-4", "maxclass" : "button", "numinlets" : 1, "numoutlets" : 1, "outlettype" : [ "bang" ], "patching_rect" : [ 284.0, 147.0, 24.0, 24.0 ], "style" : "" }
      } , { "box" : { "id" : "obj-2", "maxclass" : "newobj", "numinlets" : 1, "numoutlets" : 1, "outlettype" : [ "signal" ], "patching_rect" : [ 284.0, 190.0, 41.0, 22.0 ], "style" : "", "text" : "click~" }
      } , { "box" : { "id" : "obj-1", "maxclass" : "newobj", "numinlets" : 2, "numoutlets" : 1, "outlettype" : [ "signal" ], "patcher" : { "fileversion" : 1, "appversion" : { "major" : 7, "minor" : 0, "revision" : 5, "architecture" : "x86", "modernui" : 1 } , "rect" : [ 394.0, 165.0, 600.0, 450.0 ], "editing_bgcolor" : [ 0.9, 0.9, 0.9, 1.0 ], "bglocked" : 0, "openinpresentation" : 0, "default_fontsize" : 12.0, "default_fontface" : 0, "default_fontname" : "Arial", "gridonopen" : 1, "gridsize" : [ 15.0, 15.0 ], "gridsnaponopen" : 1, "objectsnaponopen" : 1, "statusbarvisible" : 2, "toolbarvisible" : 1, "lefttoolbarpinned" : 0, "toptoolbarpinned" : 0, "righttoolbarpinned" : 0, "bottomtoolbarpinned" : 0, "toolbars_unpinned_last_save" : 0, "tallnewobj" : 0, "boxanimatetime" : 200, "enablehscroll" : 1, "enablevscroll" : 1, "devicewidth" : 0.0, "description" : "", "digest" : "", "tags" : "", "style" : "", "subpatcher_template" : "", "boxes" : [ { "box" : { "id" : "obj-9", "maxclass" : "newobj", "numinlets" : 1, "numoutlets" : 1, "outlettype" : [ "" ], "patching_rect" : [ 42.0, 64.0, 72.0, 22.0 ], "style" : "", "text" : "mstosamps" }
      } , { "box" : { "id" : "obj-8", "maxclass" : "newobj", "numinlets" : 0, "numoutlets" : 1, "outlettype" : [ "" ], "patching_rect" : [ 42.0, 17.0, 30.0, 22.0 ], "style" : "", "text" : "in 2" }
      } , { "box" : { "id" : "obj-7", "maxclass" : "newobj", "numinlets" : 2, "numoutlets" : 1, "outlettype" : [ "" ], "patching_rect" : [ 176.0, 83.0, 36.0, 22.0 ], "style" : "", "text" : "latch" }
      } , { "box" : { "id" : "obj-6", "maxclass" : "newobj", "numinlets" : 1, "numoutlets" : 1, "outlettype" : [ "" ], "patching_rect" : [ 171.5, 175.0, 46.0, 22.0 ], "style" : "", "text" : "history" }
      } , { "box" : { "id" : "obj-5", "maxclass" : "newobj", "numinlets" : 1, "numoutlets" : 1, "outlettype" : [ "" ], "patching_rect" : [ 104.0, 175.0, 51.0, 22.0 ], "style" : "", "text" : ">= 0.99" }
      } , { "box" : { "id" : "obj-1", "maxclass" : "newobj", "numinlets" : 0, "numoutlets" : 1, "outlettype" : [ "" ], "patching_rect" : [ 193.0, 33.0, 30.0, 22.0 ], "style" : "", "text" : "in 1" }
      } , { "box" : { "id" : "obj-2", "maxclass" : "newobj", "numinlets" : 1, "numoutlets" : 1, "outlettype" : [ "" ], "patching_rect" : [ 46.0, 133.0, 80.0, 22.0 ], "style" : "", "text" : "!/ samplerate" }
      } , { "box" : { "id" : "obj-3", "maxclass" : "newobj", "numinlets" : 2, "numoutlets" : 1, "outlettype" : [ "" ], "patching_rect" : [ 46.0, 173.0, 47.0, 22.0 ], "style" : "", "text" : "phasor" }
      } , { "box" : { "id" : "obj-4", "maxclass" : "newobj", "numinlets" : 1, "numoutlets" : 0, "patching_rect" : [ 46.0, 310.0, 37.0, 22.0 ], "style" : "", "text" : "out 1" }
      } ], "lines" : [ { "patchline" : { "destination" : [ "obj-7", 1 ], "disabled" : 0, "hidden" : 0, "source" : [ "obj-1", 0 ] }
      } , { "patchline" : { "destination" : [ "obj-3", 0 ], "disabled" : 0, "hidden" : 0, "source" : [ "obj-2", 0 ] }
      } , { "patchline" : { "destination" : [ "obj-4", 0 ], "disabled" : 0, "hidden" : 0, "source" : [ "obj-3", 0 ] }
      } , { "patchline" : { "destination" : [ "obj-5", 0 ], "disabled" : 0, "hidden" : 0, "source" : [ "obj-3", 0 ] }
      } , { "patchline" : { "destination" : [ "obj-6", 0 ], "disabled" : 0, "hidden" : 0, "source" : [ "obj-5", 0 ] }
      } , { "patchline" : { "destination" : [ "obj-7", 1 ], "disabled" : 0, "hidden" : 0, "source" : [ "obj-6", 0 ] }
      } , { "patchline" : { "destination" : [ "obj-7", 0 ], "disabled" : 0, "hidden" : 0, "source" : [ "obj-6", 0 ] }
      } , { "patchline" : { "destination" : [ "obj-3", 1 ], "disabled" : 0, "hidden" : 0, "source" : [ "obj-7", 0 ] }
      } , { "patchline" : { "destination" : [ "obj-9", 0 ], "disabled" : 0, "hidden" : 0, "source" : [ "obj-8", 0 ] }
      } , { "patchline" : { "destination" : [ "obj-2", 0 ], "disabled" : 0, "hidden" : 0, "source" : [ "obj-9", 0 ] }
      } ] } , "patching_rect" : [ 284.0, 236.0, 38.0, 22.0 ], "style" : "", "text" : "gen~" }
      } ], "lines" : [ { "patchline" : { "destination" : [ "obj-5", 0 ], "disabled" : 0, "hidden" : 0, "source" : [ "obj-1", 0 ] }
      } , { "patchline" : { "destination" : [ "obj-1", 0 ], "disabled" : 0, "hidden" : 0, "source" : [ "obj-2", 0 ] }
      } , { "patchline" : { "destination" : [ "obj-2", 0 ], "disabled" : 0, "hidden" : 0, "source" : [ "obj-4", 0 ] }
      } , { "patchline" : { "destination" : [ "obj-1", 1 ], "disabled" : 0, "hidden" : 0, "source" : [ "obj-7", 0 ] }
      } ], "dependency_cache" : [ ], "embedsnapshot" : 0 }
      }
    • luvulongtime's icon
      luvulongtime's icon
      luvulongtime
      May 06 2022 | 12:48 pm
      Note to self; check the forums next time before you try to solve something and end up banging your head against the wall...
      Apparently the banging helped so here's my version
      Max Patcher
      In Max, select New From Clipboard.
      And to add insult to injury; Looks at patches in thread > hey, i recognize these! Searches folder with handy stuff saved from the forum; well i'll be darned!
    • Graham Wakefield's icon
      Graham Wakefield's icon
      Graham Wakefield
      May 06 2022 | 3:46 pm
      Use accum, not phasor.
      Hz -> / samplerate -> accum -> clip 0 1 will give you a one shot ramp. A trigger to the accum's 2nd inlet will reset it.
      If you want the end of the ramp to land at 0 again, send the result through a wrap 0 1.
      If you don't want the accum to start counting when the patch loads, use accum @init 1
      Graham
    • Neil Baldwin's icon
      Neil Baldwin's icon
      Neil Baldwin
      May 03 2023 | 6:30 pm
      Been struggling with this myself today trying to implement one-shot sample buffer playing using phasor. The accum method makes more logic sense but if I remember correctly there's mention of this in Generating Sound & Organising Time that says don't use that method for different pitches because of aliasing. Maybe I remembered wrongly.
      Edit: I should say that I'm trying to implement sample playback that can do variable pitch, forwards/reverse and looping/not-looping. Aware this is probably one of the most fundamental things but so far the mental gymnastics are leaving me fatigued. I'm still not past the part where you stop thinking like Max.
    • Graham Wakefield's icon
      Graham Wakefield's icon
      Graham Wakefield
      May 03 2023 | 7:25 pm
      Using accum for different pitches is fine, accum will happy accumulate non-integer values as you need. But one thing to watch out for, if you are playing from a buffer~ you need to make sure you are reading with some kind of interpolation, since you aren't going to be reading integer sample positions (I suspect that's what you were thinking of from the GO book).
      Basically when you play a buffer at almost any desirable pitch, you need to move through it at fractional sample steps, which means you need data from points between actual neighbouring sample values in the buffer itself. This data doesn't exist so you have to approximate it from the neighbouring sample values. That's what interpolation does. The simplest form of interpolation is linear, which means guessing that the path from one sample to the next is a straight line. It's not the best interpolation, but it is very cheap and does a great job a lot of the time.
      For that, you can send the accum output to a [peek mybuf @interp linear], where mybuf is whatever your buffer's name is.
    • Neil Baldwin's icon
      Neil Baldwin's icon
      Neil Baldwin
      May 03 2023 | 8:00 pm
      Thanks Graham, appreciate the reply. I think you're right about my ill-remembered GO quote (don't have my copy in front of my right now, will dig back through when I'm home at the weekend).
      I think I'm lacking the logic chops to understand how you stop a sample at an arbitrary point (given that sending a 1, or whatever, to drive your accum object is....always a 1 so there's no way, in my brain, that you can can internally stop a buffer from playing. Obviously allowing the index to go beyond 1. will just run out of data and it stops making sound. But say you have a 5 second sample in a buffer and only want to play it from 1s to 2s and stop, that seems impossible under control). I will add that I'm a seasoned Max developer but have taken my first steps in Gen. I guess I'm falling for all the Gen Beginner Traps 🤣
    • Neil Baldwin's icon
      Neil Baldwin's icon
      Neil Baldwin
      May 04 2023 | 12:57 pm
      Finally something is sinking in! 🤣
      Made a little Gen sample player that has pitch control, direction control, optional looping and the ability to set a start->end slice of the buffer. I feel like I really achieved something here. Went back to Graham's book to realign myself with Gen-think. 🙏 I'd be curious to hear from any season Gen people to see where I might have done better. 👍
      basicBufferPlay.maxpat
      maxpat 33.04 KB