|
|
|
01-30-2019, 11:50 PM
|
#1
|
Human being with feelings
Join Date: Nov 2010
Posts: 2,436
|
Script request: delete empty AUDIO take from item
Why is this useful?
When you loop things or have record armed many tracks that are ready to capture things that don't necessarily have to be connected at the time of recording you may end up with lots of empty audio items. When I say empty I mean audio items whose samples (all of them) are 0.
If these are saved in *.wav format you can imagine the waste of space... (thank God for wavpack)
The script would work the same way SWS/S&M: Takes - Remove empty MIDI takes/items among selected items
works but with audio takes only.
I tried to find something similar to this on ReaPack and forums but no luck...
edit: solved - go to post #5 of this thread for a fully working lua script
__________________
REAPER ReWorked: An elegant and self-sufficient all-around REAPER configuration
Other stuff
Last edited by Breeder; 09-03-2020 at 03:18 PM.
|
|
|
01-31-2019, 03:28 PM
|
#2
|
Human being with feelings
Join Date: Mar 2016
Posts: 1,239
|
But if it's an analogue input, even if nothing is connected, chances are the noise floor might cause non-zero samples surely.....?
|
|
|
01-31-2019, 03:32 PM
|
#3
|
Human being with feelings
Join Date: Nov 2010
Posts: 2,436
|
Quote:
Originally Posted by andyp24
But if it's an analogue input, even if nothing is connected, chances are the noise floor might cause non-zero samples surely.....?
|
In my case it is always 0 but in theory you can check for other values close to 0 that you judge to be acceptable in your user case.
I finished the script by myself in the end, just need to handle sample reading and then I'll post it here unless someone with ready solution pops up.
__________________
REAPER ReWorked: An elegant and self-sufficient all-around REAPER configuration
Other stuff
Last edited by Breeder; 09-03-2020 at 03:18 PM.
|
|
|
01-31-2019, 04:30 PM
|
#4
|
Human being with feelings
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
|
Quote:
Originally Posted by Breeder
just need to handle sample reading
|
These templates may come in handy:
https://github.com/ReaTeam/ReaScript...e/master/Audio
Nice script idea btw.
|
|
|
01-31-2019, 08:56 PM
|
#5
|
Human being with feelings
Join Date: Nov 2010
Posts: 2,436
|
Quote:
Originally Posted by nofish
|
Thanks!
This seems to work here for me, hope it helps someone else
Oh, and it needs SWS extension installed to make it work!
Code:
-- Globals -------------------------------------------------------------------------------------------------------------
local g_db_limit = nil -- Set to nil for "-inf" (g_db_limit = nil ...only samples with value 0.00000000001 which
-- is equal to -220db will be considered empty) or db value instead (g_db_limit = -80)
local g_delete_files_with_non_existent_source = true -- If this is true, if take's source is missing (indicated by the
-- text "offline" instead of audio peaks) it will also get deleted
-- Set to "false" to disable
-- Actions used --------------------------------------------------------------------------------------------------------
local g_cmd_delete_take = reaper.NamedCommandLookup("_S&M_DELTAKEANDFILE4") -- SWS/S&M: Delete active take and source file in selected items (no undo)
local g_cmd_unselect_all_items = 40289 -- Item: Unselect all items
-- Main ----------------------------------------------------------------------------------------------------------------
function Main ()
-- Convert g_db_limit to sample value
local dbValLimit = 0
if g_db_limit ~= nil then
dbValLimit = math.exp((g_db_limit)*0.11512925464970228420089957273422)
else
dbValLimit = 0 + 0.00000000001
end
-- Save selected items and their takes - also find empty audio takes
local emptyTakesFound = false
local selectedItems = {}
for i = 0, reaper.CountSelectedMediaItems(0)-1 do
local item = reaper.GetSelectedMediaItem(0, i)
selectedItems[i+1] = {}
selectedItems[i+1].item = item
selectedItems[i+1].allTakes = {}
for j = 0, reaper.CountTakes(item)-1 do
local take = reaper.GetTake(item, j)
selectedItems[i+1].allTakes[j+1] = {}
selectedItems[i+1].allTakes[j+1].isEmpty = true
selectedItems[i+1].allTakes[j+1].takeId = j
-- Read samples from current take and mark it as empty if no samples over g_db_limit found
if take == nil or reaper.TakeIsMIDI(take) == true then
selectedItems[i+1].allTakes[j+1].isEmpty = false
else
local src = reaper.GetMediaItemTake_Source(take)
local samplerate = reaper.GetMediaSourceSampleRate(src)
local channelCount = reaper.GetMediaSourceNumChannels(src)
local srcType = reaper.GetMediaSourceType(src, "")
local srcFile = reaper.GetMediaSourceFileName(src, "")
if g_delete_files_with_non_existent_source == true and srcFile ~= "" and srcFile ~= nil and reaper.file_exists(srcFile) == false then
selectedItems[i+1].allTakes[j+1].isEmpty = true
elseif samplerate == 0 or channelCount == 0 or srcType == "VIDEOEFFECT" or srcType == "LTC" or srcType == "CLICK" or srcType == "RPP_PROJECT" or srcType == "VIDEO" then
selectedItems[i+1].allTakes[j+1].isEmpty = false
else
local accessor = reaper.CreateTakeAudioAccessor(take)
local startTime = reaper.GetAudioAccessorStartTime(accessor)
local endTime = reaper.GetAudioAccessorEndTime(accessor)
local window = 1.0 -- 1 second
local breakNow = 0
while startTime < endTime and breakNow ~= 2 and selectedItems[i+1].allTakes[j+1].isEmpty == true do
local samplesPerChannel = math.ceil(window * samplerate)
local bufferSize = samplesPerChannel*channelCount
local buffer = reaper.new_array(samplesPerChannel*channelCount)
reaper.GetAudioAccessorSamples(accessor, samplerate, channelCount, startTime, samplesPerChannel, buffer)
-- Check all samples for values over dbValLimit and break as soon as they are found
for k = 1, bufferSize do
if math.abs(buffer[k]) > dbValLimit then
selectedItems[i+1].allTakes[j+1].isEmpty = false
break
end
end
startTime = startTime + (window - (window / 100)) -- small overlap so there are no some kind of rounding mistakes or whatever
-- If startTime passes over end time, make sure to get only the samples from the end (increase window so
-- we don't lose anything due to roding errors for the same reasons in previous line) end then break out
if startTime >= endTime then
window = window + 1
startTime = endTime - window
if startTime < 0 then
startTime = 0
end
window = endTime - startTime
breakNow = 1
end
if breakNow == 1 then
breakNow = 2
end
end
reaper.DestroyAudioAccessor(accessor)
end
end
if selectedItems[i+1].allTakes[j+1].isEmpty == true then
emptyTakesFound = true
end
end
end
-- Delete empty takes
if emptyTakesFound == true then
reaper.PreventUIRefresh(1)
reaper.Undo_BeginBlock2(0)
reaper.Main_OnCommandEx(g_cmd_unselect_all_items, 0, 0)
-- Go through all the items, deleting empty takes
for _, currentItemData in ipairs(selectedItems) do
local lastActiveTakeId = nil
for i = 0, reaper.CountTakes(currentItemData.item)-1 do
if reaper.GetActiveTake(currentItemData.item) == reaper.GetTake(currentItemData.item, i) then
lastActiveTakeId = i
break
end
end
reaper.SetMediaItemInfo_Value(currentItemData.item, "B_UISEL", 1)
-- Go through all the takes in current item and delete empty take
for _, currentTakeData in ipairs (currentItemData.allTakes) do
local currentTake = reaper.GetTake(currentItemData.item, currentTakeData.takeId)
if currentTakeData.isEmpty == true and currentTake ~= nil then
-- Delete this empty take
reaper.SetActiveTake(currentTake)
reaper.Main_OnCommandEx(g_cmd_delete_take, 0, 0)
reaper.UpdateArrange()
-- Update take ids (tried using take pointers and take guids but it seems action for deleting takes
-- changes those so it's best to use ids which are always the same but require updating due to deleting)
for _, takeData in ipairs (currentItemData.allTakes) do
if takeData.takeId > currentTakeData.takeId then
takeData.takeId = takeData.takeId - 1
end
end
if lastActiveTakeId ~= nil and lastActiveTakeId > currentTakeData.takeId then
lastActiveTakeId = lastActiveTakeId - 1
end
-- Check if active take was deleted
if currentTakeData.takeId == lastActiveTakeId then
lastActiveTakeId = nil -- if active take is the one we're
end -- deleting, no need to restore it
end
end
-- Restore active take and unselect all items
if lastActiveTakeId ~= nil then
reaper.SetActiveTake(reaper.GetTake(currentItemData.item, lastActiveTakeId))
end
reaper.Main_OnCommandEx(g_cmd_unselect_all_items, 0, 0)
reaper.UpdateArrange()
end
-- Restore item selection
for _, currentItemData in ipairs(selectedItems) do
if currentItemData.item ~= nil and reaper.ValidatePtr(currentItemData.item, "MediaItem*") then
reaper.SetMediaItemInfo_Value(currentItemData.item, "B_UISEL", 1)
end
end
reaper.PreventUIRefresh(-1)
reaper.UpdateArrange()
reaper.Undo_EndBlock2(0, "Remove empty audio takes/items among selected items and delete their source files", -1)
end
end
Main()
function NoUndoPoint () end -- Makes sure there is no unnecessary undo point created, see more
reaper.defer(NoUndoPoint) -- here: http://forum.cockos.com/showpost.php?p=1523953&postcount=67
Some effort has been invested in this. If you seriously use it, please consider supporting the developer. Thank you!
I don't mind if someone puts this script in ReaPack, but please include my donation link, forum nickname and link to this thread in the description if you do so.
__________________
REAPER ReWorked: An elegant and self-sufficient all-around REAPER configuration
Other stuff
Last edited by Breeder; 09-03-2020 at 03:18 PM.
|
|
|
02-22-2019, 11:12 PM
|
#6
|
Human being with feelings
Join Date: Nov 2010
Posts: 2,436
|
Fixed the script in my last post. Reupdate if you're using it
Bugs were:
- When deleting multiple takes in the same item, it didn't work because the action for deleting takes was changing take pointers (and take GUID it seems so take id is to be used)
- Sometimes REAPER doesn't output 0 but really small number so if using -g_db_limit = nil, it actually deletes anything below -220db
- Added the ability to delete audio files whose source is missing. This is enabled by default. Set g_delete_files_with_non_existent_source to false to disable
__________________
REAPER ReWorked: An elegant and self-sufficient all-around REAPER configuration
Other stuff
Last edited by Breeder; 09-03-2020 at 03:18 PM.
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 12:14 PM.
|