New Tool (2.8, 3.0): Flexible Pattern Resizer

This is great! If it hasn’t been said yet, it’d be good to have it be capable of changing a selection’s length independent of the pattern; this way you could stretch “live-played” elements to fit for any bpm.

also: I think percentages would be pretty helpful in a context like that.

Hey dblue,

there is one bug in the PatternResizer tool: If a automation point is on the very last position of a pattern (so the same position as the first in the next pattern), this point will be erased while a pattern shrink.

there is one bug in the PatternResizer tool

Nicely spotted. Looks like a pretty simple fix, but I’ll try to give it a bit more testing today.

Thanks, here maybe another one, or some priority thing:

If I shrink this track from 128 to 64 bars:

Attachment 5512 not found.

it looks like this after shrinking:

Attachment 5513 not found.

So instead of taking the F#4 for the second note, it takes the third and offsets it. Surely this is coded right, but wouldn’t be the F#4 expected instead, since it has a higher rhythmical priority? Even > uneven?

Thanks, here maybe another one, or some priority thing: (…)

In situations where two notes would collide in the smaller sized pattern, and one note must therefore be deleted due to space constraints, it will first give priority to notes that are louder (70 vs 40 in your example), or, if both volumes are the same, then it will give priority to the note which ends up with the least amount of note delay.

There are of course many other ways to handle this kind of thing, and some extra options in the tool itself would be great.

Ideally, the tool would not simply throw away those “in between” notes in the first place, but would instead create new note columns for them whenever possible.

As usual, this is all just crap that’s been saved in my todo.txt somewhere for a long time :wink:

Ideally, the tool would not simply throw away those “in between” notes in the first place, but would instead create new note columns for them whenever possible.

That would satisfy everybody! +1

Version 1.06 now available for Renoise 2.8 and 3.0

No major new features. Just fixed this automation bug reported by Jurek.

Downloads in the original post.

Awesome tool, Thanks dblue!

Hey I didn’t know that Renoise can expand/shrink by itself. Why nobody told me? Apple + F8 / Apple + F9…

This is great!

This is great!

But attention, better use this tool instead renoise internal for now, since the internal has bug. This tool is already fixed.

EDIT:

dblue, I hope that you don’t mind if I place a little extended version of your pattern resizer tool here:
Attachment 6440 not found. (UNOFFICIAL TEST VERSION)

Basically I added two more shortcuts, “resize x2” and “resize x0.5”. These are meant as replacement shortcuts for the Renoise’s internal expanding/shrinking (Command + F8 / Command + F9), since those are buggy.

It also retains cursor position while playing at least. And auto-fixes LPB.

EDIT: Added dblue’s fixes from below.

Edit2: will add a better lpb autofix soon, that actually works with multiple times usage :stuck_out_tongue:

Arg, sorry still throws sometimes an error, if expanding from last pattern line…? I don’t geddit, how set start_at properly… start_at starts with 1,renoise.song().selected_line_index with 0?

I don’t mind too much if you make edits, but if you do plan to release it publicly then please make it very obvious that it’s a modified version by you, and not the original version by me. People should be aware which exact version they are using, just to avoid confusion. If you want to incorporate my pattern resizing functions into your own tool, that’s also totally fine as long as proper credit is given :slight_smile:

Regarding your line index bug, the pattern lines are indexed starting from 1 in the Lua API, not from 0.

To compensate for that in your calculations, first subtract 1 from the selected index, then multiply or divide it, then add 1 back to the result.

-- Expand
local sli = ((renoise.song().selected_line_index - 1) * 2) + 1

-- Shrink
local sli = ((renoise.song().selected_line_index - 1) / 2) + 1

You’re also missing quite a bunch of sanity/safety checks in your modified code, so it’s very easy to expand/shrink everything to some invalid LPB, invalid line index, and so on. Exactly how you prefer to handle this is up to you, but you can simply wrap your calculations with math.min() and math.max() to apply some crude range limiting.

local sli = math.max(1, math.min(renoise.song().selected_pattern.number_of_lines, ((renoise.song().selected_line_index - 1) * 2) + 1 ))

I took the liberty of modifying your functions to include these changes.

renoise.tool():add_keybinding {
  name = "Pattern Editor:Pattern:Resize x2",
  invoke = function()
  
    -- Reference to song
    local rs = renoise.song()
  
    -- Resize pattern
    resize_pattern(rs.selected_pattern, adjust_pattern_length(2))
    
    -- Adjust selected line index
    local sli = rs.selected_line_index
    local max_lines = rs.selected_pattern.number_of_lines
    local new_sli = math.max(1, math.min(max_lines, ((sli - 1) * 2) + 1 ))
    rs.selected_line_index = new_sli
    
    -- Adjust LPB
    local t = rs.transport
    t.lpb = math.max(1, math.min(256, t.lpb * 2))
    
    -- Move transport to the new position and resume/stop playback
    local playing = t.playing
    t:start_at(new_sli)
    if (not playing) then t:stop() end
    
  end 
}

renoise.tool():add_keybinding {
  name = "Pattern Editor:Pattern:Resize x0.5",
  invoke = function()
  
    -- Reference to song
    local rs = renoise.song()
   
    -- Adjust selected line index
    local sli = rs.selected_line_index
    local max_lines = rs.selected_pattern.number_of_lines
    local new_sli = math.max(1, math.min(max_lines, ((sli - 1) / 2) + 1 ))
    rs.selected_line_index = new_sli
    
    -- Adjust LPB
    local t = rs.transport   
    t.lpb = math.max(1, math.min(256, t.lpb / 2))
    
    -- Move transport to the new position and resume/stop playback
    local playing = t.playing
    t:start_at(new_sli)
    if (not playing) then t:stop() end
    
    -- Resize pattern
    resize_pattern(rs.selected_pattern, adjust_pattern_length(1/2))
    
  end 
}

There are other things you might consider, like preventing the entire expand/shrink operation if the LPB or other values would theoretically go out of bounds, but I leave that up to you.

All in all, these are pretty good additions, so I will likely include some variation of them in my original tool… if I ever get around to updating the damn thing!

Wow, this is how perfect code looks :slight_smile:

Maybe a very helpful addition would be auto-fixing all synced dsp, too, by fixing the lines values!

Is there some simple way to get all syncing values of a dsp device without knowing individual parameter offsets?

This one doesn’t work for phrases right? Would be great if it did!

This might be a dumb question, but where is the download link?

The attachment got lost after the forum upgrade. I’ve manually added it back now. See first topic to download…

Hey,

found a new bug in v3.00 (Renoise 3.21). If you have fx devices in a group and you have a parameter of the fx automated like so:

It will throw this error:

org.illformed.PatternResizer.xrnx/main.lua’ failed in one of its notifiers.

main.lua:228: attempt to index field ‘?’ (a nil value)
stack traceback:
main.lua:228: in function ‘resize_pattern’
main.lua:496: in function main.lua:495

If you delete the automation of the compressor above, no error will appear.

NOTE: The automation is marked as active, but the actual automation is empty, due the usage of the pattern split function.

EDIT:
Might be caused by this problem only. But I am not sure: