Storing a pattern data for later use

I’m trying to work out the best way to store some line data from a pattern track and then write it back at a later stage…

For example if I run the following code:

line =[1].tracks[1]:line(1)  
print (line)  

I get this output:

C-400...... | ---........ | ---........ | ---........ | ---........ | ---........ | ---........ | ---........ | ---........ | ---........ | ---........ | ---........ | 0000 | 0000 | 0000 | 0000 | 0000 | 0000 | 0000 | 0000  

Which is all the data from that particular track that I want, however the ‘line’ variable is only pointing to that particular line so if I clear the track then I lose the data in ‘line’. I can get around this by doing

line = tostring([1].tracks[1]:line(1) )  

Which works, so I then have the data stored in a string, but now I cannot find a quick way to write this data back to the track at a later stage. The only way I can think of is to iterate over each note and effect column and write the data back from the string variable I have stored it in, this seems a slow way do it.

Another way I can think of is to copy the track into a temporary pattern and then use[].tracks[]:copy_from(other_pattern_track object)  

when I need to retrieve line data, maybe this is quicker?

However both these methods seem a bit clunky to me. Does anyone know a better way to achieve this?


Use table.copy or table.rcopy to copy the contents of the table to a new one, rather than point at the existing table.

From LUA.Standard.API.lua:

Thanks, I tried that but got the following error: 


*** [string “-- create or convert a table to an object t…”]:93: bad argument #1 to ‘table.copy’ (table expected, got ‘PatternTrackLine’)
*** stack traceback:
*** [C]: in function ‘assert’
*** [string “-- create or convert a table to an object t…”]:93: in function ‘copy’
*** testlib.lua:66: in main chunk


OK, seems it is a PatternTrackLine object, not a table as such. Sure with these types of Renoise defined objects using var = object actually copies the object, not just points to it like it does with a table. If you use var =[1].tracks[1]:line(1) and then edit line 1 and after print var does it really print the changed value?

(Sorry can’t be done in the TestPad and not got the time to try and set up a quick test tool right now… Especially with how much my GUI skills suck!!)

Yep it prints the changed value, if I run this code:

line =[1].tracks[1]:line(1)[1].tracks[1]:clear()  
print (line)  

I get an output of a blank pattern line, doing these steps in the terminal gives the same results, the variable always points to what is currently in the line so it seems it only references.

com.renoise.PatternRotate.xrnx does something like this, by hackily copying all properties of a line manually into a standard table:

-- copy all effect column properties from src to dest column  
local effect_column_properties = {  
function copy_effect_column(src_column, dest_column)  
 for _,property in pairs(effect_column_properties) do  
 dest_column[property] = src_column[property]  
-- copy all note column properties from src to dest column  
local note_column_properties = {  
function copy_note_column(src_column, dest_column)  
 for _,property in pairs(note_column_properties) do  
 dest_column[property] = src_column[property]  
-- creates a copy of the given patternline  
function copy_line(src_line, dest_line)  
 for index,src_column in pairs(src_line.note_columns) do  
 if (not dest_line.note_columns[index]) then  
 dest_line.note_columns[index] = {}  
 local dest_column = dest_line.note_columns[index]  
 copy_note_column(src_column, dest_column)  
 for index,src_column in pairs(src_line.effect_columns) do  
 if (not dest_line.effect_columns[index]) then  
 dest_line.effect_columns[index] = {}  
 local dest_column = dest_line.effect_columns[index]  
 copy_effect_column(src_column, dest_column)  
--- test  
local src_line =  
local temp_line = { note_columns = {}, effect_columns = {} }  
copy_line(src_line, temp_line) -- create copy  
src_line:clear() -- modify line  
copy_line(temp_line, src_line) -- restore line from copy  

Thanks taktik

That’s very useful, although completely different to the approach I have taken!

I have come up with this:

-- Function to copy track line data  
local function copy_line(pattern, track, line)  
 return tostring ([pattern].tracks[track]:line(line) )  
-- Function to write track line data  
local function write_line(source, pattern, track, line)   
 -- Write note values  
 for n = 0, 11 do  
 local s = n*14+1  
 local note =[pattern].tracks[track].lines[line].note_columns[n+1]  
 note.note_string = string.sub(source, s, s+2)  
 note.instrument_string = string.sub(source, s+3, s+4)  
 note.volume_string = string.sub(source, s+5, s+6)  
 note.panning_string = string.sub(source, s+7, s+8)  
 note.delay_string = string.sub(source, s+9, s+10)  
 -- Write effect values  
 for n = 0, 7 do  
 local s = n*7+169  
 local efx =[pattern].tracks[track].lines[line].effect_columns[n+1]  
 efx.number_string = string.sub(source, s, s+1)  
 efx.amount_string = string.sub(source, s+2, s+3)   
-- Call it   
write_line(copy_line(1,1,1), 1, 1, 33)  

I want this to happen in realtime so I wonder which approach executes faster?

I took the following approach in the Clip Composing Language, which is similar to taktiks.
I would guess, my method is slightly faster than taktiks, as I don’t use string-indices for
the lua tables. But I can imagine, as you are using fixed string offsets, that your string
method is maybe even faster. But you can’t be sure without benchmarking yourself :slight_smile:

class "CclLine"  
function CclLine:__init (trackidx)  
 self.track = trackidx = { } -- note columns  
 self.xc = { } -- fx columns  
 self.atm = { } -- automation data  
function CclLine:from_line (line)  
 for i, c in ipairs (line.note_columns) do  
 if (not c.is_empty) then[i] = {  
 c.note_value, c.instrument_value, c.volume_value,  
 c.panning_value, c.delay_value  
 for i, c in ipairs (line.effect_columns) do  
 if ((not c.is_empty) and c.number_string:sub (1, 1) ~= "Y") then  
 self.xc[i] = { c.number_value, c.amount_value }  
function CclLine:write (line_idx, pattern, pattern_line)  
 pattern_line:clear ()  
 for i, v in pairs ( do  
 local nc = pattern_line:note_column(i)  
 nc.note_value = v[1]  
 nc.instrument_value = v[2]  
 nc.volume_value = v[3]  
 nc.panning_value = v[4]  
 nc.delay_value = v[5]  
 for i, v in pairs (self.xc) do  
 local xc = pattern_line:effect_column(i)  
 xc.number_value = v[1]  
 xc.amount_value = v[2]  
 -- snip --  

(Full code can be found at )