For the case above, this will do the job just fine:
local line = renoise.song().patterns[pattern_index].tracks[track_index].lines[line_index]
for i = 1 , 12 do
note_table[i] = line.note_columns[i].note_value
end
-- or all notes in a pattern:
local pattern = renoise.song().selected_pattern
for _, track in pairs(pattern.tracks) do
for _, line in pairs(track.lines) do
for _, note_column in pairs(line.note_columns) do
print(note_column.note_value)
end
end
end
Avoid calling too much renoise. stuff within loops again and again. Use locals or pairs instead. This is what may be slow and the iterators avoid…
Have to just say this was good advice and has helped speed a few things up here (though unfortunately not the iterator I was hoping for)
Anyway, I had wondered what all the code like this I had seen before was about, as I had confused it with creating objects from classes. (or maybe it is? )
I shall be applying this where possible to my for loops in the future…
In the example scripts, the pattern iterator to simply change specific notes within a selection.
Is this the most efficient method? I am modifying it to change the instrument value of a selection and it seems to take quite a bit more time than the blink of an eye.
I imagine that operating directly on a selection as in taktik’s example above would be more efficient, though in my example the start and end points of a selected block would need to be implemented.
function SetInstrument()
local pattern_iter = renoise.song().pattern_iterator
local pattern_index = renoise.song().selected_pattern_index
for pos,line in pattern_iter:lines_in_pattern(pattern_index) do
for _,note_column in pairs(line.note_columns) do
if (line.note_columns[1].is_selected) then
line.note_columns[1].instrument_value = renoise.song().selected_instrument_index-1
end
end
end
end
Below is the cpu stats as i execute the above script about six times over ten seconds. It really is quite slow and cpu intensive. Am I using it incorrectly? Is there a more efficient way to alter instrument info of a selection?
Everytime you call ITER, you iterate the whole pattern again, you only need to iterate it once and then process the contents.
Just to redirect you more to the correct method:
iter = song.pattern_iterator:lines_in_track(track_index)
for _,line in iter do
for cur_column,note_column in ipairs(line.note_columns) do
if area_to_process == OPTION_SELECTION_IN_TRACK and note_column.is_selected then
line.note_columns[1].instrument_value = renoise.song().selected_instrument_index-1
end
end
end
No, that’s not true. Wonder where you have that information from? We often just used this as shortcut.
Because column.is_selected is the only way to access selections right now, there are know further optimizations available that I’m aware of.
But in your SetInstrument() function you do iterate over all note_columns, but only access the first one, so this would a more “correct” and slightly more efficient version:
local EMPTY_INSTRUMENT = renoise.PatternTrackLine.EMPTY_INSTRUMENT
local pattern_iter = renoise.song().pattern_iterator
local pattern_index = renoise.song().selected_pattern_index
for _,line in pattern_iter:lines_in_pattern(pattern_index) do
-- will be nil when a send or the master track is iterated
local first_note_column = line.note_columns[1]
if (first_note_column and
first_note_column.instrument_value ~= EMPTY_INSTRUMENT and
first_note_column.is_selected)
then
first_note_column.instrument_value = renoise.song().selected_instrument_index - 1
end
end
Performance wise this looks just fine to me - no noticeable lag, CPU spike here.
If you want all note columns and not just the first one, avoid calling line.note_columns too often:
local EMPTY_INSTRUMENT = renoise.PatternTrackLine.EMPTY_INSTRUMENT
local pattern_iter = renoise.song().pattern_iterator
local pattern_index = renoise.song().selected_pattern_index
for _,line in pattern_iter:lines_in_pattern(pattern_index) do
for _, note_column in pairs(line.note_columns) do
if (note_column.instrument_value ~= EMPTY_INSTRUMENT and note_column.is_selected) then
note_column.instrument_value = renoise.song().selected_instrument_index - 1
end
end
end
I recalled a reply in the back of my head from you somewhere back in the Alpha period where i made this mistake calling the iterator every time a next for loop was recycled, thus having the pattern being completely reprocessed every “for” iteration turn. Perhaps i’m misinterpreting the code here, but given the description of Protman’s response it looks quite similar to what i experienced back then.