New Tool (3.0,3.1): xStream

splash-big-mkII.png

Introducing xStream
xStream allows you to generate or transform existing pattern/automationdata via custom code which can be created and tweaked in realtime

You can obtain the tool from thetools page, orgithub

Documentation
When you install the tool, a ‘README.md’ is located in the installation folder. This is a markdown-formatted documentation file, including a quick reference to the xStream-specific Lua API. You can also visit the xStream github page for the newest version of documentation, regardless of what version you have installed.

And of course, you can study the example models. For newcomers, it is highly recommended to start with themodels which are prefixed with ‘Demo-’. These models are designed to demonstrate a particular aspect of xStream without being overly complex.

3 Likes

Amazing!

Hope someone films and uploads your demo of this tonight

Hello danoise

I’m normally just an occasionallurker at these forums, but this particular tool of yours forces me to sign in and comment. :slight_smile:

First of all,seems like an interestingconcept. I’ve only tested the tool for half an hour, but I’mlooking forward to explore its full potential.

Now, one of the ideas for a macro I immediately felt the need to create was a custom chord generator. Unfortunately I don’t speak this lua language, but I managed to figure this much out by copy-pasting from your examples into the empty slot.

--Creates a minor chord from the note value in note column 1
--
--Example:

--enter C-4 (or any other note value) in note column 1 in a track

--select the row

--press fill_selection button in xStream methods
--the C-4 (or other note value) will be replaced with C-4 +
-- D#4 + G-4 which is the C minor chord
--
--------------------------------------------------------------

local existing_note = xline.note_columns[1].note_value

xline.note_columns = {
 {
 note_value = existing_note + 0,
 instrument_value = 13,
 volume_value = args.volume,
 panning_value = 80
 },
 {
 note_value = existing_note +3,
 instrument_value = 13,
 volume_value = args.volume
 },
 {
 note_value = existing_note +7,
 instrument_value = 13,
 volume_value = args.volume
 }
}

Now if I want to manipulate the Cx (cutoff note) parameter in the panning_value so that it is for example “C8”, what needs to be done? It only seems to accept numerical values. Any suggestions?

Hey fsus, thanks -

it’s really encouraging to know that you could use the tool without much prior knowledge

Now if I want to manipulate the Cx (cutoff note) parameter in the panning_value so that it is for example “C8”, what needs to be done? It only seems to accept numerical values. Any suggestions?

It follows the Renoise API way of specifying things. So, you can use both value or string, whichever is the most handy.

-- here, the value and string amount to the same thing - a C-8 note
note_string = "C-8"
note_value = 96

The API documentationhas the full information on note and effect-column properties, including special ones like “OFF”

How about an example workflow for noobs

Hm… one example would be to select the “Notes and scales” model and then select some pattern data and hit ‘Fill selection’

→ You have just restricted all notes to that particular scale/key

→ This is also what I refer to as the offline mode

Another one (my favourite) would be to select “Random increase”, disable ‘clear_undefined’, and let playback enter a blockloop

→ Now you will hear an endlessly evolving/repeating pattern of notes. Try switching instrument while playing :smiley:

→ Setting ‘clear_undefined’ to false means that we add new notes on top of existing ones

→ This is also what I refer to as online, or ‘streaming’ mode

Whether you find that useful or not, is a different matter :slight_smile:

Aha, reading from that API stuff I figured out that one needs to write this

panning_value = 0x00000C08

in order to place out a C8 (Cx: Cut note after X ticks (0 - TPL)) in the panning column

Lovely, I need to check this lua stuff out.

Hey fsus, thanks -

it’s really encouraging to know that you could use the tool without much prior knowledge

It follows the Renoise API way of specifying things. So, you can use both value or string, whichever is the most handy.

-- here, the value and string amount to the same thing - a C-8 note
note_string = "C-8"
note_value = 96

The API documentationhas the full information on note and effect-column properties, including special ones like “OFF”

True, you can specify any possible value using numbers. It can be a little complex though, because you’d need to pass values through a little calculation first.

In most cases, strings are much easier to work with, what you see in the pattern editor you can also enter as a string value:

panning_string = "C8"

If the value “8” happened to be the result of some kind of calculation, you could hand over a string by using string.format()

local my_ticks_value = 8
panning_string = ("C%d"):format(my_ticks_value)

But if you are applying a value as a result of some kind of expression, or you are comparing values, numbers are useful.

For example, this little snippet will only transform notes that are not empty or note-offs

-- transpose notes down one semitone
if (xline.note_columns[1].note_value < 120) then
  xline.note_columns[1].note_value = xline.note_columns[1].note_value - 1
end

This is so, because the “note off” and “empty” are both higher than 119 (120 and 121, respectively)

For me xStream seems to have a lot more potential in offline mode.

I imagine inthe future xStreamwould hosta hugenumber of models/buttons (placed on a second screen in dual monitor setup), each buttonexecuting anunique custom macro operation. Maybe hundreds of such models would need to be placed within selectable categoriesor something for a better overview. Thiswould bemy first feature request, because it would make it easier to organize stuff.

Anyway, this doesn’t work for me:

local my_ticks_value = 8
xline.note_columns = {
 {
 note_value = 36,
 instrument_value = 7,
 volume_value = args.volume,
 panning_string = ("C%d"):format(my_ticks_value)
 }

All the values render properly, it just refuses to place out the ‘C8’ in the panning column.But maybe one can’t mix _values with _strings?

I imagine inthe future xStreamwould hosta hugenumber of models/buttons (placed on a second screen in dual monitor setup), each buttonexecuting anunique custom macro operation. Maybe hundreds of such models would need to be placed within selectable categoriesor something for a better overview. Thiswould bemy first feature request, because it would make it easier to organize stuff.

Indeed, this is something I’ve been thinking about as well. Right now, it’s presenting whatever models you have in a single folder - logical next steps would be to list those models in a table, grid or some other container, along with the ability to categorize presets by putting them into subfolder (I’m a big fan of using the file system to describe a hierarchal structure). Right now, it’s a problem that you so easily can run out of space on the screen.

And while “hundreds of models” might sound a little overwhelming, yeah - why not. I think I would personally aim for a little more flexibility in my models, and use the preset system to create unique variations thereof - but then, obviously the preset system too would need the ability to host hundreds of entries :smiley:

Anyway, this doesn’t work for me:

Well spotted! There was indeed a little mistake when applying alfa-numeric values that could be interpreted as hex (U8 would work, but your C8 wouldn’t… uploading a fix ASAP

For the first suggestion, I just get the same 3 notes played in the same sequence, endlessly, throughout the track.

Well, it depends on what you “feed” it - since that model is transforming existing pattern data, the notes will remain the same. If you had some melody line, chord sequence, you should be able to hear a difference.

For me xStream seems to have a lot more potential in offline mode.

This is also a point which was raised at the meetup. Basically, xStream will, in its current shape, allow you to do “only one thing at a time”.
While that of course makes sense in this early stage, it also is quite limiting from a live performance, jamming point of view.

My longer-term ideas for xStream involves having a kind of “stream manager”, essentially a type of arranger which will allow you to control multiple models, and schedule events at certain times.
But right now, this is really a pipe dream because of the amount of work involved. Focusing on making the core as efficient and stable as possible has the top priority!!

Version 1.01 is on github now

FIXME attempt to fix crash-proneness : apply the callback string during idle loop instead of right away
FEATURE detect when model is changed, ability to revert to last saved state
CORE better unit tests for song pos

Edit: this update seems to resolve one of the major problems so far, which was a tendency to crash Renoise - especially true with the most complex models (‘Sequencer4’).

My theory as to why this could happen? It turned out that, when switching between models, or setting a model for the first time, the act of updating the user interface - more specifically, the textfield containing the callback code - would call it’s notifier once for every line. This would result in xStream trying to compile the callback method maybe 50 times in a split-second…

While doing such a thing shouldn’t really be able to take down Renoise - ever - xStream is using some pretty “unusual” features of the lua language, and as such, we might have headed a little bit into unknown/untested territory here.

Bottom line is, I have improved xStream in this regard - the user interface will now wait for the idle update before submitting a modified string. Hopefully, this should prevent crashes from happening. Please report this if it still happens to you.

Also, there is now a “revert to saved” button, and the “save” button is enabled only when the model has been modified.

Version 1.01 is on github now

FIXME attempt to fix crash-proneness : apply the callback string during idle loop instead of right away
FEATURE detect when model is changed, ability to revert to last saved state
CORE better unit tests for song pos

Edit: this update seems to resolve one of the major problems so far, which was a tendency to crash Renoise - especially true with the most complex models (‘Sequencer4’).

Have been working on that too and found out what the problem is: The buttons which do select new models do update/rebuilt all buttons which select new models too when clicking them, so pressing a model button killed the button that was currently pressed. We’re internally avoiding doing such things, but for tools we can’t make such “prerequisites”, so I’ll fix that here for the next Renoise update.

If you need a workaround for your tool now: avoid rebuilding the model buttons when selecting a new model via a model button - then it should work.

1.02 is available now on github and the tools page

FIXME Avoid recreating model/preset button-lists as a result of these buttons being clicked

Uploading a full hour (!!) of video right now (check back later)

It’s my presentation of the xStream tool for Renoise at the meetup last Saturday.

Regarding that video above: If someone reaches the one hour point, they are rewarded with something reminiscent of actual music.

Also, it could be turned into a drinking game:

If you take a hit every time I say “the thing is…”, you will be blasted quite quickly :smashed:

TBH the audio in video needs some compression for upper volumes, expandation/gating for quitter stuff and eq on highs. Was quite difficult at least for me to understand the words… My respect you did this presentation and explained it so detailed.

3.1 spoiler, nice :slight_smile:

Erm I have have some questions regarding making a algorithm with it…

Here is the code:

See post below

My questions are:

  1. How do I add a slider value? “reveal_location” just seems to unfocus renoise.

  2. In the example above, if num_notes are > 3, the iterator n suddenly starts with 3 instead 0… Do I made a mistake? Don’t get it…

  3. How can I check for a note-off, so it would be detected a an note?

  4. will the note-offs automatically moved?

Thanks for help!

Thanks for the presentation vid danoise :slight_smile:

Can this tool go through a selection of notes and sort these over time, from lowest note to highest note or the other way around? The time it takes to sort, generated as pattern content…something like this;