So I am trying to write a script that initializes a song with 16 tracks, a specific set of effects on each one and does midi mapping on my controller, setting up lights, listeners, etc.
It seems like this should be simple enough, but even when working with GPT, I’m getting confounded by the API and how to look up device names and how to insert them. For reference, the below is the broken script I’m working with, and it fails immediately on trying to insert an effect on a track with the error
failed to instantiate the device ‘Audio Effects/Gainer’. the device is either unknown, or an error happened while initializing it.’
I have zero idea how to start troubleshooting this. For reference, I’m an professional c++ dev and experienced renoise user, but I don’t have Lua experience or experience with the API. It seems like this should be doable ???
– Number of Tracks and Controllers
local NUM_TRACKS = 16
local MIDIMIX_CONTROLLERS = { “MIDImix 1”, “MIDImix 2” } – Adjust names if needed
– Plugin Names (the names we use to later search within a track)
local GAIN_NAME = “MIDIMIX_MUTE_GAIN” – Our renamed gainer
local FILTER_NAME = “Analog Filter”
local SEND_1_NAME = “Send 1”
local SEND_2_NAME = “Send 2”
– Ensure at least two send tracks exist.
function ensure_send_tracks()
local song = renoise.song()
local send_count = 0
– Count existing send tracks (they are part of song.tracks)
for _, track in ipairs(song.tracks) do
if track.type == renoise.Track.TRACK_TYPE_SEND then
send_count = send_count + 1
end
end
– Add send tracks if fewer than 2 exist
while send_count < 2 do
song:insert_track_at(#song.tracks + 1)
local new_track = song.tracks[#song.tracks]
new_track.type = renoise.Track.TRACK_TYPE_SEND
new_track.name = "Send Track " … (send_count + 1)
send_count = send_count + 1
end
end
– Initialize regular tracks with our effects chain.
function initialize_tracks()
local song = renoise.song()
– Make sure send tracks exist before modifying our track devices
ensure_send_tracks()
– Create regular tracks if there aren’t enough
while #song.tracks < NUM_TRACKS do
song:insert_track_at(#song.tracks + 1)
end
– Set up each regular track (first NUM_TRACKS tracks assumed to be regular)
for i = 1, NUM_TRACKS do
local track = song.tracks[i]
track.name = "MIDIMIX Track " … i
track.prefx_volume.value = 1.0 – Full volume
-- Insert devices AFTER the built-in Volume/Pan device:
-- 1. Insert Gainer (to be used as a mute switch)
local mute_gain = track:insert_device_at("Audio Effects/Gainer", 2)
mute_gain.name = GAIN_NAME
-- Instead of using -INF, use the parameter's minimum value.
mute_gain.parameters[1].value = mute_gain.parameters[1].value_range.min
mute_gain.is_active = false -- Start inactive
-- 2. Insert Lowpass Filter
local filter = track:insert_device_at("Audio Effects/Analog Filter", 3)
filter.name = FILTER_NAME
-- 3. Insert Send 1 device
local send1 = track:insert_device_at("Audio Effects/Send", 4)
send1.name = SEND_1_NAME
send1.parameters[1].value = 0.5 -- Default send amount (normalized)
-- 4. Insert Send 2 device
local send2 = track:insert_device_at("Audio Effects/Send", 5)
send2.name = SEND_2_NAME
send2.parameters[1].value = 0.5 -- Default send amount (normalized)
end
end
– MIDI Mapping for Two MIDIMixes (only basic mappings shown)
function map_midi_controls()
local song = renoise.song()
for midimix_index, device_name in ipairs(MIDIMIX_CONTROLLERS) do
for i = 1, 8 do – 8 channels per MIDIMix
local track_index = (midimix_index - 1) * 8 + i
if track_index > NUM_TRACKS then break end
local track = song.tracks[track_index]
-- Map Fader to Track Volume
renoise.tool():add_midi_mapping {
name = "MIDIMix: Fader " .. i,
invoke = function(value)
track.prefx_volume.value = value / 127 -- Normalize to 0-1
end
}
-- Map Mute Button to toggle MIDIMIX_MUTE_GAIN (the gainer)
renoise.tool():add_midi_mapping {
name = "MIDIMix: Mute " .. i,
invoke = function()
local mute_gain = nil
for _, device in ipairs(track.devices) do
if device.name == GAIN_NAME then
mute_gain = device
break
end
end
if mute_gain then
mute_gain.is_active = not mute_gain.is_active
end
end
}
-- Map Knob 1 to Lowpass Filter cutoff
renoise.tool():add_midi_mapping {
name = "MIDIMix: Knob 1 " .. i,
invoke = function(value)
local filter = nil
for _, device in ipairs(track.devices) do
if device.name == FILTER_NAME then
filter = device
break
end
end
if filter then
filter.parameters[1].value = value / 127
end
end
}
-- Map Knob 2 to Send 1 amount
renoise.tool():add_midi_mapping {
name = "MIDIMix: Knob 2 " .. i,
invoke = function(value)
local send1 = nil
for _, device in ipairs(track.devices) do
if device.name == SEND_1_NAME then
send1 = device
break
end
end
if send1 then
send1.parameters[1].value = value / 127
end
end
}
-- Map Knob 3 to Send 2 amount
renoise.tool():add_midi_mapping {
name = "MIDIMix: Knob 3 " .. i,
invoke = function(value)
local send2 = nil
for _, device in ipairs(track.devices) do
if device.name == SEND_2_NAME then
send2 = device
break
end
end
if send2 then
send2.parameters[1].value = value / 127
end
end
}
-- (Optionally, you can add a mapping for the Rec/Arm button here)
end
end
end
– Run the Initial Setup
initialize_tracks()
map_midi_controls()
renoise.app():show_status(“MIDIMix Setup Complete!”)