-----DEBUG CONTROL-------------------------------------------------------------- debug_output = true -- true/false --display debug messages in the console -----DISPLAY CONSOLE MESSAGE---------------------------------------------------- -- Display a message in the console for debugging, message can be a number variable -- or a string but not mixed. No line feed character is added. function Msg(value) --returns nothing if debug_output then --check if flag is set true (at the start of this script) reaper.ShowConsoleMsg(tostring(value).."\n") end end -- NoIndex: true --[[ Lokasenna_GUI example - Getting user input before running an action; i.e. replacing GetUserInputs ]]-- --[[ -------------------------------- --REATRAK LOCAL GUI LIBRARY start -------------------------------- local info = debug.getinfo(1,'S'); script_path = info.source:match[[^@?(.*[\/])[^\/]-$]] --Msg("script_path "..script_path) --[[ local lib_path = script_path --reaper.GetExtState("Lokasenna_GUI", "lib_path_v2") --]] --if not lib_path or lib_path == "" then --reaper.MB("Couldn't load the ReaTrak Lokasenna_GUI library. Please check Scripts/ReaTrak/ReaTrak_Classes/", "Whoops!", 0) --return --end --[[ loadfile(script_path .. "ReaTrak_Core.lua")() GUI.req(script_path .. "ReaTrak_Classes/Class - Label.lua")() GUI.req(script_path .. "ReaTrak_Classes/Class - Knob.lua")() GUI.req(script_path .. "ReaTrak_Classes/Class - Tabs.lua")() GUI.req(script_path .. "ReaTrak_Classes/Class - Slider.lua")() GUI.req(script_path .. "ReaTrak_Classes/Class - Button.lua")() GUI.req(script_path .. "ReaTrak_Classes/Class - Menubox.lua")() GUI.req(script_path .. "ReaTrak_Classes/Class - Textbox.lua")() GUI.req(script_path .. "ReaTrak_Classes/Class - Frame.lua")() GUI.req(script_path .. "ReaTrak_Classes/Class - Options.lua")() GUI.req(script_path .. "ReaTrak_Classes/Class - Window.lua")() -------------------------------- --REATRAK LOCAL GUI LIBRARY end -------------------------------- --]] -------------------------------- --LOKASENNA GUI LIBRARY start -------------------------------- -- NoIndex: true --[[ Lokasenna_GUI example - Getting user input before running an action; i.e. replacing GetUserInputs ]]-- -- The Core library must be loaded prior to anything else --reaper.MB("Using Lokasenna_GUI library", "Notice", 0) local lib_path = reaper.GetExtState("Lokasenna_GUI", "lib_path_v2") if not lib_path or lib_path == "" then reaper.MB("Couldn't load the Lokasenna_GUI library. Please run 'Script: Set Lokasenna_GUI v2 library path.lua' in your Action List.", "Whoops!", 0) return end loadfile(lib_path .. "Core.lua")() GUI.req("Classes/Class - Label.lua")() GUI.req("Classes/Class - Knob.lua")() GUI.req("Classes/Class - Tabs.lua")() GUI.req("Classes/Class - Slider.lua")() GUI.req("Classes/Class - Button.lua")() GUI.req("Classes/Class - Menubox.lua")() GUI.req("Classes/Class - Textbox.lua")() GUI.req("Classes/Class - Frame.lua")() GUI.req("Classes/Class - Options.lua")() GUI.req("Classes/Class - Window.lua")() -------------------------------- --LOKASENNA GUI LIBRARY end -------------------------------- -- If any of the requested libraries weren't found, abort the script nicely. if missing_lib then return 0 end -- Button Colors = {r, g, b, transparency} GUI.colors["count_in"] = {255, 124, 192, 255} GUI.colors["intro_post_fill"] = {119, 17, 174, 255} GUI.colors["intro"] = {159, 22, 232, 255} GUI.colors["intro_fill"] = {183, 128, 237, 255} GUI.colors["verse_post_fill"] = {17, 39, 174, 255} GUI.colors["verse"] = {55, 118, 235, 255} GUI.colors["verse_fill"] = {113, 190, 241, 255} GUI.colors["verse_ending"] = {151, 208, 245, 255} GUI.colors["bridge_post_fill"] = {206, 105, 20, 255} GUI.colors["bridge"] = {234, 133, 48, 255} GUI.colors["bridge_fill"] = {239, 164, 100, 255} GUI.colors["pre_chorus_post_fill"] = {206, 179, 20, 255} GUI.colors["pre_chorus"] = {234, 208, 48, 255} GUI.colors["pre_chorus_fill"] = {244, 231, 151, 255} GUI.colors["chorus_post_fill"] = {11, 116, 39, 255} GUI.colors["chorus"] = {17, 174, 59, 255} GUI.colors["chorus_fill"] = {80, 237, 123, 255} GUI.colors["chorus_ending"] = {158, 254, 182, 255} GUI.colors["play_anywhere"] = {228, 26, 39, 250} GUI.colors["drum_riff"] = {115, 23, 17, 255} GUI.colors["hold"] = {191, 191, 191, 255} GUI.colors["shot"] = {127, 127, 127, 255} GUI.colors["rest"] = {0, 0, 0, 255} --Text Colors GUI.colors["btn_txt1"] = {255, 255, 255, 255} --white GUI.colors["btn_txt2"] = {155, 155, 155, 255} --gray GUI.colors["btn_txt3"] = {0, 0, 0, 255} --black ------------------------------------ -------- Functions ---------------- ------------------------------------ function print(value) reaper.ShowConsoleMsg(tostring(value) .. "\n") end function round(val, decimal) local exp = decimal and 10^decimal or 1 return math.ceil(val * exp - 0.5) / exp end -- convert hex to floating point routine ---------------------------------------- tab={["0"]="0000",["1"]="0001",["2"]="0010",["3"]="0011", ["4"]="0100",["5"]="0101",["6"]="0110",["7"]="0111", ["8"]="1000",["9"]="1001",["a"]="1010",["b"]="1011", ["c"]="1100",["d"]="1101",["e"]="1110",["f"]="1111", ["A"]="1010",["B"]="1011",["C"]="1100",["D"]="1101",["E"]="1110",["F"]="1111"} function hexToFloat(str) local str1="" local a,z for z=1,string.len(str) do a=string.sub(str,z,z) str1=str1..tab[a] end local pm=string.sub(str1,1,1) local exp=string.sub(str1,2,9) local c=tonumber(exp,2)-127 local p=2^c local man="1"..string.sub(str1,10,32) local x=0 for z=1,string.len(man) do if string.sub(man,z,z)=="1" then x=x+p end p=p/2 end if pm=="1" then x= -x end return(x) end function get_acid() --main routine --------------------------------------------------------------------------------------------- sel_item = reaper.GetSelectedMediaItem( 0, 0 ) if sel_item then item_take = reaper.GetMediaItemTake( sel_item, 0 ) take_type = reaper.TakeIsMIDI( item_take ) if take_type then goto skip end end if sel_item and not take_type then source = reaper.GetMediaItemTake_Source( item_take ) filename = reaper.GetMediaSourceFileName(source, "") item_pitch = reaper.GetMediaItemTakeInfo_Value( item_take, "D_PITCH" ) item_start = reaper.GetMediaItemInfo_Value( sel_item, "D_POSITION" ) count_markers_regions, num_markers, num_regions = reaper.CountProjectMarkers(0) retval, num_markers, num_regionsOut = reaper.CountProjectMarkers(0) time = reaper.GetCursorPosition() --if name == "" then name = "X" end name = "" markeridx, regionidx = reaper.GetLastMarkerAndCurRegion(0, item_start) --print("Region "..regionidx) retval, isrgn, pos, rgnend, name, markrgnindexnumber, color = reaper.EnumProjectMarkers3(0, regionidx) --print("Region "..name) --if (pos == item_start or pos > item_start) and item_start < rgnend then --print(name) --end if not string.match( name, "@.*") then --goto skip end -- skip region marked @ ignore region_root, chordtype = string.match(name, "(%w[#b]?)(.*)$") if not region_root then region_root = "none" end --print("Chord root "..region_root) if string.match(name, "/C") then region_root = "C" end if string.match(name, "/C#") then region_root = "C#" end if string.match(name, "/Db") then region_root = "C#" end if string.match(name, "/D") then region_root = "D" end if string.match(name, "/D#") then region_root = "D#" end if string.match(name, "/Eb") then region_root = "D#" end if string.match(name, "/E") then region_root = "E" end if string.match(name, "/F") then region_root = "F" end if string.match(name, "/F#") then region_root = "F#" end if string.match(name, "/Gb") then region_root = "F#" end if string.match(name, "/G") then region_root = "G" end if string.match(name, "/G#") then region_root = "G#" end if string.match(name, "/Ab") then region_root = "G#" end if string.match(name, "/A") then region_root = "A" end if string.match(name, "/A#") then region_root = "A#" end if string.match(name, "/Bb") then region_root = "A#" end if string.match(name, "/B") then region_root = "B" end end local f = assert(io.open(filename, "rb")) local byte_count = f:seek("end") --print("file has ", byte_count, " bytes") i = 1 while true do f:seek("set", byte_count - i) read_byte4 = f:read(1) current_byte = string.format("%02X",string.byte(read_byte4)) --print(current_byte) if current_byte == "64" then --get next byte f:seek("set", byte_count - i -1) read_byte3 = f:read(1) current_byte = string.format("%02X",string.byte(read_byte3)) if current_byte == "69" then --get next byte f:seek("set", byte_count - i - 2) read_byte2 = f:read(1) current_byte = string.format("%02X",string.byte(read_byte2)) if current_byte == "63" then --get next byte f:seek("set", byte_count - i - 3) read_byte1 = f:read(1) current_byte = string.format("%02X",string.byte(read_byte1)) if current_byte == "61" then break end end end end i = i +1 --if i >= byte_count - 5 then fail = true break end --print("File has not been ACIDized, no 'acid' signature found") fail = true break end if i > 1000 then break end --goto finish end end if not fail then data_start = byte_count - i + 1 --print("data starts at byte ", data_start) --read data bytes ------------------------- f:seek("set", data_start) chunk_length4 = f:read(1) chunk_length3 = f:read(1) chunk_length2 = f:read(1) chunk_length1 = f:read(1) current_data = string.format("%02X",string.byte(chunk_length1))..string.format("%02X",string.byte(chunk_length2))..string.format("%02X",string.byte(chunk_length3))..string.format("%02X",string.byte(chunk_length4)) --print("ACID info chunk length (4 Bytes)= ".. current_data) --print("ACID info chunk length (decimal)= ".. tonumber(current_data, 16)) ----------------------------------- file_type4 = string.byte(f:read(1)) file_type3 = string.byte(f:read(1)) file_type2 = string.byte(f:read(1)) file_type1 = string.byte(f:read(1)) current_data = string.format("%02X", file_type1)..string.format("%02X", file_type2)..string.format("%02X", file_type3)..string.format("%02X", file_type4) --print("file type (4 Bytes)= ", current_data) --[[ if (string.byte(file_type4) & 0x01)~= 0 then print("\t\t\tOne shot") else print("\t\t\tLoop") end if (string.byte(file_type4) & 0x02)~= 0 then print("\t\t\tRoot note is set") else print("\t\t\tNo root note") end if (string.byte(file_type4) & 0x04)~= 0 then print("\t\t\tStretch is on") else print("\t\t\tStretch is off") end if (string.byte(file_type4) & 0x08)~= 0 then print("\t\t\tDisk based") else print("\t\t\tRAM based") end if (string.byte(file_type4) & 0x10)~= 0 then print("\t\t\tbit 4 set") else print("\t\t\tbit 4 off") end if (string.byte(file_type4) & 0x20)~= 0 then print("\t\t\tbit 5 set") else print("\t\t\tbit 5 off") end if (string.byte(file_type4) & 0x40)~= 0 then print("\t\t\tbit 6 set") else print("\t\t\tbit 6 off") end if (string.byte(file_type4) & 0x80)~= 0 then print("\t\t\tbit 7 set") else print("\t\t\tbit 7 off") end ---------------------- --]] root_note2 = f:read(1) root_note1 = f:read(1) current_data = string.format("%02X",string.byte(root_note1))..string.format("%02X",string.byte(root_note2)) --print("root note (2 Bytes)= ".. current_data) notes = { "C#-1","D-1","D#-1","E-1","F-1","F#-1","G-1","G#-1","A-1","A#-1","B-1", "C0","C#0","D0","D#0","E0","F0","F#0","G0","G#0","A0","A#0","B0", "C1","C#1","D1","D#1","E1","F1","F#1","G1","G#1","A1","A#1","B1", "C2","C#2","D2","D#2","E2","F2","F#2","G2","G#2","A2","A#2","B2", "C3","C#3","D3","D#3","E3","F3","F#3","G3","G#3","A3","A#3","B3", "C4","C#4","D4","D#4","E4","F4","F#4","G4","G#4","A4","A#4","B4", "C5","C#5","D5","D#5","E5","F5","F#5","G5","G#5","A5","A#5","B5", "C6","C#6","D6","D#6","E6","F6","F#6","G6","G#6","A6","A#6","B6", "C7","C#7","D7","D#7","E7","F7","F#7","G7","G#7","A7","A#7","B7", "C8","C#8","D8","D#8","E8","F8","F#8","G8","G#8","A8","A#8","B8", "C9","C#9","D9","D#9","E9","F9","F#9","G9","G#9","A9","A#9","B9", "C10","C#10","D10","D#10","E10","F10","F#10","G10","G#10","A10","A#10","B10"} --print("Root note is:\t\t".. notes[tonumber(current_data, 16)]) pitch_note = { "C","C#","D","D#","E","F","F#","G","G#","A","A#","B", "C","C#","D","D#","E","F","F#","G","G#","A","A#","B", "C","C#","D","D#","E","F","F#","G","G#","A","A#","B"} acid_root = 1 if notes[tonumber(current_data, 16)] then acid_root = notes[tonumber(current_data, 16)] octave = acid_root:gsub('%D','') acid_root = acid_root:gsub(octave,"") --print("Chord "..acid_root) --[[ if(acid_root:match("%W+")) then --if it contain alpha number = acid_root:match("%d+") alpha = acid_root:match("%W+") print("number "..number) print("Alpha "..alpha) end --]] else acid_root= "none" end ------------------------- always_8000_2 = f:read(1) always_8000_1 = f:read(1) current_data = string.format("%02X",string.byte(always_8000_1))..string.format("%02X",string.byte(always_8000_2)) --print("always 8000 (2 Bytes)= ".. current_data) ---------------------- always_0_4 = f:read(1) always_0_3 = f:read(1) always_0_2 = f:read(1) always_0_1 = f:read(1) current_data = string.format("%02X",string.byte(always_0_1))..string.format("%02X",string.byte(always_0_2))..string.format("%02X",string.byte(always_0_3))..string.format("%02X",string.byte(always_0_4)) --print("always 00000000 (4 Bytes)= ".. current_data) ---------------------- num_beats4 = f:read(1) num_beats3 = f:read(1) num_beats2 = f:read(1) num_beats1 = f:read(1) current_data = string.format("%02X",string.byte(num_beats1))..string.format("%02X",string.byte(num_beats2))..string.format("%02X",string.byte(num_beats3))..string.format("%02X",string.byte(num_beats4)) --print("number of beats (4 Bytes)= ".. current_data) acid_beats = current_data ---------------------- meter_den2 = f:read(1) meter_den1 = f:read(1) current_data = string.format("%02X",string.byte(meter_den1))..string.format("%02X",string.byte(meter_den2)) --print("meter_denominator = (2 Bytes)".. current_data) acid_denom = current_data ---------------------- meter_num2 = f:read(1) meter_num1 = f:read(1) current_data = string.format("%02X",string.byte(meter_num1))..string.format("%02X",string.byte(meter_num2)) --print("meter_numerator = (2 Bytes)".. current_data) acid_numer = current_data --------------------- --unknown = f:read(2) --current_data = string.format("%04X",string.byte(unknown)) --print("unknown = ", current_data) ------------------ tempo4 = f:read(1) tempo3 = f:read(1) tempo2 = f:read(1) tempo1 = f:read(1) current_data = string.format("%02X",string.byte(tempo1))..string.format("%02X",string.byte(tempo2))..string.format("%02X",string.byte(tempo3))..string.format("%02X",string.byte(tempo4)) --print("tempo (4 Bytes)= ".. current_data) --print("tempo decimal = ".. hexToFloat(current_data)) acis_tempo = hexToFloat(current_data) end assert(f:close()) --::finish:: --if not acid_root then acid_root = "" end if fail then acid_root = "" end for i = 1, 36 do if acid_root == pitch_note[i] then acid_new_pitch = i + item_pitch acid_root_pitch = i end end -- print("acid_new_pitch " ..acid_new_pitch) if acid_new_pitch then acid_new_pitch = math.floor(acid_new_pitch) else acid_new_pitch = 1 end --print("floor "..acid_new_pitch) for i = 1, 12 do if region_root == pitch_note[i] then --print("Reg ".. region_root .." ".. i) region_root_pitch = i end end --if region_root_pitch > acid_new_pitch then acid_new_pitch = acid_new_pitch -12 end if region_root_pitch then if region_root_pitch < acid_new_pitch then acid_new_pitch = acid_new_pitch -12 end end --if acid_new_pitch > 12 then acid_new_pitch = acid_new_pitch - 12 end --if acid_new_pitch < 12 then acid_new_pitch = acid_new_pitch + 12 end --if acid_new_pitch == 0 then acid_new_pitch = acid_new_pitch +12 end --print("Acid Pitch New ".. acid_new_pitch) new_pitch = pitch_note[acid_new_pitch] if not new_pitch then new_pitch = "none" end GUI.elms.acid_root_label:ondelete() GUI.New("acid_root_label", "Label", 1, 170, 50, acid_root , true, 1) GUI.elms.acid_root_label:init() GUI.elms.item_pitch_label:ondelete() GUI.New("item_pitch_label", "Label", 1, 100, 80, item_pitch , true, 1) GUI.elms.item_pitch_label:init() GUI.elms.item_note_label:ondelete() GUI.New("item_note_label", "Label", 1, 170, 80, new_pitch , true, 1) GUI.elms.item_note_label:init() GUI.elms.region_root_label:ondelete() GUI.New("region_root_label", "Label", 1, 170, 110, region_root , true, 1) GUI.elms.region_root_label:init() end ::skip:: end function btn_pitch_up() new_pitch = item_pitch +1 reaper.SetMediaItemTakeInfo_Value( item_take, "D_PITCH", new_pitch ) reaper.UpdateTimeline() reaper.UpdateArrange() end function btn_pitch_down() new_pitch = item_pitch -1 reaper.SetMediaItemTakeInfo_Value( item_take, "D_PITCH", new_pitch ) reaper.UpdateTimeline() reaper.UpdateArrange() end function btn_set_up_to_chord() for i = 1, 12 do if acid_root == pitch_note[i] then --print("Acid ".. acid_root .." ".. i) acid_new_pitch = i end end for i = 1, 12 do if region_root == pitch_note[i] then --print("Reg ".. region_root .." ".. i) region_root_pitch = i end end if region_root_pitch < acid_new_pitch then new_pitch = (region_root_pitch + 12) - acid_new_pitch else new_pitch = region_root_pitch - acid_new_pitch end --if new_pitch > 12 then new_pitch = new_pitch - 12 end reaper.SetMediaItemTakeInfo_Value( item_take, "D_PITCH", new_pitch ) reaper.UpdateTimeline() reaper.UpdateArrange() end function btn_set_down_to_chord() for i = 1, 12 do if acid_root == pitch_note[i] then --print("Acid ".. acid_root .." ".. i) acid_new_pitch = i end end for i = 1, 12 do if region_root == pitch_note[i] then region_root_pitch = i end end if region_root_pitch < acid_new_pitch then new_pitch = (region_root_pitch - 12) - acid_new_pitch else new_pitch = region_root_pitch - acid_new_pitch -12 end if new_pitch < -12 then new_pitch = new_pitch +12 end reaper.SetMediaItemTakeInfo_Value( item_take, "D_PITCH", new_pitch ) reaper.UpdateTimeline() reaper.UpdateArrange() end function btn_set_pitch_to_acid() reaper.SetMediaItemTakeInfo_Value( item_take, "D_PITCH", 0 ) reaper.UpdateTimeline() reaper.UpdateArrange() end function btn_split() reaper.Main_OnCommand( 40186, 0 ) end GUI.func = get_acid -- GUI.func will run on every loop -- Use this to set the poll time in seconds: GUI.freq = .5 -- .05 ------------------------------------ -------- Window settings ----------- ------------------------------------ GUI.name = "Set ACID Items" GUI.x, GUI.y, GUI.w, GUI.h = 0, 0, 400, 200 GUI.anchor, GUI.corner = "mouse", "C" ------------------------------------ -------- GUI Elements -------------- ------------------------------------ --[[ Button z, x, y, w, h, caption, func[, ...] Checklist z, x, y, w, h, caption, opts[, dir, pad] Menubox z, x, y, w, h, caption, opts, pad, noarrow] Slider z, x, y, w, caption, min, max, defaults[, inc, dir] ]]-- --GUI.New("mnu_mode", "Menubox", 1, 64, 32, 72, 20, "Mode:", "Auto,Punch,Step") --GUI.New("chk_opts", "Checklist", 1, 192, 32, 192, 96, "Options", "Only in time selection,Only on selected track,Glue items when finished", "v", 4) --GUI.New("sldr_thresh", "Slider", 1, 32, 96, 128, "Threshold", -60, 0, 48, nil, "h") GUI.New("btn_set_up_to_chord", "Button", 1, 270, 100, 114, 24, "Set Up to Chord", btn_set_up_to_chord) GUI.elms.btn_set_up_to_chord.col_txt = "btn_txt1" GUI.elms.btn_set_up_to_chord.col_fill = "chorus" GUI.elms.btn_set_up_to_chord.font = 3 GUI.New("btn_set_down_to_chord", "Button", 1, 270, 130, 114, 24, "Set Down to Chord", btn_set_down_to_chord) GUI.elms.btn_set_down_to_chord.col_txt = "btn_txt1" GUI.elms.btn_set_down_to_chord.col_fill = "chorus" GUI.elms.btn_set_down_to_chord.font = 3 GUI.New("btn_split", "Button", 1, 60, 152, 84, 24, "Split Item", btn_split) GUI.elms.btn_split.col_txt = "btn_txt1" GUI.elms.btn_split.col_fill = "play_anywhere" GUI.elms.btn_split.font = 3 GUI.New("btn_set_pitch_to_acid", "Button", 1, 160, 152, 104, 24, "Set Pitch to Acid", btn_set_pitch_to_acid) GUI.elms.btn_set_pitch_to_acid.col_txt = "btn_txt1" GUI.elms.btn_set_pitch_to_acid.col_fill = "verse" GUI.elms.btn_set_pitch_to_acid.font = 3 GUI.New("set_pitch_label", "Label", 1, 10, 10, "Set Pitch" , true, 1) GUI.New("btn_pitch_up", "Button", 1, 120, 10, 30, 15, "+", btn_pitch_up) GUI.elms.btn_pitch_up.col_txt = "btn_txt1" GUI.elms.btn_pitch_up.col_fill = "bridge" GUI.elms.btn_pitch_up.font = 2 GUI.New("btn_pitch_down", "Button", 1, 120, 30, 30, 15, "-", btn_pitch_down) GUI.elms.btn_pitch_down.col_txt = "btn_txt1" GUI.elms.btn_pitch_down.col_fill = "bridge" GUI.elms.btn_pitch_down.font = 1 --[[ GUI.New("Button1", "Button", { z = 1, x = 120, y = 148, w = 48, h = 24, caption = "Dyn 1", font = 1, col_txt = "txt", col_fill = "bridge", func = Button_Pressed_1 }) --]] --GUI.New("my_txt", "Textbox", 1, 50, 130, 120, 20, "Text:", 4) --GUI.Val("my_txt") --Returns the contents of the textbox. --GUI.Val("my_txt", "Hello, world!") --Sets the contents of the textbox. GUI.New("acid_label", "Label", 1, 10, 50, "Acid Root", true, 1) GUI.New("acid_root_label", "Label", 1, 170, 50, " ", true, 1) GUI.New("pitch_label", "Label", 1, 10, 80, "Pitch", true, 1) GUI.New("item_pitch_label", "Label", 1, 100, 80, "" , true, 1) GUI.New("item_note_label", "Label", 1, 170, 80, "" , true, 1) GUI.New("chord_label", "Label", 1, 10, 110, "Region Root", true, 1) GUI.New("region_root_label", "Label", 1, 170, 110, " ", true, 1) GUI.Init() GUI.Main()