The question is how to automatically write an effect to the pattern on the selected note column with a shortcut key.
I’ve already implemented the add_keybindings, so I’ve just to know the code to write desired effected, which should be something like
renoise.song().patterns[].tracks[].lines[].effect_columns (that is in read only).
Here’s a quick example that will write a random 0Sxx sample offset command:
local effect_column = renoise.song().selected_effect_column
if (effect_column ~= nil) then
effect_column.number_string = "0S"
effect_column.amount_value = math.floor(math.random() * 255)
end
currently functions with +1/+10/-10/-1 pitch-up, pitchdown, notecut, retrig, arpeggio (which i forgot to show) and vibrato.
if you want to take a peek:
function arpxy(effect,x,y)
local counter=nil
local currentamount=nil
local old_x=nil
local old_y=nil
local new_x=nil
local new_y=nil
if renoise.song().selection_in_pattern==nil then return end
for i=renoise.song().selection_in_pattern.start_line,renoise.song().selection_in_pattern.end_line
do
if
renoise.song().patterns[renoise.song().selected_pattern_index].tracks[renoise.song().selected_track_index].lines[i].effect_columns[1].amount_value == 0 and (x < 0 or y < 0)
then renoise.song().patterns[renoise.song().selected_pattern_index].tracks[renoise.song().selected_track_index].lines[i].effect_columns[1].number_string=""
else
renoise.song().patterns[renoise.song().selected_pattern_index].tracks[renoise.song().selected_track_index].lines[i].effect_columns[1].number_string=effect
old_y=renoise.song().patterns[renoise.song().selected_pattern_index].tracks[renoise.song().selected_track_index].lines[i].effect_columns[1].amount_value % 16
old_x=math.floor (renoise.song().patterns[renoise.song().selected_pattern_index].tracks[renoise.song().selected_track_index].lines[i].effect_columns[1].amount_value/16)
new_x=old_x+x
new_y=old_y+y
print ("new_x: " .. new_x)
print ("new_y: " .. new_y)
if new_x > 15 then new_x = 15 end
if new_y > 15 then new_y = 15 end
if new_y < 1 then new_y = 0 end
if new_x < 1 then new_x = 0 end
counter=(16*new_x)+new_y
renoise.song().patterns[renoise.song().selected_pattern_index].tracks[renoise.song().selected_track_index].lines[i].effect_columns[1].amount_value=counter
end
end
end
renoise.tool():add_keybinding {name = "Global:Paketti:Arp Amount Xy -1", invoke = function() arpxy("0A",-1,0) end}
renoise.tool():add_keybinding {name = "Global:Paketti:Arp Amount Xy +1", invoke = function() arpxy("0A",1,0) end}
renoise.tool():add_keybinding {name = "Global:Paketti:Arp Amount xY -1", invoke = function() arpxy("0A",0,-1) end}
renoise.tool():add_keybinding {name = "Global:Paketti:Arp Amount xY +1", invoke = function() arpxy("0A",0,1) end}
now, dblue will obviously have opinions on the ugliness of the code, and he will know how to present it more understandable, but basically this arpxy function means that if you just copy the addkeybinding and switch “0A” to ANY effect you want, you’ll be able to create +1/-1 shortcuts for either effectXy or effectxY.
Yep. I mean absolutely no offense mate, but your code is often quite “interesting”, to say the least
I love your enthusiasm, but you still have a few bad habits you need to break (not using more local variables, not taking full advantage of useful helper functions, etc), so in this case I do think it’s better to give a simple and clear example of how this stuff works, rather than a big chunk of code ripped straight from Paketti. Of course, you did also show something I did not: working with renoise.song().selection_in_pattern
Nevertheless, you have your own style of doing things, and it’s great to see how much energy you’re putting into your tool(s). Keep it up!
@esa: Just to show there are no hard feelings, here’s something that I hope will inspire you a bit
function arpxy(effect, x, y)
-- local reference to the song
local song = renoise.song()
-- local reference to the selection
local selection = song.selection_in_pattern
-- if we have no selection...
if selection == nil then
-- nothing to do!
return
end
-- local reference to the selected pattern track
local pattern_track = song.selected_pattern_track
-- loop through all selected lines
for i = selection.start_line, selection.end_line do
-- local reference to the effect column we are working with
local effect_column = pattern_track:line(i):effect_column(1)
-- if the new effect amount would go below zero...
if effect_column.amount_value == renoise.PatternTrackLine.EMPTY_EFFECT_AMOUNT and (x < 0 or y < 0) then
-- erase the effect
effect_column.number_value = renoise.PatternTrackLine.EMPTY_EFFECT_NUMBER
-- else apply our modifications to the effect x/y values
else
-- write the effect string
effect_column.number_string = effect
-- extract the old x/y values
local old_x = math.floor(effect_column.amount_value / 16)
local old_y = effect_column.amount_value % 16
-- calculate the new x/y values and limit them to 0 - 15
local new_x = math.max(0, math.min(15, old_x + x))
local new_y = math.max(0, math.min(15, old_y + y))
-- combine the new x/y values into a single amount
local amount_value = (new_x * 16) + new_y
-- write the new amount
effect_column.amount_value = amount_value
end
end
end
i also meant no offence(*). i am barely able to understand any code so it’s like “umm uh oh wow!!” followed by some more “umm uhh ?!?”. when i end up writing selected_track_index selected_pattern_index selected_line_index into those super-long strings, i keep wondering, what am i not seeing. i know you’ve tried to show it to me a few times, and i appreciate the efforts you make to beautify my (absolutely horrific looking and barely understandable) “code”.
i know this is exactly like what my 1994 .mods look like to me, just a bit of “what? was? i? thinking?”. im not sure what helper functions are, but yeah, i could shorten with a lot of locals. I see sometimes you drop in some api functions that have the character “:” in them, and those seem to be the ones used by those who have progressed further away from just poking at something in the terminal and then pasting it into a function. hence why i dont really use locals, because if i go
local sli=renoise.song().selected_line_index
i can’t test the line that uses sli on the terminal because it will shoot an error. once i can map that mess into the helpers that you guys have helpfully created in the api, i guess all my functions will work faster, better and will look prettier. i’m just poking around in the dark with grep as my makeshift flashlight and just generally makin a mess everywhere i go
i hope that i’ll eventually get the subtlety and the beauty of code and be able to make something that’s optimized and non-messy. it really feels like there’s just some sort of crucial key information that i have not been able to grok via just grepping keywords from the documentations to see which functions have “pattern” in the name, f.ex.
also im actually afraid of code, maybe that’s the reason for trying to do it in the simplest most lowlevel way possible which then ends up being just… uhh… awkward and ugly.
i hope to one day just re-write all of paketti from scratch and then be able to just get at it so that it is less prone to errors and looks less like code written, copypasted from the forums and just mucked about by someone who doesn’t know how to code.
TL;DR i know im wonky and weird but the ideas are what matter, the subtlety and beauty of code i can learn (this i know for a fact), and maybe it’ll be useful as a case-example - because many have very strong a priori opinions about lua-scripting being completely impossible to learn.
every day im more and more shocked at the possibilities of LUA. i know pretty much every bit of code in paketti can be traced back to vV, conner_bw, dblue or anyone else inside the community, and some friends i’ve had facetoface chats with and who have tried to humor me enough to kinda try and break it down to me so that i can grok it… but… the past year has been totally absolutely worth it. i still don’t understand tables, can barely comprehend what im doing most of the time, but there’s just something there that seems to work (barely)
that’s why im so chuffed about the possibility of live broadcasts of lua coding for beginners like mxb was proposing elsewhere, and i can’t wait to visit augsburg again and talk with koppi about stuff, since now he knows how to code.
and yep, i know it’s silly, but i still can’t get over how people who code are able to code something even if they have never used the language before - this coder-logic kind of thing is just a sight to behold.
(*) when i dont know something, what i do know, is that someone else will know how to do it better, just because they swim in those lakes. so i always defer to what you say.
thank you so very much. i guess i will always wonder why math.max is (0 and math.min is (15
i’ll modify the XX -type effects to use this same idea, and im sure i can pull off 0-255 with this blueprint.
math.max(a, b) will return whichever value (ie. a or b) has the highest value
Therefore, math.max(0, -1) will return 0
.
math.min(a, b) will return whichever value (ie. a or b) has the lowest value
Therefore, math.min(15, 16) will return 15
.
When you combine these functions in the correct order, you can effectively limit the range of a calculated value. That’s why math.max(0, math.min(15, some_value)) will always return a value between 0 and 15