Tool idea: Euclidean rhythm generator

joule, I think you’re right about the multiple generators. Three layers (like you suggest) sounds like a good idea.

Anyway, I am eager to prototype this. Mmm, weather’s awesome right now, so probably tomorrow evening!

joule, I think you’re right about the multiple generators. Three layers (like you suggest) sounds like a good idea.

Anyway, I am eager to prototype this. Mmm, weather’s awesome right now, so probably tomorrow evening!

Sounds awesome. My idea was to have an “add generator” button as seen in the mock-up. Maybe to add up to say 8 generators or more (due to the cool mute workaround described in OP that would need their own ‘blank note’ generators and could easily stack up). For this mute trick to work, generators should be processed serially from left to right.

I’m not completely sure about the rounding option described above, as I haven’t thought that through very deeply. But i “feel” that notes could possibly be snapped differently in this kind of routine, which is potentially interesting.

Also the lower part in the screenshot generators might not be very clear. It’s how I envision maximum flexibility/usability, but you might have better ideas.

  1. Seq mode

1a) Stretch - streches the whole final sequence to n number of lines. (n = stretch/cycle value box)

1b) Cycle - repeats the sequence in its original state n number of times (n = stretch/cycle value box)

1c) Oneshot - inserts the sequence only one time. Can be placed by using the Seq offset parameter (kind of a global offset for any track pasted)

Seq offset is “rotating” the final result, naturally.

Would be fun to have a generator like a tool where you can crank the numbers and get a track in a pattern generated as a result.

Have you tried this one;http://www.renoise.com/tools/danushri

OK, weather seems much less hospitable today so I fired up xStream and a did this little thing:
https://gist.github.com/bjorn-nesby/648b8a318f9f59d00227cc5167c0e6c3

Euclidean.gif?raw=1

You’ll have to imagine what that GIF sounds like, but I can tell you that it’s pretty funky :slight_smile:
To install, select the code from the gist above and paste it into xStream (see picture)

paste_clipboard.png?raw=1

It’s really just a single “generator” function, but it’s really easy to play around with. By default, the tool streams to the pattern in real-time when you hit play + edit.
But you can also press the TRK and SEL buttons in the toolbar to write output to the track, selection (two modes: anchored relative to the pattern or selection itself).
And add it to the “favorites grid” to make it keyboard/MIDI assignable :slight_smile:

Note that in this version, only the first generator (column #1) can be controlled visually using sliders etc. - but you can scroll down in the code to see the last four generators and change their values. Changes are immediately reflected in the output while the tool is streaming (“live coding”).

@joule: technically, I’ve implemented “invert” - great idea - but not “note-off masking”. It could be done by letting the generator examine the output buffer, but I wanted to keep things simple to begin with…
Also, while four of five generators are currently represented as manually specified code, I actually would like to represent them as arguments, as you’d then be able to include them in presets.
The reason it currently works like this ATM is twofold: I want to make sure we establish a sensible range for arguments (for example, steps are right now between 1-32, and offset between -16 and 16). And secondly, because having all those arguments on the screen would simply take up too much space - not the first time I’ve experienced this problem, so an upcoming version of xStream will most likely support “grouped/tabbed” arguments, somehow. But even then, this is still a pretty good “Euclidean playground” :lol:

@danoise,

This is pretty awesome. Looks very promising. I’ll have to get a bit more into xstream, but from what I can tell this “platform” seems sufficient for the task! Yeah some improved GUI capabilities, sure.

If I learn this a bit better, I could add what I want. Like stretching sequences, for example.

Did you forget the instrument value? That might be handy :slight_smile:

Did you forget the instrument value? That might be handy :slight_smile:

Eh, I absolutely did. Hacking opportunity granted.

I suggest binding to the selected instrument? Add an argument and specify “bind” and “rns.selected_instrument_index_observable” as the value :slight_smile:

I wanted it being able to use different instruments. Might as well…

Here is a model with instruments included: http://pastebin.com/fQJs1eBj

EDIT: And here are blanknotes added that can be used for muting clashing notes: http://pastebin.com/MajzWD95

EDIT2: Added a cycle parameter to restart the Euclidian pattern every Nth line. Good for pattern breaks or when you for instance discover that only the first half of a rhythmic element sounds good. http://pastebin.com/MS2ynB3S

@danoise: Can you help add a “stretch” function? The parameter should optimally allow for perfect stretching both dividing by three or multiplying by three (for example), so a percentage value would not be accurate enough :wacko: I think we’d have to add some delay value maths, making everything run thru a dly value calculator.

This would become awesome if the xStream GUI will be able to show several generators :slight_smile: I would also add a global “restart every Nth line” parameter in that case.

I also thought about refining the blanknotes parameter by splitting into two separate toggles: “Notes are blanks” and “Leave rests as is”. By this we’d have the flexibility of inserting ghost snares into the same column without overwriting anything, for example. Or write a low velocity hi-hat on inverted notes into the same column as high velocity hi-hat.

Cool! I will take a look at the stretch feature, think I have an idea about how it could be done.

I also thought about refining the blanknotes parameter by splitting into two separate toggles: “Notes are blanks” and “Leave rests as is”. By this we’d have the flexibility of inserting ghost snares into the same column without overwriting anything, for example. Or write a low velocity hi-hat on inverted notes into the same column as high velocity hi-hat.

That’s pretty simple actually. By the time you define the ‘xline’, it already contains the existing pattern data so you just define each characteristic instead of redefining the entire column (like I did in my example). So, set the note_string only, and the rest will remain untouched.
Also, when you leave a column blank - as in {} - xStream has a global option for whether this should retain or clear existing data…

Yes, I will split the blanknote feature as suggested.

Actually, I suspect it might be a good idea to make this into a separate tool later. The GUI is getting more complicated and would benefit from being streamlined. I also envision separating the euclidean parameters from all special parameters (invert, offset, mute et c) - i e making “euclidean pattern” and “generator” two different entities. Euclidean setting would then be selected in a list in each generator. By this we could use the same euclidean setting in two different generators, which is helpful when playing around with this kind of “layered” processing (mutes/inverts into same column).

I can see this tool being very useful for making hi-hat patterns especially.

The next step would be to make a generator being able to act as a “modifier” and not just a “paster”, i e increase note value by 2 and decrease velocity by 20 according to a euclidean pattern :slight_smile: Yeah, stuff like this calls for a carefully made GUI.

Do you think there is a super big benefit in taking advantage of xstreams live feature? The whole renoise.pattern could be pasted on any value change anyways, which makes playing around just as easy.

OT: Btw… seeing your tools. Have you ever thought about making some kind of generator from templates? Say you put in a chord in track 2 and press a shotcurt, then a pre-defined arpeggio rhythm is being generated in track 1 based on this chord. It feels like such a tool could be a sibling to xstream, with different modifiers, filters and rules being available to choose from :slight_smile: Would be cool for semi-rapid harmony and song structure prototyping. As trackers we’re used to working with patterns, and would benefit a lot from having mathematical and reusable patterns to compose with.

Here’s a version with stretching. Not as funky, but useful as a generator of 13/11 beats - if that’s your thing :wink:
https://gist.github.com/bjorn-nesby/648b8a318f9f59d00227cc5167c0e6c3

I also did a checkbox which lets you lock the cyclelength to the number of steps and enabled it per default. IMO, it’s confusing having to adjust two separate parameters in order to do something as basic as changing the overall sequencelength.

I will split the blanknote feature as suggested.

If I was quick enough, you could then use this version as the basis? Anyway, split and fork to your hearts delight.

Not even sure how the blanknote is supposed to work in this current version, but hey :stuck_out_tongue:

OT: Btw… seeing your tools. Have you ever thought about making some kind of generator from templates? Say you put in a chord in track 2 and press a shotcurt, then a pre-defined arpeggio rhythm is being generated in track 1 based on this chord

I did another model called ChordMemory that actually works pretty close to this. It’s not an arpeggiator, but it does recognize chords in the pattern and offers to save them as a preset - after which, you can apply these presets to notes elsewhere.The limitation is that xStream ‘prefers’ to function within a single track (well, as you know by now, technically we are actuallylimited to a single line at a time). While this is a big limitation, it also grants the tool a certain focus and simplicity… However, you can always query the current output mode (realtime, offline) and for example, switch the track to somewhere else as you produce output, etc. In other words, there is usually a way to obtain the goal you want.

In the longer term Iwould like to see the tool become more friendly to “normal” users. But right now, it’s about making it a capable beast and solving issues as they arise.

Do you think there is a super big benefit in taking advantage of xstreams live feature?

If not for you, then for me, yes. I wrote the tool specifically with this in mind. Actually it was taktik who requested that it should also be able to apply the model to a tracks or selection, so thank him for having that insight. Personally, I’m all about twiddling knobs and hearing stuff change in realtime :slight_smile:

And, if it seems a bit strange that xStream doesn’t come with an arpeggiator model, this is actually because that - due to my focus on realtime input - there was a need to build a better infrastructure, including voice managers and stuff. Thanks to xRules (that other ‘x’ tool) this work is almost done.

Cool! Will look closer this evening!

About the chord stuff, I was intrigued by the prospect of live coding (as available in xStream). I made some notes of some functions that could be available, just for some inspiration on how to structure such a model. As always, one problem with arp templates is how to nicely render both a three voiced chord or a four voiced chord by the same rule.


chord detector (returns table of currently playing voices, for using a silent track as a guiding chord generator). Scanning a patterntrack like this should be possible in xStream, since it’s Renoise LUA, no? Maybe you’d have to use a timer so it doesn’t scan on every new line during playback.
local chord = CURRENT_VOICES

returns { E-4, G-4, C-5 }

set the input track of the voice detector:

CHORD_TRACK = track_index


changes inversion of chord, either relative change or absolute inversion. this really just shuffles the elements of the array, and transposes ±12 where appropriate.
chord = inversion(chord, inversion)

input a note value and return the closest note available in a chord. Maybe useful sometimes?

closest_chord_note(note_value, chord)


chord[1], chord[2], chord[3] et c are the voices.


This should be pretty simple making in xStream. I wonder if a euclidean generator would be cool for arps as well.

EDIT: I am guessing that the CURRENT_VOICES variable should be readable only, and that the trick is to update it in realtime but in a cpu efficient way.

chord detector (returns table of currently playing voices , for using a silent track as a guiding chord generator)

That’s the crux of the matter, because it can be done but it’s really complicated to stuff such complex functionality into a single model/function (assuming that you want to track notes that arrive one-by-one, and not just at the same time). Since xStream already reads from the pattern, it’s not so much a matter of retrieving this information, it’s more about storing and accessing it later on…hence, I saw the need for a voice-manager class.

An example of an existing, supporting class is xScale (see the model ‘Notes and Scales’ for an example) - it packages some complex logic into a few external methods that you can invoke from within your model.

the trick is to update it in realtime but in a cpu efficient way.

I have thought of making a switch to disable the interpretation of input, but so far, xStream is performing admirably even on my ancient netbook so I’ve not really given it priority. Of course, there would be an upper limit to how complex logic you could stuff into a model, but ‘pure’ lua is actually pretty damn fast.

Cool! Will look closer this evening!

Works like expected? It simply produces notes with regular intervals, using the delay column.

Also, perhaps you couldexplain the blanknote feature again - I am a still bit unsure how it’s useful.

The stretch feature is not quite what I imagined. I thought it should stretch the sequence, and maintain the pattern but in a shrinked/expanded form. Perhaps a bit tricky.

The blanknote feature is useful for two practical reasons that I can think of:

  1. You want to overlay a second generator into the same column, for instance putting low velocity hi-hats into the same column as high velocity hi-hats.

  2. You want to mute (erase) notes from a generator when they are clashing with another generator (i e, silence kicks whenever there is a snare). This would then be done by duplicating the snare generator, and outputting it to the kick column with blanknotes on.

Also the cyclelength seems to be bugging. Basically cyclelength would be just a padding function (either cutting the sequence or inserting silence after it. Practically, this can be used for inserting “one-shot” sequences. Or for cropping a sequence.

Nevertheless I am liking this generator! I hope xstream will be developed and that the GUI could be made even more usable.

PS. About xstream… would be cool if you eventually could stack models. And maybe somehow use several instances of xstream where each instance could be tied to its own track, with its settings saved in the song somehow. (I’m thinking about flexibly auto-generating a track based on data from another track). Imagine the fun stuff you can make with simple components, and the effectiveness of only having to enter a chord into a chord track, for example. It would be like a modular arpeggiator, and even more. I guess these things are manually possible now, but not very practical.

The stretch feature is not quite what I imagined. I thought it should stretch the sequence, and maintain the pattern but in a shrinked/expanded form. Perhaps a bit tricky.

Ah, think I will pull the relevant code into some other model, because the ability to distribute X notes over Y lines is definitely useful :slight_smile:

The blanknote feature is useful for two practical reasons that I can think of:

  1. You want to overlay a second generator into the same column, for instance putting low velocity hi-hats into the same column as high velocity hi-hats.

  2. You want to mute (erase) notes from a generator when they are clashing with another generator (i e, silence kicks whenever there is a snare). This would then be done by duplicating the snare generator, and outputting it to the kick column with blanknotes on.

That makes sense, the challenge is really how to express it without turning everything into a complicated mess :slight_smile:

Nevertheless I am liking this generator! I hope xstream will be developed and that the GUI could be made even more usable.

Actually I did (inspired by our discussion) undertake a major refactoring of the UI class in xStream. It was a monster, about 5K lines of code.
Now it’s much more manageable. Still need to do the “tab” thing, but this class needed to be sorted out first :slight_smile:

Also, yes to your other suggestions.

Ah, think I will pull the relevant code into some other model, because the ability to distribute X notes over Y lines is definitely useful :slight_smile:

Yes, I noticed it did what my tool is doing: https://www.renoise.com/tools/place-selected-notes-evenly

But I used math.floor and you used math.ceil (or the other way around), rendering delay values being one step off. Maybe your way is the correct one and I should fix this in my tool.

That makes sense, the challenge is really how to express it without turning everything into a complicated mess :slight_smile:

Yes. GUI grouping would help a bit. I’m thinking something like this:

Top group (euclidean sequence, minor cycle):
Steps
Pulses
Offset/rotate
Reverse
Cropping/padding
Stretch

Next group (major cycle):
Cyclelength (usable for restarting minor cycle at any place, i e some things maintain polyrhythm over longer time)
Offset/rotate (just for flexibility)

Next group (various settings):
Blank notes
Don’t overwrite with blank lines
Invert hits/non-hits

Last group:
Instrument
Velocity
Column

Actually I did (inspired by our discussion) undertake a major refactoring of the UI class in xStream. It was a monster, about 5K lines of code.
Now it’s much more manageable. Still need to do the “tab” thing, but this class needed to be sorted out first :slight_smile:

Great to hear that you’re putting effort into this tool. It’s very potent.

Also, yes to your other suggestions.

Making xstream a streamlined and user friendly part of workflow when generating patterns would be huge. Even more huge than Renoise having a piano roll :wink: I guess that would call for a new pasting principle alongside live and TRK, that would fire any time an input track is updated.

I just put out the new version (1.45). Managed to release our in-progress euclidean generator - oops :slight_smile:

But most importantly, I’ve had a bit of time to think about the tabbed arguments implementation.

And I think the best way to structure this is to think in terms of the “args” becoming a multidimensional array.

So, imagine for example my sequencer model - it has four notes, four volumes, four duplicates of pretty much everything.

What I would want when accessing those values would be something like

args.pitch.a
args.pitch.b
args.pitch.c
etc.

Or alternatively, I could organize my arguments like this

args.a.pitch
args.a.volume
etc.

In either case, I would create arguments while making use of a basic dot notation syntax.

The UI would then organize the arguments panel accordingly,_as well as_providing the ability to sort the entries

Because of the way it’s stored we can control the order of keys - something you normally can’t do in lua tables.

Not sure if having tabs within tabs will be necessary - it will certainly make the code a lot more complex. Try to consider if your example above could be structured to provide everything needed in a single tabbedlevel? We still need multiple generators, right?

It would be nice to have a tab for each generator, but also the ability to group arguments (you know, just the subtle graphical box thing to make the gui more user friendly).

Maybe that would be difficult to make? I’d imagine something like

args.generator_1__tab.a__group.steps

args.generator_1__tab.b__group.blanknotes

args.generator_2__tab.a__group.steps

args.generator_2__tab.b__group.blanknotes

__ being a delimiter.

Tabbed arguments is now a reality.

https://forum.renoise.com/t/new-tool-3-0-3-1-xstream/44430

I spent yesterday night recording a lot of output from this model. It’s absolutely wicked, not only for rhythmic but alsorhythmic/melodic material

(which is why I added transpose and phrase options, btw.)

Awesome!! I will for sure customize this into my own flexible but user unfriendly generator! :slight_smile:

Yeah, I’m looking forward to the ability of generating euclidian chord stabs…