Hey guys,
I’m stuck on a script I wrote that renders a song into individual patterns across a selection of tempos. Everything works perfectly except um actually getting the tempo to set.
Basically it creates a folder with the name of the project file, and then makes a bunch of sub folders according to your tempo range and increment, and then renders out the song as a set of patterns for one tempo, does the same for the next tempo etc. But I can’t get the tempo to actually set, ie everything just renders out at the same tempo.
What’s confusing is that I’ll set it via rns.transport.bpm and if you read it back it shows the tempo definitely was changed. But immediately afterward it flips back to either the lowest value of the tempo range or the global bpm of when you executed the script.
I feel like something really simple is probably going on but I dont work with Lua alot and Im just not seeing it.
I’ve tried 2 different approaches and both have the same problem. The first one uses a coroutine:
--render a song as individual patterns in a selection of tempos.
--moves from tempBpm to targetBpm in increments of tempoInc
--Creates a folder with project name, and then makes tempo sub folders like '60' '65' etc to hold renders
rns = renoise.song()
targetBpm = 80
tempBpm = 60
tempoInc = 5
local function rendering_done_callback()
print("done a render. in callback rns.transport.bpm is returning: " .. rns.transport.bpm)--this is reading the initial value of tempBpm (60) and on some occasions it reads the originalBpm of when we ran the script...in either case, it never correctly reads what we set it to down in the coroutine. I tried setting tempo up here in the callback, but that didnt work either
coroutine.resume(renderCoroutine)
if tempBpm == targetBpm then
rns.transport.bpm = originalBpm --reset to originalBpm
renoise.app():show_message("done")
end
end
-----------------this block just isolates project name so we can make a main folder to keep our tempo folders...is there a variable for project name that u can just read or is this neccessary-----
local fullDir = renoise.song().file_name --complete directory
local startEx ,endEx = string.find(fullDir,".xrns") --get start/end of extension
local i = startEx-1
local nameStart
local flag = true
while flag do --work back from extension to find a slash so we can get the project file name
if string.sub(fullDir,i,i) == "\\" then
flag = false
nameStart= i+1
else
i = i - 1
end
end
nom = string.sub(fullDir,nameStart,startEx-1) --now we have the project name
ourDir = string.sub(fullDir,1,nameStart-1) --now we have the project files's directory
newSubdir = ourDir .. nom --now we can make a folder with same name as our renoise project
os.mkdir(newSubdir) --make the folder
-----------------------------------------end of the main folder making block
originalBpm = rns.transport.bpm --save original bpm before rendering
rns.transport.bpm = tempBpm --set tempo to starting tempo
--**there are times when all our renders turn out to be at the originalBpm,
--meaning that somewhow even this line didnt take??
----------------------------------------------------------------render coroutine
renderCoroutine = coroutine.create(function()
while tempBpm < targetBpm do --for each tempo, make a folder with tempo name ie '65'. In that folder render each pattern of the sequence for that tempo.
local seqNum = 1
while seqNum <= #rns.sequencer.pattern_sequence do
local newSubSubDir = newSubdir .."\\" .. tempBpm --folder name is just the current tempo value
os.mkdir(newSubSubDir)--make the folder
local filename = newSubSubDir .. "\\" .. seqNum .. "_" .. tempBpm .. "_" .. nom .. ".wav" --filename is made up of the seqNum so we know the order plus tempo and song name, even though the name and tempo are already implied by the folder system it's inside.
local options = {
start_pos = renoise.SongPos(seqNum,1),
end_pos = renoise.SongPos(seqNum,rns.patterns[1].number_of_lines),
sample_rate = 44100,
bit_depth = 16 ,
interpolation = 'default',
priority = 'high',
}
rns:render(options, filename, rendering_done_callback) --render
seqNum = seqNum + 1
coroutine.yield()
end --end of looping thru all patterns in the sequence
tempBpm = tempBpm + tempoInc
rns.transport.bpm = tempBpm
print("we set rns.transport.bpm in our coroutine and now it returns " .. rns.transport.bpm)
end --end looping thru all tempos defined by range and increment
end)-----------------------------------------------------------------end coroutine
--call coroutine once to get it running
print("start coroutine")
coroutine.resume(renderCoroutine)
And then I also tried doing tempo incrementing inside the render call back like this:
--render a song as individual patterns in a selection of tempos.
--moves from tempBpm to targetBpm in increments of tempoInc
--Creates a folder with project name, and then makes tempo sub folders like '60' '65' etc to hold renders
rns = renoise.song()
targetBpm = 80
tempBpm = 60
tempoInc = 5
seqNum = 1
local function rendering_done_callback()
print("done a render. in callback rns.transport.bpm is returning: " .. rns.transport.bpm)--this is reading the initial
local renderAgain = false
seqNum = seqNum + 1
if seqNum <= #rns.sequencer.pattern_sequence then --if more patterns in sequence, render again
renderAgain = true
else --if no more patterns in sequence, increment tempo, and mabe render again
seqNum = 1
tempBpm = tempBpm + tempoInc
rns.transport.bpm = tempBpm
print("just set bpm within callback and it reads: " .. rns.transport.bpm )
if tempBpm < targetBpm then
renderAgain = true
else
end
end
if renderAgain == true then
newSubSubDir = newSubdir .."\\" .. tempBpm --folder name is just the current tempo value
os.mkdir(newSubSubDir)--make the folder
filename = newSubSubDir .. "\\" .. seqNum .. "_" .. tempBpm .. "_" .. nom .. ".wav" --filename is made up of the seqNum so we know the order plus tempo and song name, even though the name and tempo are already implied by the folder system it's inside.
local options = {
start_pos = renoise.SongPos(seqNum,1),
end_pos = renoise.SongPos(seqNum,rns.patterns[1].number_of_lines),
sample_rate = 44100,
bit_depth = 16 ,
interpolation = 'default',
priority = 'high',
}
print("call render from callback")
rns:render(options, filename, rendering_done_callback) --render
end
if renderAgain ~= true then
rns.transport.bpm = originalBpm --reset to originalBpm
renoise.app():show_message("done")
end
end
-----------------this block just isolates project name so we can make a main folder to keep our tempo folders...is there a variable for project name that u can just read or is this neccessary-----
local fullDir = renoise.song().file_name --complete directory
local startEx ,endEx = string.find(fullDir,".xrns") --get start/end of extension
local i = startEx-1
local nameStart
local flag = true
while flag do --work back from extension to find a slash so we can get the project file name
if string.sub(fullDir,i,i) == "\\" then
flag = false
nameStart= i+1
else
i = i - 1
end
end
nom = string.sub(fullDir,nameStart,startEx-1) --now we have the project name
ourDir = string.sub(fullDir,1,nameStart-1) --now we have the project files's directory
newSubdir = ourDir .. nom --now we can make a folder with same name as our renoise project
os.mkdir(newSubdir) --make the folder
-----------------------------------------end of the main folder making block
originalBpm = rns.transport.bpm --save original bpm before rendering
rns.transport.bpm = tempBpm --set tempo to starting tempo
--**there are times when all our renders turn out to be at the originalBpm,
--meaning that somewhow even this line didnt take??
--------------------------------------------------------------------------------------------
newSubSubDir = newSubdir .."\\" .. tempBpm --folder name is just the current tempo value
os.mkdir(newSubSubDir)--make the folder
filename = newSubSubDir .. "\\" .. seqNum .. "_" .. tempBpm .. "_" .. nom .. ".wav" --filename is made up of the seqNum so we know the order plus tempo and song name, even though the name and tempo are already implied by the folder system it's inside.
local options = {
start_pos = renoise.SongPos(seqNum,1),
end_pos = renoise.SongPos(seqNum,rns.patterns[1].number_of_lines),
sample_rate = 44100,
bit_depth = 16 ,
interpolation = 'default',
priority = 'high',
}
print("--------------------------call render to enter into our callback queqe")
rns:render(options, filename, rendering_done_callback) --render
----------------------------------------------------------------------------------------------
neither of these work. At the moment as I test these, bpm is staying exclusively at whatever bpm I have in the box in the song tool bar. Right now its set to 200, and no matter what I do it flips back to 200 every time after being set via the script. Even if I comment out every reference to bpm besides rns.transport.bpm = tempBpm, it still flips back. And if I remove that variable and say rns.transport.bpm = 150, it STILL flips back to 200 when I read it up in the callback.
It would be awesome if someone could run this on their computer from the tool dev window and confirm in the console that they are getting the same thing as me. This is what I get from running the first code example on a song with 3 patterns in the sequence:
start coroutine
done a render. in callback rns.transport.bpm is returning: 200
done a render. in callback rns.transport.bpm is returning: 200
done a render. in callback rns.transport.bpm is returning: 200
we set rns.transport.bpm in our coroutine and now it returns 65
done a render. in callback rns.transport.bpm is returning: 200
done a render. in callback rns.transport.bpm is returning: 200
done a render. in callback rns.transport.bpm is returning: 200
we set rns.transport.bpm in our coroutine and now it returns 70
done a render. in callback rns.transport.bpm is returning: 200
done a render. in callback rns.transport.bpm is returning: 200
done a render. in callback rns.transport.bpm is returning: 200
we set rns.transport.bpm in our coroutine and now it returns 75
done a render. in callback rns.transport.bpm is returning: 200
done a render. in callback rns.transport.bpm is returning: 200
done a render. in callback rns.transport.bpm is returning: 200
we set rns.transport.bpm in our coroutine and now it returns 80
The ‘200’ is the number I have in the bpm box in the song toolbar, and shouldnt factor in to this script at all, it gets read and saved but then is only referenced at the very end to restore tempo to whatever it was before running the script, and like I said above, if you remove all references to this, ie dont save it to a variable called originalBpm and dont restore it up in the callback routine it does the exact same thing. Also, sometimes instead of 200 I’m getting ‘60’ which is the intial value for tempBpm. It fluctuates between these randomly.
Anybody have any idea of what this could be??