reaper-oss / sws

The SWS extension is a collection of features that seamlessly integrate into REAPER, the Digital Audio Workstation (DAW) software by Cockos, Inc
https://www.sws-extension.org/
MIT License
448 stars 85 forks source link

FR: Normalize Items To XXX Short Term LUFS #852

Closed JustinPerkinsMKE closed 7 years ago

JustinPerkinsMKE commented 7 years ago

I currently use the "Normalize item(s) to Peak RMS" action but it would also be nice to see an action that can normalize each selected item to have the same short-term peak LUFS value.

The goal here is to get a group of items to have the same loudness in their loudest sections, and for the user to be able to define what that loudness is, either -23 LUFS or -19 LUFS etc. The defined setting should be a background setting that can be changed and then when the action runs, it conforms to that loudness. I think that's how the Normalize item(s) to Peak RMS currently works.

Right now I think you can only normalize by LUFS based on the entire item reading but this doesn't always make sense to the ear, so I think way to normalize items by their short-term peak LUFS would help get them all to the same loudness in a way that makes sense to your ear.

Thanks for considering.

nofishonfriday commented 7 years ago

Also possible now via script with added ReaScript loudness functions in v2.9.6.

JustinPerkinsMKE commented 7 years ago

@nofishonfriday Thanks. I'll have to take a look and see if I can replace this with my current action that lets me normalize items to a specific RMS level, such as -20RMS for example.

Will this let you choose any LUFS level and normalize to the max short term LUFS level you choose?

nofishonfriday commented 7 years ago

With an appropriate script, yes.

JustinPerkinsMKE commented 7 years ago

@nofishonfriday Should I ask in the ReaScript slack or public forum if somebody can make an action that normalizes selected items to XXX Max Short Term LUFS?

I took a look and it wasn't obvious to me on how to do this one.

nofishonfriday commented 7 years ago

First time I heard about ReaScript slack (I goggled for it just now), so can't really suggest anything, sorry.

But to get started, this would be a basic version of normalizing sel. items to a LUFS max short term target. I say basic, because

To test, licecap where I first run this script (normalizing to -23 LUFS max short term) than check with BR Loudness.

https://i.imgur.com/RSxkY6W.gifv

------------------------------------------------------
--- user area ----------------------------------------
------------------------------------------------------

LUFSshortTermMaxTarget = -23

------------------------------------------------------
--- user area end ------------------------------------
------------------------------------------------------

 reaper.ClearConsole()

function msg(m)
  return reaper.ShowConsoleMsg(tostring(m) .. "\n")
end

-- from Justin
function DB2VAL(x)
  return math.exp(x*0.11512925464970228420089957273422)
end

function main()

  reaper.PreventUIRefresh(1)
  reaper.Undo_BeginBlock() -- Begining of the undo block. Leave it at the top of your main function.

  selected_items_count = reaper.CountSelectedMediaItems(0)
  for i = 0, selected_items_count-1  do
    -- GET ITEMS
    item = reaper.GetSelectedMediaItem(0, i) -- Get selected item i

    take = reaper.GetActiveTake(item) -- Get the active take
    if take ~= nil then -- if ==, it will work on "empty"/text items only
      success, lufsIntegrated, range, truePeak, truePeakPos, shortTermMax, momentaryMax = reaper.NF_AnalyzeTakeLoudness(take, false)
      -- msg("short term max:" .. shortTermMax)

      deltaVol = LUFSshortTermMaxTarget - shortTermMax

      reaper.SetMediaItemTakeInfo_Value(take, "D_VOL", (DB2VAL(deltaVol)))

    end -- ENDIF active take
  end -- ENDLOOP through selected items

  reaper.Undo_EndBlock("Normalize sel. items to XXX max short term", -1)
end

main()

reaper.PreventUIRefresh(-1)
JustinPerkinsMKE commented 7 years ago

@nofishonfriday Thanks. I might not have time today or tomorrow but I'll test this soon but if I can replace it with my current normalize to peak RMS that would be great.

I need to play around and see what my preferred Max Short Term LUFS normalization would be. I assume it's easy to change the LUFS value?

I think the items would also be at 0 to start, so no concern there.

nofishonfriday commented 7 years ago

Btw, for more refined loudness scripts you could try to ask X-Raym from the Reaper forum. It was him who requested the ReaScript Loudness functions, so assume he plans to do some scripts with it.

nofishonfriday commented 7 years ago

"I assume it's easy to change the LUFS value?"

Yes, for now this can be set in the script directly by editing in "User area" -> LUFSshortTermMaxTarget directly. (of course more 'fancy' ways would also be possible, like doing it via a user prompt pop up, but as said, this is just a very basic 'demo' version)

JustinPerkinsMKE commented 7 years ago

OK, thanks. I would be happy to make a handsome donation if a script can be made that brings up a simple box where you can set the Max Short Term LUFS normalization and then apply it.

This way I can work it into my Custom Action and replace the RMS normalize with this.

Do you think it's possible?

nofishonfriday commented 7 years ago

Yep, give me a day or two. :)

JustinPerkinsMKE commented 7 years ago

@nofishonfriday Sounds good. I'm tied up the next two days anyways but I look forward to trying it out when it's ready.

Much appreciated.

nofishonfriday commented 7 years ago

A version for testing is now available via ReaPack: nofish_Normalize loudness of selected items active take to X LUFS max short term.lua

There's a switch to turn on / off console info output in the user config area at the beginning of the script. I've left it on currently to see what's going on.

Let me know how it goes. :)

JustinPerkinsMKE commented 7 years ago

@nofishonfriday Thanks! I'm totally away from my studio today but I can try this tomorrow.

Looking forward to it.

JustinPerkinsMKE commented 7 years ago

@nofishonfriday Excuse my dumbness, but I can't find this. I've synchronized ReaPack in REAPER and searched everywhere.

Can you point me to it or help me find it?

Thanks

nofishonfriday commented 7 years ago

Not your fault, sorry. I've had trouble with ReaPack so I temporarily removed it. Should be back up now, synchronize the packages and you should (hopefully) see it.

nofishonfriday commented 7 years ago

Ok, sorry again. I did a small update and couldn't get to update ReaPack. But now the correct version is up. You should see version 1.01 available now on ReaPack.

JustinPerkinsMKE commented 7 years ago

Thanks. I'm gone again for the evening but I'll try it out late tonight or tomorrow.

Much appreciated.

JustinPerkinsMKE commented 7 years ago

Hmm. I synchronized the packages and I'm still not seeing it. Do I have to do anything special to get your scripts to be part of ReaPack or should it automatically find it?

JustinPerkinsMKE commented 7 years ago

@nofishonfriday OK, I got it installed now. It seems great but is there a way it can be like the RMS normalize where we set the X LUFS value in a separate window that is remembered, but then when the script is run as part of a larger custom action, items are normalized to that Max Short Term LUFS?

Basically, I need this to be part of a big custom action so I need to define the LUFS level separately like the SWS RMS normalize feature, so that when it runs, it just normalizes to that value.

Does that make sense?

nofishonfriday commented 7 years ago

Ok, I get what you mean.

I think I'd split it in two scripts then, one just to set the LUFS target value (which will be persistent across projects) and the actual normalizing script then takes this target value and runs without asking for the target value again.

This should do, right ?

JustinPerkinsMKE commented 7 years ago

@nofishonfriday Right! I think that is how the SWS RMS normalize works. One script/window just sets the RMS target level remembered across all projects, and another does the action to selected items.

That should work well.

This is because I want the main action to happen as part of a big custom action and not be asked each time about the LUFS level.

Thanks!

nofishonfriday commented 7 years ago

In future I should read more properly. :D You already mention "The defined setting should be a background setting..." in the opening post so showing the prompt each time the script is run is a bad design choice of course.

Anyway, the new versions are up in ReaPack. You can ditch the old script completely (for your purpose), the two relevant new ones are:

nofish_Set normalize loudness to X LUFS max short term target vaulue.lua and nofish_Normalize loudness of selected items active take to X LUFS max short term - no prompt.lua

First run the first one to set the target value, then run the second which then uses this persistent target value for normalizing (you can check in the console output to what it's been normalized etc., as said, console output can also be turned off in the script directly if wanted)

Let me know how it works....

nofishonfriday commented 7 years ago

edit: Doh, hold on please, stupid typo:

nofish_Set normalize loudness to X LUFS max short term target vaulue.lua

Let me fix this first, sorry, I'll get back when the new version is up.

JustinPerkinsMKE commented 7 years ago

@nofishonfriday Thanks!

Let me know if you have a way to make a donation for this.

nofishonfriday commented 7 years ago

Ok, typo corrected version is up now, ready to test.

About donation, thanks a lot for the offer, I can give you my Paypal adress, but first I'd prefer you testing and confirming everything works as it should. :D

JustinPerkinsMKE commented 7 years ago

@nofishonfriday OK. It may take a few days to really run it though it's paces, especially with my unusual schedule at the moment but initially it seems AWESOME.

Can you walk me through turning off the Console Output pop up that tells me what has been done?

JustinPerkinsMKE commented 7 years ago

@nofishonfriday Actually, I managed to find where I turn true into false.

That may seem like nothing to you but for me it's a big step in coding :)

nofishonfriday commented 7 years ago

Haha, good. :)

Take your time with testing, I'm not in a hurry...

JustinPerkinsMKE commented 7 years ago

@nofishonfriday I think it's going to be fine but I'll test a few scenarios. With the SWS RMS normalize, sometimes I'd get one of a dozen items that normalizes to an INSANE level for no reason.

Tim recently fixed it so that's good.

It's just hard to know if anything like that will pop up until I try it for a bit.

Will it always have to be that the item/take gain must stat at 0dB for it to work? Or was that just a thing with the testing build?

nofishonfriday commented 7 years ago

Will it always have to be that the item/take gain must stat at 0dB for it to work? Or was that just a thing with the testing build?

Should be fine now also with values other than 0dB.

JustinPerkinsMKE commented 7 years ago

@nofishonfriday Great, thanks! Mostly I run this right away when the item/takes are still all set to 0, but now and then I might need to run it on files that have been already tweaked.

I was just curious if there was a definitive answer.

nofishonfriday commented 7 years ago

Closing this (in agreement with OP) as it's now available via script in ReaPack.