gtz polyrhythmic step sequencer progress

  • This almost works. It's surprisingly close. And yet, it kinda doesn't. So let's just say that up front.

    At first glance, it's a pretty generic step sequencer. Currently optimized for varibrightness-enabled 256 or 128. Not sure how it'll work on 2011 models. Not sure it's worth fixing for 64, or that a downgraded interface without without variable brightness would make much sense either.

    So, most of you can't use it. Is that enough disclaimers?

    Okay! What are we lookin' at?

    It's a step sequencer, yes. Each measure is divided up into 16 steps across, and each row represents a pitch, currently from F major pentatonic. Drawing patterns on the grid edits the pattern of MIDI notes that play. Right? Good.

    That control is triggered by pressing and releasing a button without touching any other buttons. And the notes are playing on MIDI channel 16.

    Holding a button and pressing a second button in that same row... The first button does nothing, but the second button you press redefines how many steps in the measure that row's divided into. Everything to the left of and including that button is active. Everything to the right of it is disabled.

    So, what does that mean? Well, a measure divided into 8 slices gives twice as long to each slice than a measure divided into 16 slices. A measure divided into 9 slices moves a little bit faster than 8, and might be thought of as quarter-note triplets. And so on. Each row can be divided independently of the others, and you can change them in real-time.

    In theory, every row starts and ends at the same time, creating even polyrhythms. That's the part I'm stuck on -- my clock isn't dividing correctly, and I haven't worked out why.

    Oh, and one more feature:

    I mentioned that by default, every note was on channel 16? That's because every row was divided into 16 slices. Change a row to 5 slices, and those notes go out on channel 5. See the pattern?

    But, why would you want that? 'cause that lets you adjust your tempo-based audio effects to match the different timebases you're feeding into them. Or you might want your symbols to use a brushed sample in triplet-based time signatures, and sticks in duplets. Or something. Really, it's just an excuse to re-assign MIDI channels per-row on the fly. Which, in conjunction with the time alterations, is pretty fun.

    So, there we are. Any suggestions on the clock?

    (I was thinking maybe I should throw that out in favor of looping an empty WAV file. I could evaluate the playhead position as a fraction from 0.-1., multiply that by each number of divisions, round those, and we're good. But how to convert BPM into playback speed?)

  • I know, I know, there should be a video. But have I mentioned that the clock isn't right?

  • Also worth mentioning:

    Half of this is in JavaScript. (and crappy JavaScript, at that) I'm a web guy, and that got me results faster, but it's really not optimized.

    Specifically, the process of spitting out 256 brightness levels and converting those into four quadrants.. that could be stramlined. A lot. But I couldn't figure out how to convert the list into a jitter.matrix, so there's a lot of JS looping and a lot of zl nonsense, and I'm sure most of that's superfluous.

    So.. don't use this as a code example, except in the cautionary sense.

  • sounds awesome. i'll give it a go tomorrow. thanks.

  • Strange. They're probably new to max 6.x or whatever.

    If you just lose the dot, they're the same objects. But there are kind of a lot of them. Crap.

    (I'm not sure what's up with the naming convention; I think c74 added those to help autocomplete and the help system?)

    let's see if I can't do a find-and-replace on all that in the text editor...

  • Let's try this...

    That one didn't load in presentation view. Replaced...

  • And I have to say, as practical as it is to use brightness levels to express more complex information, this really does "look like math" when you see it in action.

  • this looks pretty darn cool. i love polyrhythms. when i was a drummer i had this crazy beat that was 2 (left hand) against 3 (right foot) against 4 (left foot) against 5 (right hand). now i can do it again; only this time with a step sequencer. and i can add more limbs! can't wait to check it out.

  • I made some progress fixing the clock. The polyrhythms lined up properly (had to rethink how and when numbers were getting rounded), but the tempo wasn't completely accurate / locked in (so it'd drift from your other software). I was experimenting with a way around that, and crashed max completely, losing hours of work.

    So... I'd recommend waiting a day or so before checking it out. 'cause it sounds like you're going to want that feature to work properly. =)

  • suggestion fer yer clock needs:


  • Will definitely check that out.

    Attached is a draft playing off max's transport object. It seems to work well. Better than what I had previously, at least. And while I don't know the first thing about syncing clocks up with other apps, someone who does will probably be happy that I at least tried to use a more standardized approach.

    ...but what you're offering is a lot more flexible, and flexible is good. =)

  • note to self:

    Your alarm clock goes off in three hours. Also, you're dumb.

  • Updated the display code, per raja's suggestion of the 256 element loop.

    I'm still compiling my list(s) in JS and outputting those all at once, because I don't trust the outlet not to overrun [zl group 64] otherwise. So, that might not be as streamlined as it could be, but it doesn't feel jerky anymore (the clock fixes probably helped too), so I'm going with it.

    It's actually pretty stable now. I'll play with raja's phasor~ suggestion for more flexible sync (and non-sync) later, but the only thing stopping this from being a 1.0 release in the doku is that you're arbitrarily stuck in F Major Pentatonic right now. (I also need to add instructions and credits)

    I don't know if it makes sense to add a full on scale/mode selector; I feel like the core functionality for most users is going to be in triggering percussion samples. I'm sort of thinking a simple selector between "chromatic", "user1" and "user2" might be the way to go, where those are all external text files the user can modify to suit their own needs. But if you think it's important to let the user choose "c# mixolydian" from a series of dropdowns or something, I'm sure we can do that.

    (I'm also thinking about sacrificing the top row to be pages/presets. And maybe using the "disabled" buttons to toggle each row between the present behavior and an additional mode, but I'm not sure what that means yet. Much less how much of a restructuring effort will be required. And I'm not thrilled about the fact that those buttons aren't present on a default row of 16 slices. So maybe it defaults to 8? I don't know. Figure that's all 2.0 stuff...)

  • I'm really looking forward to 1.0 of this - not tried it yet. I'd be no help in re-writing so will wait for it to be declared stable. :)

    Just want to add my name to the list of people who would definitely find it useful to have a scale/mode selector. Polyrhythmic melodies ftw.

  • @restlessboy,
    Knowing that people care about scales/modes is definitely valuable.

    I don't know. I agree on the polyrhythmic melodies, but it's still a relatively short repeating block; the downfall of any step sequencer. Adding polyrhythms and keeping the tempo very low will stretch that block out a ways, but is it enough? (I'm hoping that changing the divisions/MIDI channels adds enough sonic variety to overcome that shortcoming.)

    I personally work around that by using the MIDI notes indirectly, to trigger other things.
    But I don't need scales for that...

  • I might change one fundamental element of the interface.

    Right now, pressing two buttons in the same row triggers the division change. I'm considering making that two buttons that are neither in the same row nor the same column. (so that "same row" and "same column" can both be used for other things)

    More specifically, I'm thinking about stealing a feature from my long-forgotten "sidestep" app. In that one, the second press of a two-button gesture "scrolled the window". So, there was a larger pattern, and you could shift it about underneath the grid. This was the opposite of how "plane" handles it; moving up or down transposes pitch; moving left and right offsets time. ("sidestep" also allowed diagonal movement of any distance at any angle, but we'd have to sacrifice that for the division change thing.)

    That's not 100% going to happen, but I'm definitely considering it. So... don't get too used to the control scheme. =)

  • more velcro

  • You know, none of my monome devices have any velcro on 'em. I've been sort of a purist, but then this happened:, you may well be right.

  • Trick question.

    They do have variable brightness. But not per-LED. One brightness level for the whole grid.

    (also: I wish)

  • There was talk of a firmware update for GS to unlock that feature, but the results weren't up to Brian's standards. So, that got scrapped. Gotta respect the guy for sticking to his guns on quality control (despite a LOT of pressure to compromise).

  • "I might change one fundamental element of the interface."

    ...but not to what I described up there.

    (The transposition-in-time-and-pitch thing might still happen; it just won't be with a two-button gesture.)

    The two-button thing will be strictly for establishing divisions. But where both presses currently have to be on the same line, they'll soon modify a range of adjacent rows. (it'll affect every row inclusive of the two buttons you're pressing)

    It'll make sense when you see it.

  • Nothing too drastic changed here:

    While a button is held, press a second button to change divisions. That's mult-row now.

    (For every row between and including the two buttons you pressed, everything up to and including the column where that second button was pressed will be considered "active", time will divide by that many steps, and MIDI channels will be distributed accordingly.)

    Press and release in the active area to toggle a beat on or off.

    Press and release in the inactive area to toggle whether or not that row is in the mysterious alt mode which doesn't actually do anything. There's no alt mode yet. But the inactive buttons have two brightness levels to reflect the toggle, so we can pretend.

    Still to come:
    * scales
    * "alt mode" (it's probably just a speed doubler)
    * something crazy not yet mentioned

  • "better than nothing" support for older monomes added.

    I do not recommend this on non-varibright devices. But at least it's possible to use there now.

    (If I could make the highlight be more of a momentary blink, that would help a great deal. But my experiments towards that end did not come out well at all.)

  • Got some errors :

    js: bad outlet index 0
    error loading serialosc
    jpatchline_new index out of range
    jpatcher_plugin: box missing outlet number 2 (&1)
    jpatchline_completeconnection:index out of range

    Don't get anything on my monome...

    [monome256 old version, 2009 i think / serialosc / mac 10.7.3]

  • crap.

  • js: bad outlet index 0, I wouldn't worry about. I actually see five of that when I first load the patch. And then it works.

    Error loading serialosc... either put a copy of serialosc.maxpat in your max search path, or in the directory with these files. I didn't provide one 'cause you should already have it.

    jpatchline errors... no clue what that's about. what version of max are you running?

    not getting anything on your monome: I'd point back to the error loading serialosc. You'll see no LEDs until you connect.

    Additionally, you'll have to turn off the "disable if your monome doesn't support pre-led variable brightness" checkbox.

  • This won't help w/ matino's problem, but I just realized the mono display's pretty messed up on a 256. (the version I posted was tested only on 128)

    Fixin' that now...

  • mono display works across a 256 now.

    also, added a seisure-inducing display option for non-varibright, which probably helps to clarify what you're looking at if you can avoid choking to death on your own tongue.

  • Added a handful of new controls.

    The scales/modes dropdown selects between various scales and modes.

    The keyslider above that selects the base note of your scale. This is further controlled by the octave selection number box.

    The duration slider determines how long notes are. At 100%, each note lasts the full length of that row's division level. At 50%, it's half that. And so forth. (I may refine that a bit; 100% is probably 1ms too long...)

    ...and that's probably all of it for this version.

  • Ok the only errors now are bad outlet. Then it says binding to port 0.

    It wont connect... I tried thru page or without, in the menu i see all my pages, i can select wich one i wanna use but it never connect. In the max window no error are added wich seems weird no?

  • There's two lines towards the top of the JS file which read:


    If you delete those two lines, the bad outlet errors will go away. They're a timing problem in Max itself. (the JS file is allowed to run instructions the moment it's loaded, which is before loadbang, and before the JS object is even rendered on screen. So when the file first loads, JS is trying to do some stuff that Max isn't ready for.

    From your perspective, there's no reason for those things to occur, and no reason not to delete those lines. But they are useful to me in development, because they're also executed automatically every time I save the JS file.

    With or without these lines, every time I make any JS change, it will clear the patterns out of the step sequencer, because those patterns are stored in JS itself. And it will assign default values to your display options. But the patch doesn't know that your patterns are cleared. And your display option checkboxes still reflect the values you set.

    So, I added those lines. They force the grid to refresh so you don't see the phantom patterns, and signal the max patch to reset some things within the patch.

    So that's why you're seeing "bad outlet" errors.

  • re: issues connecting in pages...

    I don't know the first thing about pages. The JS thing might fix that for you, but try the patch directly, see if that much works.

  • "something crazy not yet mentioned"...

    I'm still not 100% sure how (or if) it's going to fit into this patch, but here's what I've been obsessed over for the past month or two:

    It doesn't look like much yet, but I swear this is powerful.

    The display part is easy enough. But, my editing scheme (your button presses will have varying influence on each pattern based on your selected position on the XY pad)... developing that part hurts my brain.

  • damn, that's cool!

  • I just downloaded this to have a go but found I can't connect. There's not the usual serialosc dropdown box. Am I missing something obvious?

  • Okay. I'm only using the runtime version of max.

    I've tried putting serialosc.maxpat into the polystep folder. Also into a Cycling 74 folder in Library/Application Support (I created the folder mysel - it wasn't there already).

    Is that right? I don't really know max well enough to understand the search path.

    Thanks for your help with this.

  • Interesting. In the full version of Max, there's a menu under "options / file preferences" where you can add and remove directories from the search path. Runtime version doesn't appear to have an "options" menu.

    So... possible there's a default path that you ought to use, but I don't know what it is.

    As an alternative, just copying it into the polystep directory ought to do it. Then reload.

  • I'm not working on this right at the moment, but I did just stumble across a solution to the timing issue that was causing the "bad outlet number" errors.

    Look at the embedmessage description, and the save() function example. It's that.

    Consider this a bookmark so I can find it later. =)