Hi! I’m able to crash Renoise now, continuously, repeatable every time, with a script. I was trying to combine multiple different functions from inside the Paketti tool compilation, as I was trying to accomplish a certain set of functions run one after the other, to accomplish certain things. I noticed that dblue had helped immensely with a pattern expander function, and decided to use that. What I got, was a crash.
Click to view contents
function resize_pattern(pattern, new_length, patternresize)
-- We need a valid pattern object
if (pattern == nil) then
renoise.app():show_status('Need a valid pattern object!')
return
end
-- Rounding function
local function round(value)
return math.floor(value + 0.5)
end
-- Shortcut to the song object
local rs = renoise.song()
-- Get the current pattern length
local src_length = pattern.number_of_lines
-- Make sure new_length is within valid limits
local dst_length = math.min(512, math.max(1, new_length))
-- If the new length is the same as the old length, then we have nothing to do.
if (dst_length == src_length) then
return
end
-- Set conversation ratio
local ratio = dst_length / src_length
-- Change pattern length
if patternresize==1 then
pattern.number_of_lines = dst_length
end
-- Source
local src_track = nil
local src_line = nil
local src_note_column = nil
local src_effect_column = nil
-- Insert a new track as a temporary work area
rs:insert_track_at(1)
-- Destination
local dst_track = pattern:track(1)
local dst_line_index = 0
local dst_delay = 0
local dst_line = nil
local dst_note_column = nil
local dst_effect_column = nil
-- Misc
local tmp_line_index = 0
local tmp_line_delay = 0
local delay_column_used = false
local track = nil
-- Iterate through each track
for src_track_index = 2, #rs.tracks, 1 do
track = rs:track(src_track_index)
-- Set source track
src_track = pattern:track(src_track_index)
-- Reset delay check
delay_column_used = false
-- Iterate through source lines
for src_line_index = 0, src_length - 1, 1 do
-- Set source line
src_line = src_track:line(src_line_index + 1)
-- Only process source line if it contains data
if (not src_line.is_empty) then
-- Store temporary line index and delay
tmp_line_index = math.floor(src_line_index * ratio)
tmp_line_delay = math.floor(((src_line_index * ratio) - tmp_line_index) * 256)
-- Process note columns
for note_column_index = 1, track.visible_note_columns, 1 do
-- Set source note column
src_note_column = src_line:note_column(note_column_index)
-- Only process note column if it contains data
if (not src_note_column.is_empty) then
-- Calculate destination line and delay
dst_line_index = tmp_line_index
dst_delay = math.ceil(tmp_line_delay + (src_note_column.delay_value * ratio))
-- Wrap note to next line if necessary
while (dst_delay >= 256) do
dst_delay = dst_delay - 256
dst_line_index = dst_line_index + 1
end
-- Keep track of whether the delay column is used
-- so that we can make it visible later if necessary.
if (dst_delay > 0) then
delay_column_used = true
end
dst_line = dst_track:line(dst_line_index + 1)
dst_note_column = dst_line:note_column(note_column_index)
-- Note prioritisation
if (dst_note_column.is_empty) then
-- Destination is empty. Safe to copy
dst_note_column:copy_from(src_note_column)
dst_note_column.delay_value = dst_delay
else
-- Destination contains data. Try to prioritise...
-- If destination contains a note-off...
if (dst_note_column.note_value == 120) then
-- Source note takes priority
dst_note_column:copy_from(src_note_column)
dst_note_column.delay_value = dst_delay
else
-- If the source is louder than destination...
if (src_note_column.volume_value > dst_note_column.volume_value) then
-- Louder source note takes priority
dst_note_column:copy_from(src_note_column)
dst_note_column.delay_value = dst_delay
-- If source note is less delayed than destination...
elseif (src_note_column.delay_value < dst_note_column.delay_value) then
-- Less delayed source note takes priority
dst_note_column:copy_from(src_note_column)
dst_note_column.delay_value = dst_delay
end
end
end -- End: Note prioritisation
end -- End: Only process note column if it contains data
end -- End: Process note columns
-- Process effect columns
for effect_column_index = 1, track.visible_effect_columns, 1 do
src_effect_column = src_line:effect_column(effect_column_index)
if (not src_effect_column.is_empty) then
dst_effect_column = dst_track:line(round(src_line_index * ratio) + 1):effect_column(effect_column_index)
if (dst_effect_column.is_empty) then
dst_effect_column:copy_from(src_effect_column)
end
end
end
end -- End: Only process source line if it contains data
end -- End: Iterate through source lines
-- If there is automation to process...
if (#src_track.automation > 0) then
-- Copy processed lines from temporary track back to original track
-- We can't simply use copy_from here, since it will erase the automation
for line_index = 1, dst_length, 1 do
dst_line = dst_track:line(line_index)
src_line = src_track:line(line_index)
src_line:copy_from(dst_line)
end
-- Process automation
for _, automation in ipairs(src_track.automation) do
local points = {}
for _, point in ipairs(automation.points) do
if (point.time <= src_length) then
table.insert(points, { time = math.min(dst_length - 1, math.max(0, round((point.time - 1) * ratio))), value = point.value })
end
automation:remove_point_at(point.time)
end
for _, point in ipairs(points) do
if (not automation:has_point_at(point.time + 1)) then
automation:add_point_at(point.time + 1, point.value)
end
end
end
else
-- No automation to process. We can save time and just copy_from
src_track:copy_from(dst_track)
end
-- Clear temporary track for re-use
dst_track:clear()
-- Show the delay column if any note delays have been used
if (rs:track(src_track_index).type == 1) then
if (delay_column_used) then
rs:track(src_track_index).delay_column_visible = true
end
end
end -- End: Iterate through each track
-- Remove temporary track
rs:delete_track_at(1)
end
[media]
http://www.youtube.com/watch?v=5hRHEHFk3T4
[/media]
What I’m trying to do is simple:
create a shortcut that:
writes current BPM / LPB setting to Master Track
clones current track to current pattern sequence
multiplies LPB by 2
writes BPM/LPB to cloned pattern Master Track
resizes cloned pattern by 2
expands pattern content by 2.
before utilizing a possibly legacy dblue expand script (pattern resizer), i was able to write lpb, multiply lpb, clone ptn, resize ptn length, write lpb. that’s quite allright, but then i decided to try and use what other things and tools ive added to paketti over the year or so, and came across these issues.