Expand Selection Keybinding Needs Optimization

I made an Expand Selection tool which can be key-bound, however, it runs very slowly when run within a large pattern; ex:512 rows.

Any ideas on how it may be optimized? The size of the selection seems to matter less than the size of the pattern. Next will be Shrink Selection :)

These do the same as advanced-edit Shrink and Expand, but they do not alter the size of the actual selection after executing. I have the code to resize the position of the selection area. What would be most preferred? Impulse Tracker did not resize the selection area. Since this performs the expand/shrink on any tracks with any columns selected, if I change the area of the selection, it would make sense to expand so all rows are selected within the expanded area. this would also be great to get working on a per-column basis rather than track only.

  
  
function cpcl_line(track, from_line, to_line)  
 local cur_track = renoise.song().selected_pattern.tracks[track]  
 cur_track.lines[to_line]:copy_from(cur_track.lines[from_line])  
 cur_track.lines[from_line]:clear()  
 cur_track.lines[to_line+1]:clear()  
end  
  
function ExpandSelection()  
 local sl = renoise.song().selection_in_pattern.start_line  
 local el = renoise.song().selection_in_pattern.end_line  
 local st = renoise.song().selection_in_pattern.start_track  
 local et = renoise.song().selection_in_pattern.end_track  
 local nl = renoise.song().selected_pattern.number_of_lines  
 local tr  
  
 for tr=st,et do  
 for l =el,sl,-1 do  
 if l ~= sl and l*2-sl <= nl  
 then  
 cpcl_line(tr,l,l*2-sl)  
 end  
 end  
 end  
end  

I don’t really have much of an idea as to how the for / if stuff could be made to work out quicker, and I’m not even sure if this would help, but this just occurred to me - maybe it’s just for beautification and nothin else, i don’t know.

For starters:

  
  
function cpcl_line(track, from_line, to_line)  
 local cur_track = renoise.song():pattern(renoise.song().selected_pattern_index):track(track)  
 cur_track:line(to_line):copy_from(cur_track:line(from_line))  
 cur_track:line(from_line):clear()  
 cur_track:line(to_line+1):clear()  
end  
  
function ExpandSelection()  
 local sl = renoise.song().selection_in_pattern.start_line  
 local el = renoise.song().selection_in_pattern.end_line  
 local st = renoise.song().selection_in_pattern.start_track  
 local et = renoise.song().selection_in_pattern.end_track  
 local nl = renoise.song().selected_pattern.number_of_lines  
 local tr  
  
 for tr=st,et do  
 for l =el,sl,-1 do  
 if l ~= sl and l*2-sl <= nl  
 then  
 cpcl_line(tr,l,l*2-sl)  
 end  
 end  
 end  
end  

Just a little faster ;)

I thought it might have had something to do with the plural "s"s :)

I’ll start working on the Shrink Selection binding.

Thanks!

Godspeed!

(already tried the “*2” to “*0.5” replacement ““method”” and, well, obviously it’s not that easy :)

Shrink Selection :)
Though imho, it should run even faster. It still seems to take 100ms or so on large patterns/selections.

function cpclsh_line(track, from_line, to_line)  
 local cur_track = renoise.song():pattern(renoise.song().selected_pattern_index):track(track)  
 cur_track:line(to_line):copy_from(cur_track:line(from_line))  
 cur_track:line(from_line):clear()  
 cur_track:line(from_line+1):clear()  
end  
  
function ShrinkSelection()  
 local sl = renoise.song().selection_in_pattern.start_line  
 local el = renoise.song().selection_in_pattern.end_line  
 local st = renoise.song().selection_in_pattern.start_track  
 local et = renoise.song().selection_in_pattern.end_track  
-- local nl = renoise.song().selected_pattern.number_of_lines  
 local tr  
  
 for tr=st,et do  
 for l =sl,el,2 do  
 if l ~= sl  
 then  
 cpclsh_line(tr,l,l/2+sl/2)  
 end  
 end  
 end  
end  
  

I don’t think you could go much faster.

  1. An alternative is to use pattern_iterator (patterntrack, and check line.is_selected in it) but I don’t think that will be faster.

  2. Setting cur_track before the for loop and passing it to cpclsh_line() might be faster. It’s worth trying.

  1. Implementing this condition should speed it up (significantly?) in most cases:
if not cur_track:line(from_line).is_empty then  

Eg:

  
function cpcl_line(cur_track, from_line, to_line)  
 if not cur_track:line(from_line).is_empty then  
 cur_track:line(to_line):copy_from(cur_track:line(from_line))  
 cur_track:line(from_line):clear()  
 cur_track:line(to_line+1):clear()  
 end  
end  
  
function ExpandSelection()  
 local sl = renoise.song().selection_in_pattern.start_line  
 local el = renoise.song().selection_in_pattern.end_line  
 local st = renoise.song().selection_in_pattern.start_track  
 local et = renoise.song().selection_in_pattern.end_track  
 local nl = renoise.song().selected_pattern.number_of_lines  
 local tr  
 local song = renoise.song()  
  
 for tr=st,et do  
 local cur_track = song:pattern(song.selected_pattern_index):track(tr)  
 if not cur_track.is_empty then  
 for l =el,sl,-1 do  
 if l ~= sl and l*2-sl <= nl then  
 cpcl_line(cur_track,l,l*2-sl)  
 end  
 end   
 end  
 end  
end