View Single Post
Old 02-24-2017, 07:02 PM   #1
eugen2777
Human being with feelings
 
eugen2777's Avatar
 
Join Date: Aug 2012
Posts: 271
Default Lua: New Function - GetMediaItemTake_Peaks

We are now able to use this?
It definitely will not be changed?
=============
Example:
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
  ------------------
  local 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()
__________________
ReaScripts

Last edited by eugen2777; 11-08-2017 at 10:12 AM.
eugen2777 is offline   Reply With Quote