diff --git a/README.md b/README.md index e87182b..8af6407 100755 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ a sample playground for norns ### hard requirements: -- norns (210114 or later) +- norns (210301 or later) ### encouraged (any or all): diff --git a/cheat_codes_2.lua b/cheat_codes_2.lua index f5d578d..308c9d0 100755 --- a/cheat_codes_2.lua +++ b/cheat_codes_2.lua @@ -1,6 +1,6 @@ -- cheat codes 2 -- a sample playground --- rev: 210227 +-- rev: 210303 -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- need help? -- please visit: @@ -12,6 +12,12 @@ if util.file_exists(_path.code.."passthrough") then passthru.init() end +function developer_mode() + params:set("rec_loop_1",2) + params:set("one_shot_clock_div",4) + params:set("one_shot_threshold",70) +end + if util.file_exists(_path.code.."namesizer") then Namesizer = include 'namesizer/lib/namesizer' end @@ -65,6 +71,7 @@ mc = include 'lib/midicheat' sharer = include 'lib/sharer' macros = include 'lib/macros' transport = include 'lib/transport' +speed_dial = include 'lib/speed_dial' math.randomseed(os.time()) variable_fade_time = 0.01 splash_done = true @@ -844,6 +851,21 @@ zilch_leds = function init() + amp_in = {} + local amp_src = {"amp_in_l","amp_in_r"} + for i = 1,2 do + amp_in[i] = poll.set(amp_src[i]) + amp_in[i].time = 0.01 + amp_in[i].callback = function(val) + if val > params:get("one_shot_threshold")/10000 then + if rec[rec.focus].state == 0 then + toggle_buffer(rec.focus) + end + amp_in[i]:stop() + end + end + end + sharer.setup("cheat_codes_2") clock.run(check_page_for_k1) @@ -885,6 +907,7 @@ function init() rec[i].clear = 1 rec[i].rate_offset = 1.0 rec[i].waveform_samples = {} + rec[i].queued = false end params:add_group("GRID",5) @@ -1168,14 +1191,22 @@ function init() page.loops_sel = 1 page.loops_page = 0 page.loops_view = {4,1,1,1} - page.levels_sel = 0 + page.levels = {} + page.levels.sel = 0 + -- page.levels_sel = 0 + page.pans = {} + page.pans.sel = 1 page.panning_sel = 1 - page.filtering_sel = 0 + page.filters = {} + page.filters.sel = 0 + -- page.filtering_sel = 0 page.arc_sel = 0 page.delay_sel = 0 - page.delay_section = 1 - page.delay_focus = 1 + -- page.delay_section = 1 + -- page.delay_focus = 1 page.delay = {{},{}} + page.delay.section = 1 + page.delay.focus = 1 for i = 1,2 do page.delay[i].menu = 1 page.delay[i].menu_sel = {1,1,1} @@ -1891,6 +1922,8 @@ function init() -- named_loadstate("/home/we/dust/data/cheat_codes_2/names/DEFAULT.cc2") end + speed_dial:init() + end --- @@ -2272,6 +2305,7 @@ function cancel_one_shot_rec_clock() end function one_shot_clock() + rec[rec.focus].queued = true if rec[rec.focus].state == 1 and rec_state_watcher.is_running then rec_state_watcher:stop() end @@ -2281,18 +2315,27 @@ function one_shot_clock() clock.sync(rate) end -- softcut.loop_start(1,rec[rec.focus].start_point-0.05) - softcut.pre_level(1,params:get("live_rec_feedback_"..rec.focus)) - softcut.loop_start(1,rec[rec.focus].start_point-(params:get("one_shot_latency_offset"))) - softcut.loop_end(1,rec[rec.focus].end_point-0.01) - softcut.position(1,rec[rec.focus].start_point-((params:get("one_shot_latency_offset")-0.01))) -- TODO CLARIFY IF THIS IS REAL ANYMORE + if params:string("one_shot_clock_div") ~= "threshold" then + softcut.loop_start(1,rec[rec.focus].start_point-(params:get("one_shot_latency_offset"))) + else + softcut.loop_start(1,rec[rec.focus].start_point+params:get("one_shot_latency_offset")) + end + if params:string("one_shot_clock_div") ~= "threshold" then + softcut.position(1,rec[rec.focus].start_point-((params:get("one_shot_latency_offset")-0.01))) -- TODO CLARIFY IF THIS IS REAL ANYMORE + else + softcut.position(1,rec[rec.focus].start_point+params:get("one_shot_latency_offset")) -- TODO CLARIFY IF THIS IS REAL ANYMORE + end + softcut.loop_end(1,rec[rec.focus].end_point) -- softcut.position(1,rec[rec.focus].start_point+0.01) - rec.play_segment = rec.focus + softcut.pre_level(1,params:get("live_rec_feedback_"..rec.focus)) softcut.rec_level(1,1) + rec.play_segment = rec.focus rec[rec.focus].state = 1 rec.stopped = false rec_state_watcher:start() if rec[rec.focus].clear == 1 then rec[rec.focus].clear = 0 end grid_dirty = true + rec[rec.focus].queued = false end function compare_rec_resolution(x) @@ -2871,7 +2914,7 @@ function cheat(b,i) end --/ OH ALL THIS SUCKS TODO FIXME softcut.fade_time(b+1,variable_fade_time) - softcut.loop_start(b+1,pad.start_point-variable_fade_time) + softcut.loop_start(b+1,pad.start_point+variable_fade_time) softcut.loop_end(b+1,pad.end_point-variable_fade_time) softcut.buffer(b+1,pad.mode) if pad.pause == false then @@ -2886,7 +2929,7 @@ function cheat(b,i) end if pad.rate > 0 then -- softcut.position(b+1,pad.start_point+0.05) - softcut.position(b+1,pad.start_point-variable_fade_time) + softcut.position(b+1,pad.start_point+variable_fade_time) elseif pad.rate < 0 then -- softcut.position(b+1,pad.end_point-variable_fade_time-0.05) softcut.position(b+1,pad.end_point-variable_fade_time) @@ -3169,8 +3212,8 @@ function try_tilt_process(b,i,t,rq) end function buff_freeze() - softcut.recpre_slew_time(1,0.5) - softcut.level_slew_time(1,0.5) + softcut.recpre_slew_time(1,0.05) + softcut.level_slew_time(1,0.05) softcut.fade_time(1,0.01) rec[rec.focus].state = (rec[rec.focus].state + 1)%2 softcut.rec_level(1,rec[rec.focus].state) @@ -3201,11 +3244,30 @@ function buff_pause() softcut.rate(1,rec[rec.focus].pause and 0 or 1) -- TODO make this dynamic to include rec rate offsets end +function threshold_rec_handler() + if rec[rec.focus].queued then + amp_in[1]:stop() + amp_in[2]:stop() + rec[rec.focus].queued = false + elseif not rec[rec.focus].queued and rec[rec.focus].state == 0 then + amp_in[1]:start() + amp_in[2]:start() + rec[rec.focus].queued = true + for i = 1,3 do + if i~=rec.focus and rec[i].state == 1 then + softcut.rec_level(1,0) + softcut.pre_level(1,params:get("live_rec_feedback_"..i)) + end + end + elseif not rec[rec.focus].queued and rec[rec.focus].state == 1 then + rec[rec.focus].end_point = poll_position_new[1] + update_waveform(1,key1_hold and rec[rec.focus].start_point or live[rec.focus].min,key1_hold and rec[rec.focus].end_point or live[rec.focus].max,128) + end +end + function toggle_buffer(i,untrue_alt) grid_dirty = true - softcut.level_slew_time(1,0.5) - softcut.fade_time(1,0.01) local old_clip = rec.focus @@ -3216,23 +3278,31 @@ function toggle_buffer(i,untrue_alt) end rec.focus = i - - if rec[rec.focus].loop == 0 and not grid_alt then - if rec[rec.focus].state == 0 then - run_one_shot_rec_clock() -- this runs only if not recording - elseif rec[rec.focus].state == 1 and rec_state_watcher.is_running then -- can have both conditions, right? - cancel_one_shot_rec_clock() - end - elseif rec[rec.focus].loop == 0 and (grid_alt and untrue_alt ~= nil) then - -- buff_flush() - elseif rec[rec.focus].loop == 1 and not grid_alt then - if one_shot_rec_clock ~= nil then - cancel_one_shot_rec_clock() + + if rec[rec.focus].loop == 0 and params:string("one_shot_clock_div") == "threshold" and rec[rec.focus].queued then + softcut.level_slew_time(1,0) + softcut.fade_time(1,0) + one_shot_clock() + else + softcut.level_slew_time(1,0.05) + softcut.fade_time(1,0.01) + if rec[rec.focus].loop == 0 and not grid_alt then + if rec[rec.focus].state == 0 then + run_one_shot_rec_clock() -- this runs only if not recording + elseif rec[rec.focus].state == 1 and rec_state_watcher.is_running then -- can have both conditions, right? + cancel_one_shot_rec_clock() + end + elseif rec[rec.focus].loop == 0 and (grid_alt and untrue_alt ~= nil) then + -- buff_flush() + elseif rec[rec.focus].loop == 1 and not grid_alt then + if one_shot_rec_clock ~= nil then + cancel_one_shot_rec_clock() + end + softcut.loop_start(1,rec[rec.focus].start_point) + softcut.loop_end(1,rec[rec.focus].end_point-0.01) end end - softcut.loop_start(1,rec[rec.focus].start_point) - softcut.loop_end(1,rec[rec.focus].end_point-0.01) rec.play_segment = rec.focus softcut.loop(1,rec[rec.focus].loop) if rec.stopped == true then @@ -3248,8 +3318,10 @@ function toggle_buffer(i,untrue_alt) rec[rec.focus].clear = 0 end end + -- end grid_dirty = true update_waveform(1,key1_hold and rec[rec.focus].start_point or live[rec.focus].min,key1_hold and rec[rec.focus].end_point or live[rec.focus].max,128) + -- update_waveform(1,live[rec.focus].min,live[rec.focus].max,128) end function update_delays() @@ -3351,7 +3423,7 @@ function adjust_key1_timing() elseif menu ~= 6 then if metro[31].time ~= 0.1 then metro[31].time = 0.1 end elseif menu == 6 then - if page.delay[page.delay_focus].menu == 1 and page.delay[page.delay_focus].menu_sel[page.delay[page.delay_focus].menu] == 5 then + if page.delay[page.delay.focus].menu == 1 and page.delay[page.delay.focus].menu_sel[page.delay[page.delay.focus].menu] == 5 then metro[31].time = 0.01 else if metro[31].time ~= 0.1 then metro[31].time = 0.1 end @@ -3428,7 +3500,7 @@ function key(n,z) menu = page.main_sel + 1 end elseif menu == 2 then - local id = page.loops_sel + -- local id = page.loops_sel if key2_hold then if page.loops.sel < 4 then local id = page.loops.sel @@ -3445,14 +3517,30 @@ function key(n,z) end end elseif page.loops.sel == 4 then - toggle_buffer(rec.focus) + if rec[rec.focus].loop == 0 and params:string("one_shot_clock_div") == "threshold" and not grid_alt then + threshold_rec_handler() + else + toggle_buffer(rec.focus) + end elseif page.loops.sel == 5 then if page.loops.meta_sel < 4 then for i = 1,16 do rightangleslice.start_end_default(bank[page.loops.meta_sel][i]) end elseif page.loops.meta_sel == 4 then - toggle_buffer(rec.focus) + if rec[rec.focus].loop == 0 and params:string("one_shot_clock_div") == "threshold" and not grid_alt then + if rec[rec.focus].queued then + amp_in[1]:stop() + amp_in[2]:stop() + rec[rec.focus].queued = false + else + amp_in[1]:start() + amp_in[2]:start() + rec[rec.focus].queued = true + end + else + toggle_buffer(rec.focus) + end end end grid_dirty = true @@ -3511,35 +3599,35 @@ function key(n,z) end end elseif menu == 3 then - local level_nav = (page.levels_sel + 1)%4 - page.levels_sel = level_nav + local level_nav = (page.levels.sel + 1)%4 + page.levels.sel = level_nav elseif menu == 5 then - local filter_nav = (page.filtering_sel + 1)%4 - page.filtering_sel = filter_nav + local filter_nav = (page.filters.sel + 1)%4 + page.filters.sel = filter_nav elseif menu == 6 then - if page.delay_section == 2 then + if page.delay.section == 2 then if key1_hold then - local k = page.delay[page.delay_focus].menu - local v = page.delay[page.delay_focus].menu_sel[page.delay[page.delay_focus].menu] + local k = page.delay[page.delay.focus].menu + local v = page.delay[page.delay.focus].menu_sel[page.delay[page.delay.focus].menu] del.links(del.lookup_prm(k,v)) if k == 1 and v == 5 then - delay[page.delay_focus == 1 and 2 or 1].feedback_mute = not delay[page.delay_focus == 1 and 2 or 1].feedback_mute + delay[page.delay.focus == 1 and 2 or 1].feedback_mute = not delay[page.delay.focus == 1 and 2 or 1].feedback_mute elseif k == 1 and v == 4 then - delay[page.delay_focus == 1 and 2 or 1].reverse = delay[page.delay_focus].reverse + delay[page.delay.focus == 1 and 2 or 1].reverse = delay[page.delay.focus].reverse end if delay_links[del.lookup_prm(k,v)] then local sides = {"L","R"} - params:set("delay "..sides[page.delay_focus == 1 and 2 or 1]..": "..del.lookup_prm(k,v),params:get("delay "..sides[page.delay_focus]..": "..del.lookup_prm(k,v))) + params:set("delay "..sides[page.delay.focus == 1 and 2 or 1]..": "..del.lookup_prm(k,v),params:get("delay "..sides[page.delay.focus]..": "..del.lookup_prm(k,v))) grid_dirty = true end else - page.delay_section = page.delay_section == 1 and 2 or 1 + page.delay.section = page.delay.section == 1 and 2 or 1 end - elseif page.delay_section == 1 then + elseif page.delay.section == 1 then if key1_hold then - del.link_all(page.delay[page.delay_focus].menu) + del.link_all(page.delay[page.delay.focus].menu) else - page.delay_section = page.delay_section == 1 and 2 or 1 + page.delay.section = page.delay.section == 1 and 2 or 1 end end elseif menu == 7 then @@ -3759,10 +3847,10 @@ function key(n,z) end elseif menu == 6 then if key1_hold then - if page.delay[page.delay_focus].menu_sel[page.delay[page.delay_focus].menu] == 4 then - local k = page.delay[page.delay_focus].menu - local v = page.delay[page.delay_focus].menu_sel[page.delay[page.delay_focus].menu] - del.quick_action(page.delay_focus, "reverse") + if page.delay[page.delay.focus].menu_sel[page.delay[page.delay.focus].menu] == 4 then + local k = page.delay[page.delay.focus].menu + local v = page.delay[page.delay.focus].menu_sel[page.delay[page.delay.focus].menu] + del.quick_action(page.delay.focus, "reverse") end else menu = 1 @@ -3779,7 +3867,7 @@ function key(n,z) else menu = 1 end - if menu == 6 and page.delay[page.delay_focus].menu == 1 and page.delay[page.delay_focus].menu_sel[page.delay[page.delay_focus].menu] == 4 then + if menu == 6 and page.delay[page.delay.focus].menu == 1 and page.delay[page.delay.focus].menu_sel[page.delay[page.delay.focus].menu] == 4 then -- just need a logic break elseif menu ~= 2 and menu ~= 8 then if key1_hold == true then key1_hold = false end @@ -3795,12 +3883,12 @@ function key(n,z) end elseif menu == 6 then key1_hold = true - if page.delay[page.delay_focus].menu == 1 and page.delay[page.delay_focus].menu_sel[page.delay[page.delay_focus].menu] == 5 then + if page.delay[page.delay.focus].menu == 1 and page.delay[page.delay.focus].menu_sel[page.delay[page.delay.focus].menu] == 5 then if delay_links["feedback"] then del.quick_action(1,"feedback_mute",z) del.quick_action(2,"feedback_mute",z) else - del.quick_action(page.delay_focus,"feedback_mute",z) + del.quick_action(page.delay.focus,"feedback_mute",z) end grid_dirty = true end @@ -3872,12 +3960,12 @@ function key(n,z) key1_hold = false end if menu == 6 then - if page.delay[page.delay_focus].menu == 1 and page.delay[page.delay_focus].menu_sel[page.delay[page.delay_focus].menu] == 5 then + if page.delay[page.delay.focus].menu == 1 and page.delay[page.delay.focus].menu_sel[page.delay[page.delay.focus].menu] == 5 then if delay_links["feedback"] then del.quick_action(1,"feedback_mute",z) del.quick_action(2,"feedback_mute",z) else - del.quick_action(page.delay_focus,"feedback_mute",z) + del.quick_action(page.delay.focus,"feedback_mute",z) end grid_dirty = true end @@ -4359,9 +4447,9 @@ function grid_redraw() end if rec[rec.focus].clear == 0 then - g:led(16,8-rec.focus,rec[rec.focus].state == 1 and led_maps["live_rec"][edition] or led_maps["live_pause"][edition]) + g:led(16,8-rec.focus,rec[rec.focus].state == 1 and led_maps["live_rec"][edition] or (rec[rec.focus].queued and 15 or led_maps["live_pause"][edition])) elseif rec[rec.focus].clear == 1 then - g:led(16,8-rec.focus,led_maps["live_empty"][edition]) + g:led(16,8-rec.focus,rec[rec.focus].queued and 9 or led_maps["live_empty"][edition]) end elseif grid_page == 1 then @@ -4811,9 +4899,9 @@ function grid_redraw() -- Live buffers if rec[rec.focus].clear == 0 then - g:led(rec.focus,2,rec[rec.focus].state == 1 and led_maps["live_rec"][edition] or led_maps["live_pause"][edition]) + g:led(rec.focus,2,rec[rec.focus].state == 1 and led_maps["live_rec"][edition] or (rec[rec.focus].queued and 15 or led_maps["live_pause"][edition])) elseif rec[rec.focus].clear == 1 then - g:led(rec.focus,2,led_maps["live_empty"][edition]) + g:led(rec.focus,2,rec[rec.focus].queued and 9 or led_maps["live_empty"][edition]) end elseif grid_page_64 == 1 then diff --git a/lib/arp_actions.lua b/lib/arp_actions.lua index e83ccc8..e5a3ba7 100755 --- a/lib/arp_actions.lua +++ b/lib/arp_actions.lua @@ -224,6 +224,9 @@ function arp_actions.clear(target) arp[target].notes = {} arp[target].start_point = 1 arp[target].end_point = 1 + clock.cancel(arp_clock[target]) + arp_clock[target] = nil + arp_clock[target] = clock.run(arp_actions.arpeggiate,target) end function arp_actions.savestate() diff --git a/lib/encoder_actions.lua b/lib/encoder_actions.lua index b7f8d13..86464e0 100755 --- a/lib/encoder_actions.lua +++ b/lib/encoder_actions.lua @@ -122,7 +122,7 @@ function encoder_actions.init(n,d) end end elseif menu == 6 then - page.delay_focus = util.clamp(page.delay_focus+d,1,2) + page.delay.focus = util.clamp(page.delay.focus+d,1,2) elseif menu == 7 then page.time_sel = util.clamp(page.time_sel+d,1,6) elseif menu == 8 then @@ -276,12 +276,12 @@ function encoder_actions.init(n,d) elseif menu == 6 then - if page.delay_section == 1 then - page.delay[page.delay_focus].menu = util.clamp(page.delay[page.delay_focus].menu+d,1,3) - elseif page.delay_section == 2 then + if page.delay.section == 1 then + page.delay[page.delay.focus].menu = util.clamp(page.delay[page.delay.focus].menu+d,1,3) + elseif page.delay.section == 2 then local max_items = {5,6,7} - local target = page.delay[page.delay_focus].menu_sel[page.delay[page.delay_focus].menu] - page.delay[page.delay_focus].menu_sel[page.delay[page.delay_focus].menu] = util.clamp(target+d,1,max_items[page.delay[page.delay_focus].menu]) + local target = page.delay[page.delay.focus].menu_sel[page.delay[page.delay.focus].menu] + page.delay[page.delay.focus].menu_sel[page.delay[page.delay.focus].menu] = util.clamp(target+d,1,max_items[page.delay[page.delay.focus].menu]) end elseif menu == 7 then @@ -448,27 +448,27 @@ function encoder_actions.init(n,d) elseif menu == 6 then - local item = page.delay[page.delay_focus].menu_sel[page.delay[page.delay_focus].menu] - local delay_name = page.delay_focus == 1 and "L" or "R" - local focused_menu = page.delay[page.delay_focus].menu - if page.delay_section == 2 then + local item = page.delay[page.delay.focus].menu_sel[page.delay[page.delay.focus].menu] + local delay_name = page.delay.focus == 1 and "L" or "R" + local focused_menu = page.delay[page.delay.focus].menu + if page.delay.section == 2 then if focused_menu == 1 then if item == 1 then ea.delta_delay_param(delay_name,"mode",d) -- params:delta("delay "..delay_name..": mode",d) elseif item == 2 then local divisor; - if delay[page.delay_focus].mode == "free" and key1_hold then + if delay[page.delay.focus].mode == "free" and key1_hold then divisor = 3 - elseif delay[page.delay_focus].mode == "free" and not key1_hold then + elseif delay[page.delay.focus].mode == "free" and not key1_hold then divisor = 1/(100/3) else divisor = 1 end - ea.delta_delay_param(delay_name,delay[page.delay_focus].mode == "clocked" and "div/mult" or "free length",d/divisor) - -- params:delta(delay[page.delay_focus].mode == "clocked" and "delay "..delay_name..": div/mult" or "delay "..delay_name..": free length",d/divisor) + ea.delta_delay_param(delay_name,delay[page.delay.focus].mode == "clocked" and "div/mult" or "free length",d/divisor) + -- params:delta(delay[page.delay.focus].mode == "clocked" and "delay "..delay_name..": div/mult" or "delay "..delay_name..": free length",d/divisor) elseif item == 3 then - local divisor = (delay[page.delay_focus].mode == "free" and key1_hold) and 10 or 0.2 + local divisor = (delay[page.delay.focus].mode == "free" and key1_hold) and 10 or 0.2 ea.delta_delay_param(delay_name,"fade time",d/divisor) -- params:delta("delay "..delay_name..": fade time",d/divisor) elseif item == 4 then @@ -530,28 +530,28 @@ function encoder_actions.init(n,d) elseif focused_menu == 3 then if item < 7 then if item == 1 or item == 3 or item == 5 then - local k = page.delay[page.delay_focus].menu - local v = page.delay[page.delay_focus].menu_sel[page.delay[page.delay_focus].menu] + local k = page.delay[page.delay.focus].menu + local v = page.delay[page.delay.focus].menu_sel[page.delay[page.delay.focus].menu] local target = bank[util.round(item/2)] local prm = {"left_delay_level","right_delay_level"} if key1_hold then for i = 1,16 do - target[i][prm[page.delay_focus]] = util.clamp(target[i][prm[page.delay_focus]] + d/10,0,1) + target[i][prm[page.delay.focus]] = util.clamp(target[i][prm[page.delay.focus]] + d/10,0,1) if delay_links[del.lookup_prm(k,v)] then - target[i][prm[page.delay_focus == 1 and 2 or 1]] = target[i][prm[page.delay_focus]] + target[i][prm[page.delay.focus == 1 and 2 or 1]] = target[i][prm[page.delay.focus]] end end else - target[target.id][prm[page.delay_focus]] = util.clamp(target[target.id][prm[page.delay_focus]] + d/10,0,1) + target[target.id][prm[page.delay.focus]] = util.clamp(target[target.id][prm[page.delay.focus]] + d/10,0,1) if delay_links[del.lookup_prm(k,v)] then - target[target.id][prm[page.delay_focus == 1 and 2 or 1]] = target[target.id][prm[page.delay_focus]] + target[target.id][prm[page.delay.focus == 1 and 2 or 1]] = target[target.id][prm[page.delay.focus]] end end grid_dirty = true if target[target.id].enveloped == false then - softcut.level_cut_cut(util.round(item/2)+1,page.delay_focus+4,(target[target.id][prm[page.delay_focus]]*target[target.id].level)*target.global_level) + softcut.level_cut_cut(util.round(item/2)+1,page.delay.focus+4,(target[target.id][prm[page.delay.focus]]*target[target.id].level)*target.global_level) if delay_links[del.lookup_prm(k,v)] then - local this_one = page.delay_focus == 1 and 2 or 1 + local this_one = page.delay.focus == 1 and 2 or 1 softcut.level_cut_cut(util.round(item/2)+1,(this_one)+4,(target[target.id][prm[this_one]]*target[target.id].level)*target.global_level) end end @@ -559,14 +559,14 @@ function encoder_actions.init(n,d) else local target = bank[item/2] local prm = {"left_delay_thru","right_delay_thru"} - local current_thru = target[target.id][prm[page.delay_focus]] == true and 1 or 0 + local current_thru = target[target.id][prm[page.delay.focus]] == true and 1 or 0 current_thru = util.clamp(current_thru + d,0,1) if key1_hold then for i = 1,16 do - target[i][prm[page.delay_focus]] = current_thru == 1 and true or false + target[i][prm[page.delay.focus]] = current_thru == 1 and true or false end else - target[target.id][prm[page.delay_focus]] = current_thru == 1 and true or false + target[target.id][prm[page.delay.focus]] = current_thru == 1 and true or false end end elseif item == 7 then @@ -817,7 +817,7 @@ function encoder_actions.init(n,d) else focused_pad = bank[n].id end - if page.levels_sel == 0 then + if page.levels.sel == 0 then if key1_hold or grid_alt or bank[n].alt_lock then bank[n].global_level = util.clamp(bank[n].global_level+d/10,0,2) else @@ -837,93 +837,74 @@ function encoder_actions.init(n,d) softcut.level_cut_cut(n+1,6,(bank[n][bank[n].id].right_delay_level*bank[n][bank[n].id].level)*bank[n].global_level) end end - elseif page.levels_sel == 1 then - - if key1_hold or grid_alt or bank[n].alt_lock then - for j = 1,16 do - local pre_enveloped = bank[n][j].enveloped - local pre_mode = bank[n][j].envelope_mode - - bank[n][j].envelope_mode = util.clamp(bank[n][j].envelope_mode + d,0,3) - - if bank[n][j].envelope_mode == 0 then - bank[n][j].enveloped = false - else - bank[n][j].enveloped = true - if pre_enveloped ~= bank[n][j].enveloped then - cheat(n, bank[n].id) - end - end - end + elseif page.levels.sel == 1 then + local pre_enveloped = bank[n][focused_pad].enveloped + local pre_mode = bank[n][focused_pad].envelope_mode + bank[n][focused_pad].envelope_mode = util.clamp(bank[n][focused_pad].envelope_mode + d,0,3) + + if bank[n][focused_pad].envelope_mode == 0 then + bank[n][focused_pad].enveloped = false else - - local pre_enveloped = bank[n][focused_pad].enveloped - local pre_mode = bank[n][focused_pad].envelope_mode - bank[n][focused_pad].envelope_mode = util.clamp(bank[n][focused_pad].envelope_mode + d,0,3) - - if bank[n][focused_pad].envelope_mode == 0 then - bank[n][focused_pad].enveloped = false - else - bank[n][focused_pad].enveloped = true - if pre_enveloped ~= bank[n][focused_pad].enveloped then - if bank[n].focus_hold == false then - cheat(n, bank[n].id) - end - elseif pre_mode ~= bank[n][focused_pad].envelope_mode then - if bank[n].focus_hold == false then - cheat(n, bank[n].id) - end + bank[n][focused_pad].enveloped = true + if pre_enveloped ~= bank[n][focused_pad].enveloped then + if bank[n].focus_hold == false then + cheat(n, bank[n].id) + end + elseif pre_mode ~= bank[n][focused_pad].envelope_mode then + if bank[n].focus_hold == false then + cheat(n, bank[n].id) end end - end - elseif page.levels_sel == 2 then if key1_hold or grid_alt or bank[n].alt_lock then for j = 1,16 do - if bank[n][j].enveloped then - if d>0 then - bank[n][j].envelope_loop = true - else - bank[n][j].envelope_loop = false - end + if j ~= focused_pad then + bank[n][j].envelope_mode = bank[n][focused_pad].envelope_mode + bank[n][j].enveloped = bank[n][focused_pad].enveloped end end - else - if bank[n][focused_pad].enveloped then - local pre_loop = bank[n][focused_pad].envelope_loop - if d>0 then - bank[n][focused_pad].envelope_loop = true - if pre_loop ~= bank[n][focused_pad].envelope_loop then - if bank[n].focus_hold == false then - cheat(n, bank[n].id) - end + end + + elseif page.levels.sel == 2 then + if bank[n][focused_pad].enveloped then + local pre_loop = bank[n][focused_pad].envelope_loop + if d>0 then + bank[n][focused_pad].envelope_loop = true + if pre_loop ~= bank[n][focused_pad].envelope_loop then + if bank[n].focus_hold == false then + cheat(n, bank[n].id) end - else - bank[n][focused_pad].envelope_loop = false end + else + bank[n][focused_pad].envelope_loop = false end end - - elseif page.levels_sel == 3 then if key1_hold or grid_alt or bank[n].alt_lock then for j = 1,16 do - if bank[n][j].enveloped then - bank[n][j].envelope_time = util.explin(0.1,60,0.1,60,bank[n][j].envelope_time) - bank[n][j].envelope_time = util.clamp(bank[n][j].envelope_time+d/10,0.1,60) - bank[n][j].envelope_time = util.linexp(0.1,60,0.1,60,bank[n][j].envelope_time) + if j ~= focused_pad then + bank[n][j].envelope_loop = bank[n][focused_pad].envelope_loop end end - else + end + + elseif page.levels.sel == 3 then if bank[n][focused_pad].enveloped then bank[n][focused_pad].envelope_time = util.explin(0.05,60,0.05,60,bank[n][focused_pad].envelope_time) bank[n][focused_pad].envelope_time = util.clamp(bank[n][focused_pad].envelope_time+d/10,0.05,60) bank[n][focused_pad].envelope_time = util.linexp(0.05,60,0.05,60,bank[n][focused_pad].envelope_time) end - end + if key1_hold or grid_alt or bank[n].alt_lock then + for j = 1,16 do + if j ~= focused_pad then + if bank[n][j].enveloped then + bank[n][j].envelope_time = bank[n][focused_pad].envelope_time + end + end + end + end if bank[n][focused_pad].level > 0.05 then - -- if bank[n][focused_pad].envelope_time/(bank[n][focused_pad].level/0.05) ~= inf then env_counter[n].time = (bank[n][focused_pad].envelope_time/(bank[n][focused_pad].level/0.05)) end end @@ -944,7 +925,7 @@ function encoder_actions.init(n,d) end softcut.pan(n+1, bank[n][bank[n].id].pan) elseif menu == 5 then - local filt_page = page.filtering_sel + 1 + local filt_page = page.filters.sel + 1 if filt_page == 1 then if bank[n][bank[n].id].filter_type == 4 then if key1_hold or grid_alt then @@ -1188,8 +1169,14 @@ function ea.move_rec_end(d) end if d <= 0 and util.round(rec[rec.focus].start_point,0.01) < util.round(rec[rec.focus].end_point + ((res)/lbr[params:get("live_buff_rate")]),0.01) then rec[rec.focus].end_point = util.clamp(rec[rec.focus].end_point+((res)/lbr[params:get("live_buff_rate")]),(1+(8*(rec.focus-1))),(9+(8*(rec.focus-1)))) - elseif d > 0 and rec[rec.focus].end_point+((res)/lbr[params:get("live_buff_rate")]) <= 9+(8*(rec.focus-1)) then - rec[rec.focus].end_point = util.clamp(rec[rec.focus].end_point+((res)/lbr[params:get("live_buff_rate")]),(1+(8*(rec.focus-1))),(9+(8*(rec.focus-1)))) + elseif d > 0 then + if rec[rec.focus].end_point+((res)/lbr[params:get("live_buff_rate")]) <= 9+(8*(rec.focus-1)) then -- FIXME: weak point? + rec[rec.focus].end_point = util.clamp(rec[rec.focus].end_point+((res)/lbr[params:get("live_buff_rate")]),(1+(8*(rec.focus-1))),(9+(8*(rec.focus-1)))) + else + if params:get("rec_loop_enc_resolution") < 3 then + rec[rec.focus].end_point = 9+(8*(rec.focus-1)) + end + end end if rec.play_segment == rec.focus then softcut.loop_end(1, rec[rec.focus].end_point-0.01) diff --git a/lib/grid_actions.lua b/lib/grid_actions.lua index b36f60c..fdafbdf 100755 --- a/lib/grid_actions.lua +++ b/lib/grid_actions.lua @@ -375,7 +375,11 @@ function grid_actions.init(x,y,z) if rec.focus ~= 8-y then rec.focus = 8-y else - toggle_buffer(8-y) + if rec[rec.focus].loop == 0 and params:string("one_shot_clock_div") == "threshold" and not grid_alt then + threshold_rec_handler() + elseif not grid_alt then + toggle_buffer(8-y) + end if grid_alt then buff_flush() end @@ -922,6 +926,20 @@ function grid_actions.init(x,y,z) if x <=3 and y == 1 and z ==1 then bank_64 = x b = bank[x] + if menu == 2 then + page.loops.sel = x + elseif menu == 7 then + page.time_sel = x + elseif menu == 8 then + rytm.track_edit = x + elseif menu == 9 then + page.arp_page_sel = x + elseif menu == 10 then + page.rnd_page = x + elseif menu == "MIDI_config" then + page.midi_bank = x + end + screen_dirty = true end if grid_alt or b.alt_lock then @@ -1228,7 +1246,11 @@ function grid_actions.init(x,y,z) if rec.focus ~= x then rec.focus = x else - toggle_buffer(x) + if rec[rec.focus].loop == 0 and params:string("one_shot_clock_div") == "threshold" and not grid_alt then + threshold_rec_handler() + elseif not grid_alt then + toggle_buffer(8-y) + end if grid_alt then buff_flush() end diff --git a/lib/main_menu.lua b/lib/main_menu.lua index f0c2e70..c4bcc51 100755 --- a/lib/main_menu.lua +++ b/lib/main_menu.lua @@ -120,7 +120,9 @@ function main_menu.init() local off = ((rec.focus-1)*8)+1 local mults = {1,2,4} local mult = mults[params:get("live_buff_rate")] - screen.text_right("s: "..string.format("%.4g",(util.round(rec[rec.focus].start_point,0.0001)-off)*mult).."s | e: "..string.format("%.4g",(rec[rec.focus].end_point-off)*mult).."s") + local display_live_start = string.format("%.4g",(util.round(rec[rec.focus].start_point,0.0001)-off)*mult) + local display_live_end = string.format("%.4g",(rec[rec.focus].end_point-off)*mult) + screen.text_right("s: "..display_live_start.."s | e: "..display_live_end.."s") end end @@ -372,6 +374,8 @@ function main_menu.init() screen.level(screen_levels[1]) screen.move(0,40) screen.text("L"..rec.focus) + screen.move(1,32) + screen.text(rec[rec.focus].queued and "..." or "") local waves = rec[rec.focus].waveform_samples @@ -412,6 +416,7 @@ function main_menu.init() end local rate_options = {"8s","16s","32s"} + local mode_options = {"loop","shot","shot+threshold"} local sets = { [1] = @@ -731,7 +736,7 @@ function main_menu.init() local level_markers = {"0 -", "1 -", "2 -"} screen.text(level_markers[i]) screen.move(10+(i*20),64) - screen.level(level_options[page.levels_sel+1] == "levels" and 15 or 3) + screen.level(level_options[page.levels.sel+1] == "levels" and 15 or 3) local level_to_screen_options = {"a", "b", "c"} if key1_hold or grid_alt or bank[i].alt_lock then screen.text("("..level_to_screen_options[i]..")") @@ -743,7 +748,7 @@ function main_menu.init() screen.line(35+(20*(i-1)),57-level_to_screen) screen.close() screen.stroke() - screen.level(level_options[page.levels_sel+1] == "envelope enable" and 15 or 3) + screen.level(level_options[page.levels.sel+1] == "envelope enable" and 15 or 3) screen.move(85,10) screen.text("env?") screen.move(90+((i-1)*15),20) @@ -753,7 +758,7 @@ function main_menu.init() else screen.text_center("-") end - screen.level(level_options[page.levels_sel+1] == "loop" and 15 or 3) + screen.level(level_options[page.levels.sel+1] == "loop" and 15 or 3) screen.move(90+((i-1)*15),30) if bank[i][focused_pad].envelope_loop then screen.text_center("∞") @@ -761,7 +766,7 @@ function main_menu.init() screen.text_center("-") end - screen.level(level_options[page.levels_sel+1] == "time" and 15 or 3) + screen.level(level_options[page.levels.sel+1] == "time" and 15 or 3) -- screen.move(85,30) -- screen.text("time") screen.move(85,34+((i)*10)) @@ -821,7 +826,7 @@ function main_menu.init() end screen.move(17+((i-1)*45),30) - screen.level(page.filtering_sel+1 == 1 and 15 or 3) + screen.level(page.filters.sel+1 == 1 and 15 or 3) if slew_counter[i].slewedVal ~= nil then if slew_counter[i].slewedVal >= -0.04 and slew_counter[i].slewedVal <=0.04 then screen.text_center(".....|.....") @@ -852,15 +857,15 @@ function main_menu.init() end end screen.move(17+((i-1)*45),40) - screen.level(page.filtering_sel+1 == 2 and 15 or 3) + screen.level(page.filters.sel+1 == 2 and 15 or 3) local ease_time_to_screen = bank[i][bank[i].id].tilt_ease_time screen.text_center(string.format("%.2f",ease_time_to_screen/100).."s") screen.move(17+((i-1)*45),50) - screen.level(page.filtering_sel+1 == 3 and 15 or 3) + screen.level(page.filters.sel+1 == 3 and 15 or 3) local q_scaled = util.linlin(0.0005,4,100,0,params:get("filter "..i.." q")) screen.text_center(string.format("%.4g",q_scaled).."%") screen.move(17+((i-1)*45),60) - screen.level(page.filtering_sel+1 == 4 and 15 or 3) + screen.level(page.filters.sel+1 == 4 and 15 or 3) local ease_type_to_screen = bank[i][bank[i].id].tilt_ease_type local ease_types = {"cont","jumpy"} screen.text_center(ease_types[ease_type_to_screen]) @@ -870,18 +875,18 @@ function main_menu.init() screen.move(0,10) screen.level(3) screen.text("delays") - local focused_menu = page.delay[page.delay_focus].menu + local focused_menu = page.delay[page.delay.focus].menu if key1_hold then screen.move(128,10) - if page.delay_section == 2 and focused_menu == 1 then - local focused_prm = page.delay[page.delay_focus].menu_sel[focused_menu] - if (delay[page.delay_focus].mode == "free" and focused_prm == 2) or (delay[page.delay_focus].mode == "free" and focused_prm == 3) or focused_prm == 4 then + if page.delay.section == 2 and focused_menu == 1 then + local focused_prm = page.delay[page.delay.focus].menu_sel[focused_menu] + if (delay[page.delay.focus].mode == "free" and focused_prm == 2) or (delay[page.delay.focus].mode == "free" and focused_prm == 3) or focused_prm == 4 then screen.text_right("fine-tune enabled") elseif focused_prm == 5 then screen.text_right("quick-jump!!") end - elseif page.delay_section == 2 and focused_menu == 3 then - if page.delay[page.delay_focus].menu_sel[focused_menu] < 7 then + elseif page.delay.section == 2 and focused_menu == 3 then + if page.delay[page.delay.focus].menu_sel[focused_menu] < 7 then screen.text_right("map changes to bank") end end @@ -889,19 +894,19 @@ function main_menu.init() screen.level(15) screen.font_size(40) screen.move(0,50) - screen.text(page.delay_focus == 1 and "L" or "R") + screen.text(page.delay.focus == 1 and "L" or "R") screen.move(0,60) - if page.delay_section == 2 then - local k = page.delay[page.delay_focus].menu - local v = page.delay[page.delay_focus].menu_sel[page.delay[page.delay_focus].menu] + if page.delay.section == 2 then + local k = page.delay[page.delay.focus].menu + local v = page.delay[page.delay.focus].menu_sel[page.delay[page.delay.focus].menu] if delay_links[del.lookup_prm(k,v)] then screen.font_size(8) screen.text("linked") end - elseif page.delay_section == 1 then + elseif page.delay.section == 1 then if key1_hold then screen.font_size(8) - if page.delay[page.delay_focus].menu ~= 3 then + if page.delay[page.delay.focus].menu ~= 3 then screen.move(0,60) screen.text("K3: toggle all links") else @@ -913,43 +918,43 @@ function main_menu.init() screen.font_size(8) local options = {"ctl","flt","mix"} for i = 1,3 do - screen.level((page.delay_section == 1 and focused_menu == i) and 15 or 3) + screen.level((page.delay.section == 1 and focused_menu == i) and 15 or 3) screen.move(30+(40*(i-1)),20) screen.text(options[i]) end - screen.level((page.delay_section == 1 and focused_menu == focused_menu) and 15 or 3) + screen.level((page.delay.section == 1 and focused_menu == focused_menu) and 15 or 3) screen.move(30+(40*(focused_menu-1)),23) screen.line((focused_menu == 3 and 41 or 40)+(40*(focused_menu-1)),23) screen.stroke() - local delay_name = page.delay_focus == 1 and "L" or "R" - screen.level((page.delay_section == 2 and focused_menu == focused_menu) and 15 or 3) - local selected = page.delay[page.delay_focus].menu_sel[focused_menu] + local delay_name = page.delay.focus == 1 and "L" or "R" + screen.level((page.delay.section == 2 and focused_menu == focused_menu) and 15 or 3) + local selected = page.delay[page.delay.focus].menu_sel[focused_menu] if focused_menu == 1 then - screen.level((page.delay_section == 2 and selected == 1) and 15 or 3) + screen.level((page.delay.section == 2 and selected == 1) and 15 or 3) screen.move(30,30) screen.text(params:string("delay "..delay_name..": mode")) screen.move(75,30) - screen.level((page.delay_section == 2 and selected == 2) and 15 or 3) - if delay[page.delay_focus].mode == "clocked" then - if delay[page.delay_focus].modifier ~= 1 then - screen.text(params:string("delay "..delay_name..": div/mult").."*"..string.format("%.4g",delay[page.delay_focus].modifier)) + screen.level((page.delay.section == 2 and selected == 2) and 15 or 3) + if delay[page.delay.focus].mode == "clocked" then + if delay[page.delay.focus].modifier ~= 1 then + screen.text(params:string("delay "..delay_name..": div/mult").."*"..string.format("%.4g",delay[page.delay.focus].modifier)) else screen.text(params:string("delay "..delay_name..": div/mult")) end else screen.text(string.format("%.4g",params:get("delay "..delay_name..": free length")).." sec") end - screen.level((page.delay_section == 2 and selected == 3) and 15 or 3) + screen.level((page.delay.section == 2 and selected == 3) and 15 or 3) screen.move(30,40) screen.text("fade: "..string.format("%.4g",params:get("delay "..delay_name..": fade time"))) - screen.level((page.delay_section == 2 and selected == 4) and 15 or 3) + screen.level((page.delay.section == 2 and selected == 4) and 15 or 3) screen.move(80,40) - local rev = delay[page.delay_focus].reverse == true and 1 or 0 + local rev = delay[page.delay.focus].reverse == true and 1 or 0 screen.text("rate: "..(rev == 1 and "-" or "")..string.format("%.4g",params:string("delay "..delay_name..": rate"))) - screen.level((page.delay_section == 2 and selected == 5) and 15 or 3) + screen.level((page.delay.section == 2 and selected == 5) and 15 or 3) screen.move(30,50) - if delay[page.delay_focus].feedback_mute then - if params:get(page.delay_focus == 1 and "delay L: feedback" or "delay R: feedback") == 0 then + if delay[page.delay.focus].feedback_mute then + if params:get(page.delay.focus == 1 and "delay L: feedback" or "delay R: feedback") == 0 then screen.text("feedback: 100%") else screen.text("feedback: 0%") @@ -958,24 +963,24 @@ function main_menu.init() screen.text("feedback: "..string.format("%.4g",params:get("delay "..delay_name..": feedback")).."%") end elseif focused_menu == 2 then - screen.level((page.delay_section == 2 and selected == 1) and 15 or 3) + screen.level((page.delay.section == 2 and selected == 1) and 15 or 3) screen.move(30,30) local current_freq = params:get("delay "..delay_name..": filter cut") local modified_freq = easingFunctions[params:string("delay "..delay_name..": curve")](current_freq/12000,10,11990,1) screen.text(string.format("%.6g",modified_freq).." hz") - screen.level((page.delay_section == 2 and selected == 2) and 15 or 3) + screen.level((page.delay.section == 2 and selected == 2) and 15 or 3) screen.move(85,30) screen.text("q: "..params:string("delay "..delay_name..": filter q")) - screen.level((page.delay_section == 2 and selected == 3) and 15 or 3) + screen.level((page.delay.section == 2 and selected == 3) and 15 or 3) screen.move(30,40) screen.text("LP: "..params:string("delay "..delay_name..": filter lp")) - screen.level((page.delay_section == 2 and selected == 4) and 15 or 3) + screen.level((page.delay.section == 2 and selected == 4) and 15 or 3) screen.move(85,40) screen.text("HP: "..params:string("delay "..delay_name..": filter hp")) - screen.level((page.delay_section == 2 and selected == 5) and 15 or 3) + screen.level((page.delay.section == 2 and selected == 5) and 15 or 3) screen.move(30,50) screen.text("BP: "..params:string("delay "..delay_name..": filter bp")) - screen.level((page.delay_section == 2 and selected == 6) and 15 or 3) + screen.level((page.delay.section == 2 and selected == 6) and 15 or 3) screen.move(85,50) screen.text("dry: "..params:string("delay "..delay_name..": filter dry")) elseif focused_menu == 3 then @@ -984,14 +989,14 @@ function main_menu.init() screen.level(3) screen.move(30,20+(i*10)) screen.text(bank_names[i]..""..bank[i].id) - screen.level((page.delay_section == 2 and selected == (i == 1 and 1 or (i == 2 and 3 or 5))) and 15 or 3) + screen.level((page.delay.section == 2 and selected == (i == 1 and 1 or (i == 2 and 3 or 5))) and 15 or 3) screen.move(50,20+(i*10)) - screen.text("in: "..string.format("%.1f",(page.delay_focus == 1 and bank[i][bank[i].id].left_delay_level or bank[i][bank[i].id].right_delay_level))) - screen.level((page.delay_section == 2 and selected == (i == 1 and 2 or (i == 2 and 4 or 6))) and 15 or 3) + screen.text("in: "..string.format("%.1f",(page.delay.focus == 1 and bank[i][bank[i].id].left_delay_level or bank[i][bank[i].id].right_delay_level))) + screen.level((page.delay.section == 2 and selected == (i == 1 and 2 or (i == 2 and 4 or 6))) and 15 or 3) screen.move(80,20+(i*10)) - screen.text("thru: "..(page.delay_focus == 1 and tostring(bank[i][bank[i].id].left_delay_thru) or tostring(bank[i][bank[i].id].right_delay_thru))) + screen.text("thru: "..(page.delay.focus == 1 and tostring(bank[i][bank[i].id].left_delay_thru) or tostring(bank[i][bank[i].id].right_delay_thru))) end - screen.level((page.delay_section == 2 and selected == 7) and 15 or 3) + screen.level((page.delay.section == 2 and selected == 7) and 15 or 3) screen.move(30,60) screen.text("main output level: "..string.format("%.2f", params:get("delay "..delay_name..": global level"))) end @@ -1069,7 +1074,7 @@ function main_menu.init() screen.level(time_page[page_line] == j and 15 or 3) screen.move(10,40+(10*(j-1))) screen.text(p_options[j]) - local mode_options = {"loose","distro "..string.format("%.4g", pattern.rec_clock_time/4),"quant","quant+trim"} + local mode_options = {"loose","bars: "..string.format("%.4g", pattern.rec_clock_time/4),"quant","quant+trim"} local show_state = pattern.play == 1 and pattern.step or mode_options[pattern.playmode] local fine_options = {show_state, pattern.count > 0 and pattern.rec == 0 and "[K3]" or "(no pat!)", params:string("sync_clock_to_pattern_"..page_line)} screen.move(80,40+(10*(j-1))) @@ -1167,12 +1172,13 @@ function main_menu.init() screen.level(3) - if page.time_sel < 4 and page.time_scroll[page_line] < 3 then + if page.time_sel < 4 then + local show_top = page.time_scroll[page_line] ~= 1 and true or false + local show_bottom = page.time_scroll[page_line] < 3 and true or false screen.move(0,64) - screen.text("...") - elseif page.time_sel < 4 then + screen.text(show_bottom and "..." or "") screen.move(0,34) - screen.text("...") + screen.text(show_top and "..." or "") end elseif menu == 8 then diff --git a/lib/midicheat.lua b/lib/midicheat.lua index 6ca4351..0e244af 100755 --- a/lib/midicheat.lua +++ b/lib/midicheat.lua @@ -7,7 +7,7 @@ function mc.init() for i = 1,3 do mc.redraw(bank[i][bank[i].id]) end - for i = 1,4 do + for i = 1,16 do if midi_dev[i].name == "Midi Fighter Twister" then mc.mft_redraw(bank[1][bank[1].id],"all") end @@ -127,82 +127,84 @@ end function mc.mft_redraw(target,parameter) -- TODO: these need to redraw on the right target.bank_id CCs... -- TODO: when the bank is changed on MFT, redraw these - local duration = target.mode == 1 and 8 or clip[target.clip].sample_length - local min = target.mode == 1 and live[target.clip].min or clip[target.clip].min - local max = target.mode == 1 and live[target.clip].max or clip[target.clip].max - local start_to_cc = util.round(util.linlin(min,max,0,127,target.start_point)) - local dest_cc = - { - [1] = {0,1,2,4,5,6,7,8,10,11} - , [2] = {16,17,18,20,21,22,23,24,26,27} - , [3] = {32,33,34,36,37,38,39,40,42,43} - } - local dests = dest_cc[target.bank_id] - if parameter == "pad_id" then - local pad_to_cc = util.round(util.linlin(1,16,0,127,target.pad_id)) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[1],pad_to_cc,1) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[1],pad_to_cc,5) - elseif parameter == "start_point" then - midi_dev[params:get("midi_enc_control_device")]:cc(dests[2],start_to_cc,1) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[2],start_to_cc,5) - elseif parameter == "end_point" then - local end_to_cc = util.round(util.linlin(min,max,0,127,target.end_point)) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[3],end_to_cc,1) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[3],end_to_cc,5) - elseif parameter == "pad_level" then - local pad_level_to_cc = util.round(util.linlin(0,2,0,127,target.level)) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[4],pad_level_to_cc,1) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[4],pad_level_to_cc,5) - elseif parameter == "bank_level" then - local bank_level_to_cc = util.round(util.linlin(0,2,0,127,bank[target.bank_id].global_level)) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[5],bank_level_to_cc,1) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[5],bank_level_to_cc,5) - elseif parameter == "pad_offset" then - local offset_to_cc = util.round(util.linlin(-1,1,0,127,(math.log(target.offset)/math.log(0.5))*-12)) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[6],offset_to_cc,1) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[6],offset_to_cc,5) - elseif parameter == "pad_rate" then - local rate_to_cc = util.round(util.linlin(-4,4,0,127,target.rate)) - local rates_to_ccs = + if params:string("midi_enc_control_enabled") == "yes" and params:string("midi_enc_echo_enabled") == "yes" and midi_dev[params:get("midi_enc_control_device")].name == "Midi Fighter Twister" then + local duration = target.mode == 1 and 8 or clip[target.clip].sample_length + local min = target.mode == 1 and live[target.clip].min or clip[target.clip].min + local max = target.mode == 1 and live[target.clip].max or clip[target.clip].max + local start_to_cc = util.round(util.linlin(min,max,0,127,target.start_point)) + local dest_cc = { - [4] = 127 - , [2] = 127 - , [1] = 110 - , [0.5] = 95 - , [0.25] = 85 - , [0.125] = 71 - , [0] = 64 - , [-0.125] = 56 - , [-0.25] = 45 - , [-0.5] = 32 - , [-1] = 16 - , [-2] = 10 - , [-4] = 0 + [1] = {0,1,2,4,5,6,7,8,10,11} + , [2] = {16,17,18,20,21,22,23,24,26,27} + , [3] = {32,33,34,36,37,38,39,40,42,43} } - midi_dev[params:get("midi_enc_control_device")]:cc(dests[7],rates_to_ccs[target.rate],1) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[7],rates_to_ccs[target.rate],5) - elseif parameter == "pan" then - local pan_to_cc = util.round(util.linlin(-1,1,0,127,target.pan)) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[8],pan_to_cc,1) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[8],pan_to_cc,5) - elseif parameter == "filter_tilt" then - local tilt_to_cc = util.round(util.linlin(-1,1,0,127,target.tilt)) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[9],tilt_to_cc,1) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[9],tilt_to_cc,5) - elseif parameter == "filter_q" then - local q_to_cc = util.round(util.linlin(-0.3,2,127,0,params:get("filter "..target.bank_id.." q"))) - midi_dev[params:get("midi_enc_control_device")]:cc(dests[10],q_to_cc,1) - elseif parameter == "all" then - mc.mft_redraw(target,"pad_id") - mc.mft_redraw(target,"start_point") - mc.mft_redraw(target,"end_point") - mc.mft_redraw(target,"pad_level") - mc.mft_redraw(target,"bank_level") - mc.mft_redraw(target,"pad_rate") - mc.mft_redraw(target,"pad_offset") - mc.mft_redraw(target,"pan") - mc.mft_redraw(target,"filter_tilt") - mc.mft_redraw(target,"filter_q") + local dests = dest_cc[target.bank_id] + if parameter == "pad_id" then + local pad_to_cc = util.round(util.linlin(1,16,0,127,target.pad_id)) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[1],pad_to_cc,1) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[1],pad_to_cc,5) + elseif parameter == "start_point" then + midi_dev[params:get("midi_enc_control_device")]:cc(dests[2],start_to_cc,1) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[2],start_to_cc,5) + elseif parameter == "end_point" then + local end_to_cc = util.round(util.linlin(min,max,0,127,target.end_point)) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[3],end_to_cc,1) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[3],end_to_cc,5) + elseif parameter == "pad_level" then + local pad_level_to_cc = util.round(util.linlin(0,2,0,127,target.level)) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[4],pad_level_to_cc,1) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[4],pad_level_to_cc,5) + elseif parameter == "bank_level" then + local bank_level_to_cc = util.round(util.linlin(0,2,0,127,bank[target.bank_id].global_level)) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[5],bank_level_to_cc,1) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[5],bank_level_to_cc,5) + elseif parameter == "pad_offset" then + local offset_to_cc = util.round(util.linlin(-1,1,0,127,(math.log(target.offset)/math.log(0.5))*-12)) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[6],offset_to_cc,1) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[6],offset_to_cc,5) + elseif parameter == "pad_rate" then + local rate_to_cc = util.round(util.linlin(-4,4,0,127,target.rate)) + local rates_to_ccs = + { + [4] = 127 + , [2] = 127 + , [1] = 110 + , [0.5] = 95 + , [0.25] = 85 + , [0.125] = 71 + , [0] = 64 + , [-0.125] = 56 + , [-0.25] = 45 + , [-0.5] = 32 + , [-1] = 16 + , [-2] = 10 + , [-4] = 0 + } + midi_dev[params:get("midi_enc_control_device")]:cc(dests[7],rates_to_ccs[target.rate],1) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[7],rates_to_ccs[target.rate],5) + elseif parameter == "pan" then + local pan_to_cc = util.round(util.linlin(-1,1,0,127,target.pan)) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[8],pan_to_cc,1) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[8],pan_to_cc,5) + elseif parameter == "filter_tilt" then + local tilt_to_cc = util.round(util.linlin(-1,1,0,127,target.tilt)) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[9],tilt_to_cc,1) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[9],tilt_to_cc,5) + elseif parameter == "filter_q" then + local q_to_cc = util.round(util.linlin(-0.3,2,127,0,params:get("filter "..target.bank_id.." q"))) + midi_dev[params:get("midi_enc_control_device")]:cc(dests[10],q_to_cc,1) + elseif parameter == "all" then + mc.mft_redraw(target,"pad_id") + mc.mft_redraw(target,"start_point") + mc.mft_redraw(target,"end_point") + mc.mft_redraw(target,"pad_level") + mc.mft_redraw(target,"bank_level") + mc.mft_redraw(target,"pad_rate") + mc.mft_redraw(target,"pad_offset") + mc.mft_redraw(target,"pan") + mc.mft_redraw(target,"filter_tilt") + mc.mft_redraw(target,"filter_q") + end end end diff --git a/lib/speed_dial.lua b/lib/speed_dial.lua new file mode 100755 index 0000000..85dc4fa --- /dev/null +++ b/lib/speed_dial.lua @@ -0,0 +1,171 @@ +local sd = {} +-- page.time_sel = 1 +-- page.time_page = {} +-- page.time_page_sel = {} +-- page.time_scroll = {} +-- for i = 1,6 do +-- page.time_page[i] = 1 +-- page.time_page_sel[i] = 1 +-- page.time_scroll[i] = 1 +-- end +-- page.time_arc_loop = {1,1,1} +-- page.track_sel = {} +-- page.track_page = 1 +-- page.track_page_section = {} +-- for i = 1,4 do +-- page.track_sel[i] = 1 +-- page.track_page_section[i] = 1 +-- end +-- page.track_param_sel = {} +-- for i = 1,3 do +-- page.track_param_sel[i] = 1 +-- end + +-- ARP +-- page.arp_page_sel = 1 +-- page.arp_param = {1,1,1} +-- page.arp_alt = {false,false,false} +-- page.arp_param_group = {} +-- for i = 1,3 do +-- page.arp_param_group[i] = 1 +-- end + +-- RND +-- page.rnd_page = 1 +-- page.rnd_page_section = 1 +-- page.rnd_page_sel = {} +-- page.rnd_page_edit = {} +-- for i = 1,3 do +-- page.rnd_page_sel[i] = 1 +-- page.rnd_page_edit[i] = 1 +-- end + +-- MIDI SETUP +-- page.midi_setup = 1 +-- page.midi_focus = "header" +-- page.midi_bank = 1 + +-- MACROS +-- page.macros = {} +-- page.macros.selected_macro = 1 +-- page.macros.section = 1 +-- page.macros.param_sel = {} +-- page.macros.edit_focus = {} +-- page.macros.mode = "setup" +-- for i = 1,8 do +-- page.macros.param_sel[i] = 1 +-- page.macros.edit_focus[i] = 1 +-- end + +-- TRANSPORT +-- page.transport = {} +-- page.transport.foci = {"TRANSPORT","TAP-TEMPO"} +-- page.transport.focus = "TRANSPORT" + +function sd:init() + for i = 1,56 do + self.stored = {} + end +end + +function deep_copy(orig) + local orig_type = type(orig) + local copy + if orig_type == "table" then + copy = {} + for orig_key, orig_value in next, orig, nil do + copy[deep_copy(orig_key)] = deep_copy(orig_value) + end + setmetatable(copy, deep_copy(getmetatable(orig))) + else -- number, string, boolean, etc + copy = orig + end + return copy +end + +function sd:store(slot,menu) + self.stored[slot] = deep_copy(menu) +end + +function sd:lookup_page_data() + if target == 2 then + for k,v in pairs(page.loops) do + print(k,v) + end + end + -- page.loops.frame = 1 +-- page.loops.sel = 1 +-- page.loops.meta_sel = 1 +-- page.loops.meta_option_set = {1,1,1,1} +-- page.loops.top_option_set = {1,1,1,1} +-- page.loops.focus_hold = {false, false, false, false} +-- page.main_sel = 1 +-- page.loops_sel = 1 +end + +function sd:try_save(menu,slot) + local stuff = {} + if menu == 2 then + stuff["sel"] = page.loops.sel + stuff["frame"] = page.loops.frame + stuff["meta_sel"] = page.loops.meta_sel + elseif menu == 3 then + stuff["sel"] = page.levels.sel + elseif menu == 4 then + elseif menu == 5 then + stuff["sel"] = page.filters.sel + elseif menu == 6 then + stuff = deep_copy(page.delay) + -- stuff["section"] = page.delay.section + -- stuff["focus"] = page.delay.focus + -- stuff[1]["menu"] = page.delay[1].menu + -- stuff[2]["menu"] = page.delay[2].menu + -- stuff[1]["menu_sel"] = deep_copy(page.delay[1].menu_sel) + -- stuff[2]["menu_sel"] = deep_copy(page.delay[2].menu_sel) + -- stuff["L menu"] = page.delay[1].menu + -- stuff["R menu"] = page.delay[2].menu + -- stuff["L menu_sel"] = deep_copy(page.delay[1].menu_sel) + -- stuff["R menu_sel"] = deep_copy(page.delay[2].menu_sel) + elseif menu == 7 then + end + stuff["menu"] = menu + if stuff ~= nil then + self.stored[slot] = deep_copy(stuff) + end +end + +function sd:try_restore(slot) + if self.stored[slot].menu == 2 then + self:translate_data(self.stored[slot],page.loops) + elseif self.stored[slot].menu == 3 then + self:translate_data(self.stored[slot],page.levels) + elseif self.stored[slot].menu == 4 then + self:translate_data(self.stored[slot],page.pans) + elseif self.stored[slot].menu == 5 then + self:translate_data(self.stored[slot],page.filters) + elseif self.stored[slot].menu == 6 then + print("this happening?") + -- self:deep_translate_data(self.stored[slot],page.delay) + page.delay = deep_copy(speed_dial.stored[slot]) + end + +end + +function sd:translate_data(source,target) + for k,v in pairs(source) do + if k ~= "menu" then + target[k] = v + else + menu = v + end + end + screen_dirty = true +end + +function sd:deep_translate_data(source,target) + menu = source.menu + target = deep_copy(source) + tab.print(target) +end + +return sd \ No newline at end of file diff --git a/lib/start_up.lua b/lib/start_up.lua index 7bf6721..94e6ac0 100755 --- a/lib/start_up.lua +++ b/lib/start_up.lua @@ -18,7 +18,6 @@ function start_up.init() softcut.loop_end(i, 9) softcut.loop_end(1,8.99) softcut.loop(i, 1) - softcut.rec(1, 1) softcut.rec_level(1, 1) -- softcut.pre_level(1, 0.25) softcut.pre_level(1, 1) @@ -29,6 +28,11 @@ function start_up.init() softcut.enable(i, 1) softcut.rate_slew_time(4,0.2) end + + clock.run(function() + clock.sleep(0.25) + softcut.rec(1, 1) + end) softcut.event_phase(phase) softcut.poll_start_phase() @@ -71,7 +75,7 @@ function start_up.init() --params:add_separator() - params:add_group("loops + buffers", 28) + params:add_group("loops + buffers", 29) params:add_separator("clips") @@ -113,7 +117,19 @@ function start_up.init() ) end - params:add_option("one_shot_clock_div","--> 1-shot sync",{"next beat","next bar","free"},1) + params:add_option("one_shot_clock_div","--> 1-shot sync",{"next beat","next bar","free","threshold"},1) + params:set_action("one_shot_clock_div", + function(x) + if x ~= 4 then + params:hide("one_shot_threshold") + _menu.rebuild_params() + else + params:show("one_shot_threshold") + _menu.rebuild_params() + end + end + ) + params:add_control("one_shot_threshold","----> thresh",controlspec.new(1,1000,'exp',1,85,'amp/10k')) params:add_control("one_shot_latency_offset","--> latency offset",controlspec.new(0,1,'lin',0.01,0,'s')) params:add_option("rec_loop_enc_resolution", "rec loop enc resolution", {"0.1","0.01","1/16","1/8","1/4","1/2","1 bar"}, 1)