10-30-2023, 02:42 PM
|
#1 |
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 4,138
|
EDIT Solved in v7.05+dev1113 - November 13 2023!
![]() Does GetFXEnvelope() work with FX inside Container? I was expecting this would create a Wet track envelope for the focused FX when the FX is inside a FX Container, but it doesn't, returns nil,.. Code:
_, trackidx, _, _, fxidx = reaper.GetTouchedOrFocusedFX(1) -- 1 to query currently focused FX track = reaper.GetTrack(0, trackidx) wet_idx = reaper.TrackFX_GetParamFromIdent(track, fxidx, ":wet") -- get wet param index env = reaper.GetFXEnvelope(track, fxidx, wet_idx, true) -- create track envelope reaper.TrackList_AdjustWindows(false) reaper.ShowConsoleMsg(tostring(env) .. '\n') Win10, REAPER 7.00+ Last edited by Edgemeal; 11-19-2023 at 04:16 PM. |
|
|
11-12-2023, 09:06 AM
|
#2 |
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 4,138
|
Any fix planned? or should I mark this as a "live with it" thing?
BTW, for script that needs to add (and get) envelope for last touched fx param in a Container I use this workaround... 1. Save track envelopes to a table. 2. Run action 41142 ( FX: Show/hide track envelope for last touched FX parameter ). 3. Loop thru track envelopes/table to find the newly added envelope. |
|
|
11-12-2023, 03:10 PM
|
#3 |
|
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 16,810
|
Edit: making GetFXEnvelope etc support containers doesn't really make sense, since FX in the containers can't have envelopes.
BUT -- you can create a parameter map to the parent container, then get the envelope for that. Lemme write you some code to do this, one sec. Last edited by Justin; 11-12-2023 at 03:23 PM. |
|
|
11-12-2023, 05:33 PM
|
#4 |
|
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 16,810
|
ok, here's some code that should be useful:
Code:
function get_fx_id_from_container_path(tr, idx1, ...) -- returns a fx-address from a list of 1-based IDs
local sc,rv = reaper.TrackFX_GetCount(tr)+1, 0x2000000 + idx1
for i,v in ipairs({...}) do
local ccok, cc = reaper.TrackFX_GetNamedConfigParm(tr, rv, 'container_count')
if ccok ~= true then return nil end
rv = rv + sc * v
sc = sc * (1+tonumber(cc))
end
return rv
end
function get_container_path_from_fx_id(tr, fxidx) -- returns a list of 1-based IDs from a fx-address
if fxidx & 0x2000000 then
local ret = { }
local n = reaper.TrackFX_GetCount(tr)
local curidx = (fxidx - 0x2000000) % (n+1)
local remain = math.floor((fxidx - 0x2000000) / (n+1))
if curidx < 1 then return nil end -- bad address
local addr, addr_sc = curidx + 0x2000000, n + 1
while true do
local ccok, cc = reaper.TrackFX_GetNamedConfigParm(tr, addr, 'container_count')
if not ccok then return nil end -- not a container
ret[#ret+1] = curidx
n = tonumber(cc)
if remain <= n then if remain > 0 then ret[#ret+1] = remain end return ret end
curidx = remain % (n+1)
remain = math.floor(remain / (n+1))
if curidx < 1 then return nil end -- bad address
addr = addr + addr_sc * curidx
addr_sc = addr_sc * (n+1)
end
end
return { fxid+1 }
end
function fx_map_parameter(tr, fxidx, parmidx) -- maps a parameter to the top level parent, returns { fxidx, parmidx }
local path = get_container_path_from_fx_id(tr, fxidx)
if not path then return nil end
while #path > 1 do
fxidx = path[#path]
table.remove(path)
local cidx = get_fx_id_from_container_path(tr,table.unpack(path))
if cidx == nil then return nil end
local i, found = 0, nil
while true do
local rok, r = reaper.TrackFX_GetNamedConfigParm(tr,cidx,string.format("param.%d.container_map.fx_index",i))
if not rok then break end
if tonumber(r) == fxidx - 1 then
rok, r = reaper.TrackFX_GetNamedConfigParm(tr,cidx,string.format("param.%d.container_map.fx_parm",i))
if not rok then break end
if tonumber(r) == parmidx then found = true parmidx = i break end
end
i = i + 1
end
if not found then
-- add a new mapping
local rok, r = reaper.TrackFX_GetNamedConfigParm(tr,cidx,"container_map.add")
if not rok then return nil end
r = tonumber(r)
reaper.TrackFX_SetNamedConfigParm(tr,cidx,string.format("param.%d.container_map.fx_index",r),tostring(fxidx - 1))
reaper.TrackFX_SetNamedConfigParm(tr,cidx,string.format("param.%d.container_map.fx_parm",r),tostring(parmidx))
parmidx = r
end
end
return fxidx, parmidx
end
-- example use
track = reaper.GetTrack(0,0);
id = get_fx_id_from_container_path(track, 2, 1, 2, 1) -- test hierarchy
fxidx,fxparm = fx_map_parameter(track,id,5)
env = reaper.GetFXEnvelope(track,fxidx,fxparm,true)
reaper.TrackList_AdjustWindows(true)
(this is more work than it should be -- we should make GetFXEnvelope() support container addreses, and probably add an API to auto-map parameters, but for now this will work for 7.0x at least...) |
|
|
11-12-2023, 09:20 PM
|
#5 | |
|
Human being with feelings
Join Date: Apr 2016
Location: ASU`ogacihC
Posts: 4,138
|
Quote:
Yes, API support would be awesome!
|
|
|
|
11-13-2023, 05:05 AM
|
#6 | |
|
Human being with feelings
Join Date: May 2017
Location: Somewhere over the Rainbow
Posts: 6,966
|
Quote:
Even if it's only working with a csv of the container-index-numbers?
__________________
Use you/she/her.Ultraschall-Api Lua Api4Reaper - ReaGirl - a GuiLib for guis working for blind people |
|
|
|
11-13-2023, 05:30 AM
|
#7 |
|
Human being with feelings
Join Date: Jul 2022
Location: Japan
Posts: 904
|
Great! It works for take FX inside container with a bit of modification. I also vote for API though.
Code:
function get_take_fx_id_from_container_path(tr, idx1, ...) -- returns a fx-address from a list of 1-based IDs
local sc,rv = reaper.TakeFX_GetCount(tr)+1, 0x2000000 + idx1
for i,v in ipairs({...}) do
local ccok, cc = reaper.TakeFX_GetNamedConfigParm(tr, rv, 'container_count')
if ccok ~= true then return nil end
rv = rv + sc * v
sc = sc * (1+tonumber(cc))
end
return rv
end
function get_container_path_from_take_fx_id(tr, fxidx) -- returns a list of 1-based IDs from a fx-address
if fxidx & 0x2000000 then
local ret = { }
local n = reaper.TakeFX_GetCount(tr)
local curidx = (fxidx - 0x2000000) % (n+1)
local remain = math.floor((fxidx - 0x2000000) / (n+1))
if curidx < 1 then return nil end -- bad address
local addr, addr_sc = curidx + 0x2000000, n + 1
while true do
local ccok, cc = reaper.TakeFX_GetNamedConfigParm(tr, addr, 'container_count')
if not ccok then return nil end -- not a container
ret[#ret+1] = curidx
n = tonumber(cc)
if remain <= n then if remain > 0 then ret[#ret+1] = remain end return ret end
curidx = remain % (n+1)
remain = math.floor(remain / (n+1))
if curidx < 1 then return nil end -- bad address
addr = addr + addr_sc * curidx
addr_sc = addr_sc * (n+1)
end
end
return { fxid+1 }
end
function take_fx_map_parameter(tr, fxidx, parmidx) -- maps a parameter to the top level parent, returns { fxidx, parmidx }
local path = get_container_path_from_take_fx_id(tr, fxidx)
if not path then return nil end
while #path > 1 do
fxidx = path[#path]
table.remove(path)
local cidx = get_take_fx_id_from_container_path(tr,table.unpack(path))
if cidx == nil then return nil end
local i, found = 0, nil
while true do
local rok, r = reaper.TakeFX_GetNamedConfigParm(tr,cidx,string.format("param.%d.container_map.fx_index",i))
if not rok then break end
if tonumber(r) == fxidx - 1 then
rok, r = reaper.TakeFX_GetNamedConfigParm(tr,cidx,string.format("param.%d.container_map.fx_parm",i))
if not rok then break end
if tonumber(r) == parmidx then found = true parmidx = i break end
end
i = i + 1
end
if not found then
-- add a new mapping
local rok, r = reaper.TakeFX_GetNamedConfigParm(tr,cidx,"container_map.add")
if not rok then return nil end
r = tonumber(r)
reaper.TakeFX_SetNamedConfigParm(tr,cidx,string.format("param.%d.container_map.fx_index",r),tostring(fxidx - 1))
reaper.TakeFX_SetNamedConfigParm(tr,cidx,string.format("param.%d.container_map.fx_parm",r),tostring(parmidx))
parmidx = r
end
end
return fxidx, parmidx
end
--------
local track = r.GetSelectedTrack2(0, 0, true)
local retval, trackidx, itemidx, takeidx, fxidx, parm = r.GetTouchedOrFocusedFX(0)
local item = r.GetMediaItem(0, itemidx)
local take = r.GetMediaItemTake(item, takeidx)
local path = get_container_path_from_take_fx_id(take, fxidx)
if path then
fxidx, parm = take_fx_map_parameter(take, fxidx, parm)
end
local env = r.TakeFX_GetEnvelope(take, fxidx, parm, true)
r.TrackList_AdjustWindows(false)
|
|
|
11-13-2023, 08:48 AM
|
#8 |
|
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 16,810
|
making these APIs work for containers, and also some very helpful attributes for FX_GetNamedConfigParm for the next builds to make this stuff a lot more convenient
|
|
|
06-16-2025, 11:04 AM
|
#9 |
|
Human being with feelings
Join Date: Dec 2023
Location: Denmark
Posts: 722
|
Trying to find head and tail in containers.
Not sure if I missed something in the code examples Justin shared, but could get the data I wanted. I wanted to find the param and container pos of a mapped parameter that's inside a container (or multiple containers), but without creating the mapping if it didn't exist. I believe I get this now constantly, by modifing the fx_map_parameter function. The function below returns the index of the root container and the index of the mapped parameter within the root container, in case it would be useful to others: Code:
function fx_get_mapped_parameter(tr, fxidx, parmidx) -- maps a parameter to the top level parent, returns { fxidx, parmidx }
local path = get_container_path_from_fx_id(tr, fxidx)
local rootContainerPos = path[1] - 1
if not path then return nil end
while #path > 1 do
fxidx = path[#path]
table.remove(path)
local cidx = get_fx_id_from_container_path(tr,table.unpack(path))
if cidx == nil then return nil end
local i, found = 0, nil
while true do
local rok, r = reaper.TrackFX_GetNamedConfigParm(tr,cidx,string.format("param.%d.container_map.fx_index",i))
reaper.ShowConsoleMsg(r .. " r\n")
if not rok then break end
if tonumber(r) == fxidx - 1 then
rok, r = reaper.TrackFX_GetNamedConfigParm(tr,cidx,string.format("param.%d.container_map.fx_parm",i))
if not rok then break end
if tonumber(r) == parmidx then found = true; parmidx = i; break end
end
i = i + 1
end
if not found then
if not found then
-- add a new mapping
local rok, r = reaper.TrackFX_GetNamedConfigParm(tr,cidx,"container_map.add")
reaper.ShowConsoleMsg(r .. "\n")
if not rok then return nil end
r = tonumber(r)
reaper.TrackFX_SetNamedConfigParm(tr,cidx,string.format("param.%d.container_map.fx_index",r),tostring(fxidx - 1))
reaper.TrackFX_SetNamedConfigParm(tr,cidx,string.format("param.%d.container_map.fx_parm",r),tostring(parmidx))
parmidx = r
end
end
end
return rootContainerPos, parmidx
end
__________________
Trying to make Reaper the best DAW for film composing! ReaPack - Script thread - Help me make more free scripts |
|
|
![]() |
| Thread Tools | |
|
|