|
|
|
03-16-2024, 05:32 AM
|
#1
|
Human being with feelings
Join Date: Jun 2011
Location: United States
Posts: 6
|
Questions about reaper.CalculateNormalization
Hi all,
I'm looking for some help in using reaper.CalculateNormalization in a script. My goal is to read the LUFS value from the first item in a selection, and use that returned LUFS value as the normalizeTarget argument in reaper.CalculateNormalization to match the subsequent items' loudness to the first item
However I'm running into the problem of the subsequent items' loudness ending up being about 3db quieter than the target, even when applying to the exact same item, so I think I'm doing something wrong. In the past I've done this manually using the SWS Loudness extension, analyzing all items, then selecting all but the first and using the "Normalize.." option to manually enter the target, but I'm trying to automate this.
I've attached a picture below showing the comparison. Item 1 on each track is reference, purple items are all the exact same item, and the grey item is the one with different volume. SWS normalize results in a value of +0.26dB, but the script getting the LUFS value using reaper.NF_AnalyzeTakeLoudness_IntegratedOnly, then using reaper.CalculateNormalization to set to that target LUFS value results in -3.55dB, and -3.18dB on the exact same item, so obviously I've screwed something up since doing this to the same item should result in no change.
Can someone help point out my mistake? Here's my code:
Code:
count_items = reaper.CountSelectedMediaItems(0)
selected_items = {}
for i = 0, reaper.CountSelectedMediaItems(0)-1 do
selected_items[i+1] = reaper.GetSelectedMediaItem(0, i)
end
if count_items > 0 then -- if any items are selected
for index, it in ipairs(selected_items) do
item = it
take = reaper.GetActiveTake(item)
itemname = reaper.GetTakeName(take)
src = reaper.GetMediaItemTake_Source(take)
sourceoffset = reaper.GetMediaItemTakeInfo_Value(take, "D_STARTOFFS")
item_length = reaper.GetMediaItemInfo_Value(item, "D_LENGTH")
source_end = sourceoffset + item_length
source_start = sourceoffset
if(index == 1)then
_, volume_ref = reaper.NF_AnalyzeTakeLoudness_IntegratedOnly(take) -- get LUFS value of first item
else
volume_correction = reaper.CalculateNormalization(src, 0, volume_ref, source_start, source_end) -- normalize subsequent items to first LUFS value
reaper.SetMediaItemTakeInfo_Value(take, "D_VOL", volume_correction) --apply volume correction to take
end
end
end
|
|
|
03-16-2024, 05:46 AM
|
#2
|
Administrator
Join Date: Mar 2007
Location: NY
Posts: 15,749
|
My guess would be the extension function is not calculating stereo loudness on these stereo items. A loudness difference from expectations of 3dB is usually caused by a mono vs stereo calculation.
You don't need to use the extension function, though. You could do something like this instead (this is not real code):
Code:
baseline_correction = reaper.CalculateNormalization(reference_item, lufs_i, target_of_zero_lu)
correction = reaper.CalculateNormalization(other_item, lufs_i, target_of_zero_lu))
reaper.SetMediaItemTakeInfo_Value(other_item, "D_VOL", correction/baseline_correction)
In other words, if the baseline reference item needs a correction of X to get to 0 LU, and the other item needs a correction of Y to get to 0 LU, that's the same as saying the other item needs a correction of X/Y to get to the same LU as the reference item.
|
|
|
03-16-2024, 05:50 AM
|
#3
|
Human being with feelings
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
|
Quote:
Originally Posted by C. Yoder
However I'm running into the problem of the subsequent items' loudness ending up being about 3db quieter than the target
|
A difference of 3 dB almost certainly hints to a mono vs. stereo issue.
Are you working on mono takes?
Please see the signal flow here, SWS loudness for takes is measured directly on the takes itself, while Reaper's loudness calculation is measured in a track context (I think), and since Reaper's tracks are always stereo this would result in the 3 dB difference.
Does this make sense?
edit:
Ninja'ed by schwa.
Last edited by nofish; 03-16-2024 at 06:04 AM.
|
|
|
03-16-2024, 06:51 AM
|
#4
|
Human being with feelings
Join Date: Mar 2016
Location: Italy
Posts: 322
|
Code:
reaper.SetMediaItemTakeInfo_Value(take, "D_VOL", volume_correction)
"D_VOL" is an absolute value and not a DB value
Code:
reaper.NF_AnalyzeTakeLoudness_IntegratedOnly(take)
it's a very slow function, you should follow SCHWA suggestion and see the difference between takes by using a reference level, like a classic - 23
you should add
Code:
reaper.UpdateArrange()
at the end of your code to update the arrange window and check the updated gain results
|
|
|
03-16-2024, 07:49 AM
|
#5
|
Human being with feelings
Join Date: Jun 2011
Location: United States
Posts: 6
|
Thank you all! That's very interesting to know about the mono vs stereo calculation. However, @schwa, that code worked perfectly to solve my problem, and feels a bit more clean since it's using the same calculation method. Again, much appreciated
@80icio - Thanks for pointing that out. The code above is actually stripped down for readability, and the full code has more of those niceties like undo points, update arrange, etc. but didn't want to clutter things for my question.
|
|
|
03-16-2024, 01:52 PM
|
#6
|
Human being with feelings
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
|
Quote:
Originally Posted by 80icio
Code:
reaper.NF_AnalyzeTakeLoudness_IntegratedOnly(take)
it's a very slow function
|
Did you do any benchmarks/comparisons? (just curious )
|
|
|
03-16-2024, 02:58 PM
|
#7
|
Human being with feelings
Join Date: Mar 2016
Location: Italy
Posts: 322
|
Quote:
Originally Posted by nofish
Did you do any benchmarks/comparisons? (just curious )
|
this is 7 items (roughly 1 min length total)
reaper.NF_AnalyzeTakeLoudness_IntegratedOnly
2.1809449195862 sec
reaper.CalculateNormalization
0.056704998016357 sec
the difference is enormous.
reaper.NF_AnalyzeTakeLoudness_IntegratedOnly is an extension function,
You can clearly spot the speed difference if you compare these 2 actions as well
SWS/BR: Normalize loudness of selected items to -23 LUFS
VS.
Item properties: Normalize items (peak/RMS/LUFS)...
|
|
|
03-16-2024, 05:11 PM
|
#8
|
Human being with feelings
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
|
Wow that's striking indeed, thanks.
I didn't code the original SWS loudness functions (that's Breeder), but I exposed them to ReaScript (NF_ = nofish), but I never compared them to the native ones which came to Reaper later on.
Nice that they are available now.
|
|
|
03-17-2024, 01:43 AM
|
#9
|
Human being with feelings
Join Date: Mar 2016
Location: Italy
Posts: 322
|
Quote:
Originally Posted by nofish
Wow that's striking indeed, thanks.
I didn't code the original SWS loudness functions (that's Breeder), but I exposed them to ReaScript (NF_ = nofish), but I never compared them to the native ones which came to Reaper later on.
Nice that they are available now.
|
I'd bet that function is slower due to the progress bar more than the analysis itself or the fact that is not a native one.
SWS/BR: Normalize loudness of selected items to -23 LUFS
Is the actual reason I started using REAPER.
No daws had anything like that, it saved me so much time on hundreds of mastering sessions.
That's why I deeply know the function.
Now I'm a full day Reaper user.
Thanks to you and Breeder
|
|
|
03-17-2024, 02:58 AM
|
#10
|
Human being with feelings
Join Date: May 2015
Location: Québec, Canada
Posts: 4,937
|
It spends 80% of the time doing GetAudioAccessorSamples reading 10ms or 200ms worth of audio. ~0.6ms each call a couple thousands of times quickly adds up. Changing it to read fewer, larger chunks could be worth a try.
EDIT: That was on a 4 mins Opus file (~800ms reading, ~200ms analyzing). It's negligible for WAV (~40ms reading, ~200ms analyzing). Unless it's resampled, then it's (~5000ms reading, ~200ms analyzing).
Reading fewer larger chunks or not doesn't impact speed in a noticeable way.
Does SWS loudness measurement really need to be done post-resampling to the project's sample rate?
Last edited by cfillion; 03-17-2024 at 03:27 AM.
|
|
|
03-17-2024, 06:53 AM
|
#11
|
Human being with feelings
Join Date: Oct 2007
Location: home is where the heart is
Posts: 12,096
|
Quote:
Originally Posted by cfillion
Does SWS loudness measurement really need to be done post-resampling to the project's sample rate?
|
Hm good question.
I'm not as deep into the loudness stuff as I used to so I wouldn't know ad hoc.
Personally though I'd treat the ReaScript loudness functions as factually deprecated now with the native alternative.
(I looked once into deprecating them officially but didn't do in the end for a reason that eludes me currently lol. Maybe I have the started branch still on my dev machine, will check.)
|
|
|
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 01:37 PM.
|