Old 07-07-2020, 01:15 PM   #1
jkooks
Human being with feelings
 
Join Date: May 2020
Posts: 190
Default Help: How do you use GetMediaItemTake_Peaks?

Hey everyone,

I have been trying to use the GetMediaItemTake_Peaks API function to get the max peak value for every n frames in the active take, but I am having a hard time figuring out what to pass it in order to get this to work.

First off, what exactly is the peakrate parameter? Is it "every n number of samples return the max and min" or is it "get the max and min samples every n length in time"?

Additionally, does the GetMediaItemTake_Peaks function account for various take properties (i.e. volume envelopes, item volume, play rates, etc) so it returns different values than if I used the source_peaks function? I haven't been able to find too much clear info on this function, so I am still trying to wrap my head around some of the specifics of it in order to figure out what I need to run for my script.

Thanks!

Last edited by jkooks; 07-08-2020 at 03:31 PM.
jkooks is offline   Reply With Quote
Old 07-07-2020, 03:57 PM   #2
jkooks
Human being with feelings
 
Join Date: May 2020
Posts: 190
Default

Also, I am having issues with it getting the same sample values over and over. Seems like the function is looping through a portion of the clip for all of the samples instead of going through the entire clip. I found something by Lokasenna that says you have to go through the samples in chunks, so only a portion of the clip at a time, but the script I saw uses a static value of 66536 to determine the sample number and I am not sure why.

Any help is appreciated!

Last edited by jkooks; 07-07-2020 at 06:32 PM.
jkooks is offline   Reply With Quote
Old 07-08-2020, 03:28 PM   #3
jkooks
Human being with feelings
 
Join Date: May 2020
Posts: 190
Default

For anyone interested in following this saga, I am now having an issue getting the position for each sampling. I put my code below but I am quite bad at math, so I wouldn't be surprised if there is a simple error I am making when determining the size of each sample group that is messing the whole thing up, or if there is just an infinitely easier way to do what I am trying to accomplish.

Code:
thisItem = reaper.GetSelectedMediaItem(0, 0)
thisTake = reaper.GetActiveTake(thisItem)

thisSource = reaper.GetMediaItemTake_Source(thisTake)
samplerate = reaper.GetMediaSourceSampleRate(thisSource)
chanNum = reaper.GetMediaSourceNumChannels(thisSource)

frameRate = reaper.TimeMap_curFrameRate(0)
frameRate = string.format("%0.2f", frameRate) --cuts off at hundredths mark

thisPos = reaper.GetMediaItemInfo_Value(thisItem, "D_POSITION")
thisLen = reaper.GetMediaItemInfo_Value(thisItem, "D_LENGTH")


local playrate = reaper.GetMediaItemTakeInfo_Value(thisTake, "D_PLAYRATE")
if playrate ~= 1 then
    reaper.SetMediaItemTakeInfo_Value(thisTake, "D_PLAYRATE", 1)
    reaper.SetMediaItemInfo_Value(thisItem, "D_LENGTH", thisLen * playrate)
end




--block size seems to be half of the amount
amount = 4 --every n frames

pkrate = (samplerate / frameRate) * amount --the amount of samples it checks for every peak return
sampleNum = math.floor((thisLen*frameRate) / amount) --the total number of samples that will be returned

secondsPerBlock = 1 --how many seconds I want each block to be

blockSize = math.floor((frameRate / amount) * secondsPerBlock) --amount of samples per block
blockNum = math.floor(sampleNum/blockSize) --figures out how many blocks consist of the entire sample size
extraBlock = sampleNum - (blockSize*blockNum) --extra samples since the last block most likely won't be full

sampleIncrement = thisLen / sampleNum --the start position for every peak return
posIncrement = sampleIncrement * blockSize --the increment for where it should start to sample the next block


buf = reaper.new_array((blockSize * chanNum) * 2) --has to be 2x the sampleNum --max and min, don't need spectral - probably don't need min either.

sampleStartTime = thisPos

highestSample = 0
highestPos = 0

local GetSamples = reaper.GetMediaItemTake_Peaks
local samplePos --position where every sample population starts
local sampleCount = 1 --count of how many samples have been returned

peaks = {}

--runs through each block to get the sample size
for i = 0, blockNum do

	buf.clear()

	if i == blockNum then blockSize = extraBlock end

	retval = GetSamples(thisTake, pkrate, sampleStartTime, chanNum, blockSize, 0, buf)

	samplePos = sampleStartTime

	--runs through every returned peak to record the min, max and peak/sample start position
	for j = 1, blockSize do
		local count = #peaks

		peaks[count+1] = buf[j] --max peak
		peaks[count+2] = buf[blockSize + j] --min peak
		peaks[count+3] = samplePos --start of where these samples were located


		-- reaper.AddProjectMarker(0, false, samplePos, 0, "Sample " .. sampleCount, 0)

		--records the overall highest sample and where they are (relatively) located
		if peaks[count+1] > highestSample then
			highestSample = peaks[count+1]
			highestPos = peaks[count+3]
		end

		samplePos = samplePos + sampleIncrement --increments the samples' position
		sampleCount = sampleCount + 1 --increments the sample count
	end

	-- reaper.AddProjectMarker(0, false, sampleStartTime, 0, "Block " .. i, 0)

	sampleStartTime = sampleStartTime + posIncrement --increments the block's position
end

-- reaper.AddProjectMarker(0, false, samplePos, 0, "END OF SAMPLES", 0)

reaper.SetEditCurPos(highestPos, false, false) --sets the edit cursor at teh start of the sample that has the highest peak

if playrate ~= 1 then     
	reaper.SetMediaItemTakeInfo_Value(thisTake, "D_PLAYRATE", playrate)
    reaper.SetMediaItemInfo_Value(thisItem, "D_LENGTH", item_len)
end


reaper.UpdateTimeline()
jkooks is offline   Reply With Quote
Old 07-09-2020, 02:35 AM   #4
Thonex
Human being with feelings
 
Join Date: May 2018
Location: Los Angeles
Posts: 1,719
Default

hi jkooks,

Here is a script I wrote to give the the peaks of a bunch of items. It's much faster than using audio buffers. It borrows heavily from functions by SPK77.

If you write the code to split the item into equal intervals, that will surely do it.

Code:
function Msg (param)
  reaper.ShowConsoleMsg(tostring (param).."\n")
end

------------------------------------------------------------
-- Mod from SPK77
-- http://forum.cockos.com/showpost.php?p=1608719&postcount=6
--Trak_Vol_dB = 20*math.log(val, 10) end
--Trak Vol val = 10^(dB_val/20) end
------------------------------------------------------------


-------------------------------------------------------------
-- item Vol conversion    https://forum.cockos.com/showthread.php?p=2200278#post2200278
-----------------------------------------------------------
local LN10_OVER_TWENTY = 0.11512925464970228420089957273422
function DB2VAL(x) return math.exp(x*LN10_OVER_TWENTY) end

function VAL2DB(x)
  if x < 0.0000000298023223876953125 then
    return -150
  else
    return math.max(-150, math.log(x)* 8.6858896380650365530225783783321); 
  end
end

function Max_Peak_FAST ()
  reaper.ClearConsole()
  reaper.PreventUIRefresh(1)
  reaper.Undo_BeginBlock()
  
  local Max_Level = 0 -- keep track of max volume of items vertically
  local Cur_Item = 0
  local Num_Items =  reaper.CountSelectedMediaItems( 0 )
  local item_id = {}
  local item_orig_vol = {}
  if Num_Items == 0 then 
      reaper.ShowMessageBox("No items selected", "Alert", 0 )
  end
  
  -- log selected items and orig vols
  for i = 0, Num_Items - 1 do
      item_id [i] =  reaper.GetSelectedMediaItem( 0, i )
      take =  reaper.GetMediaItemTake( item_id[i],0 )
      item_orig_vol [i] = reaper.GetMediaItemTakeInfo_Value( take, "D_VOL" )
  end
  
  reaper.Main_OnCommand(40108,0) -- Normalize items
  
  -- log selected items new vols (how much they were increased by)
    for i = 0, Num_Items - 1 do
        --item_id [i] =  reaper.GetSelectedMediaItem( 0, i )
        take =  reaper.GetMediaItemTake( item_id[i],0 )
        new_vol = reaper.GetMediaItemTakeInfo_Value( take, "D_VOL" )
        retval, take_name = reaper.GetSetMediaItemTakeInfo_String( take, "P_NAME", "", 0 )
        Msg(take_name .. "\t\t".. 0 - string.format("%.2f",VAL2DB(new_vol)))
        reaper.SetMediaItemInfo_Value(item_id [i], "D_VOL",item_orig_vol [i] )
    end
  --reaper.Main_OnCommand(41923,0)-- Item: Reset items volume to +0dB
  reaper.Main_OnCommand(reaper.NamedCommandLookup("_XENAKIOS_RESETTAKEVOL"),0)--Xenakios/SWS: Reset active take volume to 0.0 dB

  reaper.PreventUIRefresh(-1) 
  reaper.Undo_EndBlock("Verify Max Peak (FAST)",-1)  
end  

Max_Peak_FAST ()
Cheers,

Andrew K
__________________
Cheers... Andrew K
Reaper v6.80+dev0621 - June 21 2023 • Catalina • Mac Mini 2020 6 core i7 • 64GB RAM • OS: Catalina • 4K monitor • RME RayDAT card with Sync Card and extended Light Pipe.
Thonex is offline   Reply With Quote
Old 07-09-2020, 11:05 AM   #5
jkooks
Human being with feelings
 
Join Date: May 2020
Posts: 190
Default

Thank you Andrew, I will definitely check that out! I'm still interested in just figuring out how to use the GetMediaItemTake_Peaks function for curiosity's sake now, but something tells me I will end up going the same route you did too.

Thanks again!
jkooks is offline   Reply With Quote
Old 08-22-2021, 11:52 AM   #6
Buy One
Human being with feelings
 
Buy One's Avatar
 
Join Date: Sep 2019
Posts: 1,134
Default

Quote:
Originally Posted by amagalma
Question: What exactly is peakrate in GetMediaItemTake_Peaks( take, peakrate, starttime, numchannels, numsamplesperchannel, want_extra_type, buf )? And how would I know what value to set? Thanks!
Asked by amagalma on March 8 2021, 12:12pm
Quote:
Originally Posted by Justin
Number of pixels per second!
Quote:
Originally Posted by amagalma
Thanks! So, are we supposed to pass GetHZoomLevel() there?
Quote:
Originally Posted by Justin
Yes, or if you're rendering at a different zoom level, that...
https://askjf.com/index.php?q=5660s
__________________
https://github.com/Buy-One/REAPER-scripts (175)
REAPER is a DAW whose user guide file is larger than its installation file
Buy One is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 03:39 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.