Possible to switch pattern without resetting position


(Mattias Sjöstrand) #1

Is it possible to switch to another pattern without starting the next pattern from the first row? I would like to somehow via a miditrigger switch back ant forth between two parallel melodies so that the other pattern starts on the same step as the last.


keeping play-position while triggering different patterns
keeping play-position while triggering different patterns
(danoise) #2

Ah, pattern juggling

Bring up the MIDI mapping dialog and search for “Sequence Pos”, this should reveal method for navigating to the next/previous pattern


(delt) #3

Also wondering about this, but without midi mapping/triggers… for example if i want to script functions that move to prev/next pattern in the pattern editor when follow is off, without interrupting playback, that kind of stuff…?


(Mattias Sjöstrand) #4

Tried it but it only change patternposition in the sequence. Maybe im not explaining myself clear enough. What i would like to do is change pattern via midi-triggers but i dont want renoise to cue up the next pattern and play it from the top (row 00). If i press the trigger for the next pattern when the first is on row 26 i want the second pattern to begin play instantly on row 26, in time with the beat. I have only found the way to que or trigger patterns to play from the first row. Any ideas?

EDIT* This is how it works in Ableton Live


(kazakore) #5

It’s easy enough to script if it doesn’t exist already.

Looking at the MIDI Mapping option you have Trigger Sequence XX and Schedule Sequence XX. Schedule obviously isn’t what you want (go to at end of current pattern) and from your description I assume Trigger Sequence must trigger it from the start of the pattern, rather than keep your position.

Bear in mind there may be some issues if you have patterns of different lengths.

Example code:

 local rns = renoise.song   
local pos = renoise.song().transport.playback_pos  
pos.sequence = pos.sequence - 1  
rns().transport.playback_pos = pos  

Will move you to the previous pattern, keeping you on the same line.

Would you like a Jump To XX Sequence? How do you want to map it?


(Mattias Sjöstrand) #6

My plan is to make a lot of short drumpatterns 4 rows long and map to a 4x4 buttons. If i press one button i want it to loop until i press another button. Then i want that pattern to start playing from the row the current patterna are about to play. This way i can switch between patterns realy fast and dynamicly create variations without losing the beat.


(kazakore) #7

Pretty sure Hitori Tori does it in a similar way and fairly certain the first video I saw was before scripting came out…

http://www.youtube.com/watch?v=aa3_kWUCRns

Excuse the numbering, I leave work in 10min so just threw this together and not got to the time to tinker and figure out how to get it properly numerical, but test this and see if it does what you want.

3818 uk.deaddogdisko.SequenceJump.xrnx

Although the Grip Pie/Duplex way of copying pattern data into “Live Patterns” may be just as or more useful than this. Then you can mix cells from the Matrix together as you see fit live, rather than playing all tracks in a pattern together.


(delt) #8

I also haven’t found a way select prev/next PATTERN, not pattern in ORDERLIST/SEQUENCE.

(Being that i’m a complete newbie at lua and at renoise, that’s not saying much :3 )


(kazakore) #9

As the default for the sequence is to keep patterns numbers in order this really doesn’t make much sense! Or if you have this disabled and the next pattern number is not actually in the sequence anywhere. Where is it going to put you??

Or do you just mean change the pattern number of the currently playing pattern? There is already default shortcuts to do this from various areas or you can use the mouse on the little arrows by the side of the numbered box in the sequence.

http://tutorials.renoise.com/wiki/Pattern_Sequencer

If in Pattern Editor keyboard shortcuts are: Left Control/Command + Arrow Left/Right = Change the current pattern’s number. As default.

Or maybe you just need to explain yourself better,…

And as my attachment hasn’t been downloaded I assume Mattias can’t be bothered to see if it does what he wants!


(danoise) #10

Agh, yes I forgot to add that this will work only when pattern-follow is enabled. Otherwise it will jump to the sequence, but playback won’t follow.
Enable pattern-follow (SCR-LOCK) and it will change pattern instantly, just like you want it to.

Kazakore’s tool doesn’t come with this limitation - works like advertised (thanks!)

On a sidenote: when you have differently sized patterns - jumping from e.g. line 102 into a pattern with 64 lines would cause a playback ‘glitch’.
So if you serious about using this live, you’d better keep your patterns the same size.


(Mattias Sjöstrand) #11

I appreciate the help! Havnt been able to try the script out because of work but i will give it a go tomorrow after a full nights sleep. :)


(Mattias Sjöstrand) #12

Tried the script and it did the work! Makes me curios about scripting but ill guess that would take som time to get my head around…


(kazakore) #13

That one is literally a few lines, one of the simplest possible examples for you to try and get your head around.

If you think you are likely to use it I will try and work out if I can do something about the number ordering in it. I assume I just need to lookup how to ask it to display all numbers with three figures (keeping leading zeros) and then it will hopefully display correctly…


(James Britt / Neurogami) #14

This was something I’ve been wondering about, and thanks very much for this code.

I’ve been adding my own OSC handlers for various things so I modded your code for yet another OSC handler, this to jump to any given pattern but keeping the same relative line number:

  
 add_global_action {   
 pattern = "/pattern/into",   
 description = "Jump to the given pattern number but keep same relative line position",  
  
 arguments = { argument("pattern_index", "number"), },  
  
 handler = function(pattern_index)  
 print("Jump into!")  
 local rns = renoise.song   
 local pos = renoise.song().transport.playback_pos  
 pos.sequence = pattern_index  
 rns().transport.playback_pos = pos  
 end  
 }  
  

What’s nice is that if you pass an invalid pattern index Renoise ignores it. You’ll see the error message if you’re viewing the scripting terminal but otherwise there are no apparent side-effects.


(kazakore) #15

I would still suggest adding something like this:

 local rns = renoise.song   
local app = renoise.app()   
  
local pos = rns().transport.playback_pos  
pos.sequence = YOURVALUE -- I do not know how you are generating this, guess a For Loop and if so could do the check earlier, if via equation you will need to do it this way)  
if pos.sequence > #rns().sequencer.pattern_sequence then app.show_status("Sequencer number outside of range!") return end  
rns().transport.playback_pos = pos  

This will then check if the chosen sequence is within the length of the song, if not break out of the function without trying to set it (maybe future version of Renoise wont handle out of range numbers so well) and give a message in the status bar explaining why nothing has happened.


(James Britt / Neurogami) #16

I don’t see how your code is handling the possible exception.

In any event I’m not a fan of adding code to handle a future-maybe-someday-perhaps possibility. YAGNI, as the saying goes. If Renoise or Lua changes such that the out-of-range error is no longer ignored and the script starts breaking stuff it will be easy enough to change once that is an actual use case. (As it is the Lua interpret spits out an error message if you try to jump to an invalid index but everything just keeps running smoothly).


(kazakore) #17

What do you mean you don’t know how it’s handling it?

if pos.sequence > #rns().sequencer.pattern_sequence  

Is the newly set pos.sequence greater than the total number of sequences in the current song.

app.show_status("Sequencer number outside of range!")  

Display a nice message to the user, so they know why their button presses haven’t done anything and don’t just think the script doesn’t work.

return end  

Return out of the function so as not to execute spurious code which wont do anything. In this case only a single operation but some times there may be a lot more which would be run which doesn’t need to be executed.

I just find it good practice to try and be tidy and complete. As you say it’s not needed but it’s the kind of little bits I try and add to my code these days.


(James Britt / Neurogami) #18

Ah. The formatting of the previous message was garbled.

Thanks.


(kazakore) #19

Yeah I’m lazy and use the key on the keyboard which is really a single quotation mark rather than a real apostrophe but that is accepted practice in most places/programs these days. That made a lot of the text look like it should have been a quote. Unfortunately the forum CODE tag doesn’t format to LUA. We could do with a dedicated LUA tag really! So that anything after – type comments get displayed as such.

test:

Normal text  
  
'This is surround by single quotes.'  
  
`this is surrounded by real apostrophes`  

Seems even the apostrophe key is seen as a quotation mark anyway! :(/>

Extra edit: Changed the above post to say Do Not so the formatting is easy to read in context now too ;)


(kazakore) #20

Plus I must have been tired as even though I read you post I then said I didn’t know how you were setting your pos.sequence value. I’ll put it in context where I would in your example code instead then.

  
  
 local rns = renoise.song   
 add_global_action {   
 pattern = "/pattern/into",   
 description = "Jump to the given pattern number but keep same relative line position",  
  
 arguments = { argument("pattern_index", "number"), },  
  
 handler = function(pattern_index)  
 if pos.sequence > #rns().sequencer.pattern_sequence then app.show_status("Sequencer number outside of range!") return end  
 local pos = renoise.song().transport.playback_pos  
 pos.sequence = pattern_index  
 rns().transport.playback_pos = pos  
 end  
  

You have extra code there you know instantly can be skipped if you value is out of range. Still very minor on the grand scheme of things! (I assumed the print (“Jump into!”) is a hangover from testing stage, to make sure it really fired, so I have removed that too.) Plus I moved the rns variable to outside of the function as personally I use it all over my code to say that little bit of typing… Maybe it can’t really go there for the OSC stuff? I’ve not done anything with that side of things so sorry if I should have moved it.