|
|
|
11-11-2018, 03:53 PM
|
#1
|
Human being with feelings
Join Date: Apr 2013
Location: France
Posts: 9,875
|
Bug: GetMediaItemTake_Peaks samples of item with inverted phase are shuffled by pair?
Hi,
I just found a weird behavior with the GetMediaItemTake_Peaks function, not sure if it is the code snippet or the function, but I think it is the function.
It seems that if the item is Phase inverted, the samples aren't return in the right order.
Instead of returning samples 1 - 2 -3 - 4, it returns 2 - 1 - 3 - 4. The val are correct (a 0.5 sample become 0.5, and vice versa), but the order is wrong.
Here is a demo:
Ahd here sample code
Code:
min_freq = 80
max_freq = 1000
Thresh_dB = -40
min_tonal = 0.85
------------------------------------------------------------
function Init()
-- Some gfx Wnd Default Values ---------------
local Wnd_bgd = 0x0F0F0F
local Wnd_Title = "Test"
local Wnd_Dock,Wnd_X,Wnd_Y = 0,100,320
Wnd_W,Wnd_H = 1044,490 -- global values(used for define zoom level)
-- Init window ------
gfx.clear = Wnd_bgd
gfx.init( Wnd_Title, Wnd_W,Wnd_H, Wnd_Dock, Wnd_X,Wnd_Y )
end
------------------------------------------------------------
function Peaks_Draw(Peaks)
local min_note = 69 + 12 * math.log(min_freq/440, 2)
local max_note = 69 + 12 * math.log(max_freq/440, 2)
local Thresh = 10 ^ (Thresh_dB/20)
----------------------
local axis = gfx.h * 0.5
local Ky = gfx.h * 0.5
local Kn = gfx.h/(max_note-min_note)
local offs = min_note * Kn
----------------------
local abs, max = math.abs, math.max
for i = 1, #Peaks, 4 do
local max_peak, min_peak = Peaks[i], Peaks[i+1]
local xx = i/4
gfx.set(0,0.5,0,1)
gfx.line(xx , axis - max_peak*Ky, xx, axis - min_peak*Ky, true) -- Peaks
--------------------
if max(abs(max_peak), abs(min_peak)) > Thresh then
local freq, tonal = Peaks[i+2], Peaks[i+3]
local note = 69 + 12 * math.log(freq/440, 2)
if tonal >= min_tonal and note >= min_note and note <= max_note then
gfx.x = xx; gfx.y = gfx.h + offs - note*Kn;
gfx.setpixel(1,0,0)
elseif note < min_note then
gfx.x = xx; gfx.y = gfx.h - 10;
gfx.setpixel(0,0,1)
elseif note > max_note then
gfx.x = xx; gfx.y = 10;
gfx.setpixel(0,1,1)
end
end
end
end
------------------------------------------------------------
function Item_GetPeaks(item)
if not item then return end
local take = reaper.GetActiveTake(item)
if not take or reaper.TakeIsMIDI(take) then return end
local item_start = reaper.GetMediaItemInfo_Value(item, "D_POSITION")
local item_len = reaper.GetMediaItemInfo_Value(item, "D_LENGTH")
local sel_start, sel_end = reaper.GetSet_LoopTimeRange(false, false, 0, 0, false)
if sel_end - sel_start == 0 then sel_start = item_start; sel_end = item_start + item_len end
local starttime = math.max(sel_start, item_start)
local len = math.min(sel_end, item_start + item_len) - starttime
if len <= 0 then return end
------------------
--PCM_Source = reaper.GetMediaItemTake_Source(take)
local n_chans = 1 -- I GetPeaks Only from 1 channel!!!
local peakrate = gfx.w / len
local n_spls = math.floor(len*peakrate + 0.5) -- its Peak Samples
local want_extra_type = 115 -- 's' char
local buf = reaper.new_array(n_spls * n_chans * 3) -- max, min, spectral each chan(but now 1 chan only)
buf.clear() -- Clear buffer
------------------
local retval = reaper.GetMediaItemTake_Peaks(take, peakrate, starttime, n_chans, n_spls, want_extra_type, buf);
local spl_cnt = (retval & 0xfffff) -- sample_count
local ext_type = (retval & 0x1000000)>>24 -- extra_type was available
local out_mode = (retval & 0xf00000)>>20 -- output_mode
------------------
Peaks = {}
if spl_cnt > 0 and ext_type > 0 then
for i = 1, n_spls do
local p = #Peaks
Peaks[p+1] = buf[i] -- max peak
Peaks[p+2] = buf[n_spls + i] -- min peak
--------------
local spectral = buf[n_spls*2 + i] -- spectral peak
-- freq and tonality from spectral peak --
Peaks[p+3] = spectral&0x7fff -- low 15 bits frequency
Peaks[p+4] = (spectral>>15)/16384 -- tonality norm value
end
end
------------------
return Peaks
end
---------------------------
function Project_IsChanged()
local cur_cnt = reaper.GetProjectStateChangeCount(0)
if cur_cnt ~= proj_change_cnt then proj_change_cnt = cur_cnt
return true
end
end
---------------------------
function main()
if Project_IsChanged() then
gfx.setimgdim(0, 0, 0) -- clear buf 0
gfx.setimgdim(0, gfx.w, gfx.h)
gfx.dest = 0; -- set dest buf = 0
local item = reaper.GetSelectedMediaItem(0, 0)
if item then
local Peaks = Item_GetPeaks(item)
if Peaks then Peaks_Draw(Peaks) end
end
end
-----------
local img_w, img_h = gfx.getimgdim(0)
if img_w > 0 and img_h > 0 then
gfx.a = 1; gfx.dest = -1; gfx.x, gfx.y = 0, 0
gfx.blit(image, 1, 0, 0, 0, img_w, img_h, 0, 0, gfx.w, gfx.h)
end
-----------
char = gfx.getchar()
if char == 32 then reaper.Main_OnCommand(40044, 0) end -- play
if char ~= -1 then reaper.defer(main) end -- defer
-----------
gfx.update()
-----------
end
Init()
main()
Note: it is great eugen2777 code, the only difference is the Peaks variable is global (to allow debug)
To replicate: test it on a item long enough (so that you have different sample value for each point in the array), and toggle the item phase: sample order will shuffled two by two.
Thanks for your expertise !
|
|
|
11-14-2018, 11:58 PM
|
#2
|
Human being with feelings
Join Date: Apr 2013
Location: France
Posts: 9,875
|
Notes : in my screenshot, array entries 3-4 7-8 etx dont changd cause they are not samples so when I say samples 1-2 3-4 it is entries 1-2 5-6 etc...
Entries which change should be a their opposite value.
|
|
|
06-14-2019, 05:03 AM
|
#3
|
Human being with feelings
Join Date: Feb 2019
Location: Southern Vermont
Posts: 864
|
Thanks much for posting this sample!
I essentially used it as a poor-man's "tutorial" for frequency detection capabilities regarding a script I'm currently working on ( https://forum.cockos.com/showthread.php?t=221862).
Love,
Dafark
|
|
|
06-14-2019, 06:42 AM
|
#4
|
Administrator
Join Date: Jan 2005
Location: NYC
Posts: 15,721
|
from the code:
Code:
Peaks[p+1] = buf[i] -- max peak
Peaks[p+2] = buf[n_spls + i] -- min peak
It shows the maximum and minimum values, so when the sign flips, the ordering of those two values flip (.12 max, 0.0 min -- flip, becomes 0.0 max, -.12 min). and
Code:
Peaks[p+3] = spectral&0x7fff -- low 15 bits frequency
Peaks[p+4] = (spectral>>15)/16384 -- tonality norm value
The next two entries are the spectral info...
|
|
|
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 07:04 AM.
|