SHARE
TWEET

Untitled

a guest Jun 25th, 2019 76 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- Passersby w/ tunnels . Monome Grid Version
  2. -- 1.1.1 @markeats
  3. -- llllllll.co/t/21089
  4. --
  5. -- GRID controlled West Coast
  6. -- style mono synth.
  7. --
  8. -- E1/K2 : Change page
  9. -- K3 : Change tab
  10. -- E2/3 : Adjust parameters
  11. --
  12. -- Tunnels page
  13. -- K1 (hold): clear buffer
  14. -- K2/K3: randomize params
  15. -- tunnels v1.1 @speakerdamage
  16.  
  17. local MusicUtil = require "musicutil"
  18. local UI = require "ui"
  19. local Graph = require "graph"
  20. local EnvGraph = require "envgraph"
  21. local Passersby = require "passersby/lib/passersby_engine"
  22.  
  23. local tab = require 'tabutil'
  24. local pattern_time = require 'pattern_time'
  25. local g = grid.connect()
  26. local mode_transpose = 0
  27. local root = { x=5, y=5 }
  28. local trans = { x=5, y=5 }
  29. local lit = {}
  30. local screen_framerate = 15
  31. local screen_refresh_metro
  32.  
  33. local ripple_repeat_rate = 1 / 0.3 / screen_framerate
  34. local ripple_decay_rate = 1 / 0.5 / screen_framerate
  35. local ripple_growth_rate = 1 / 0.02 / screen_framerate
  36. local screen_notes = {}
  37.  
  38.  
  39.  
  40. local tn = include('tunnels/lib/tunnel')
  41.  
  42. local SCREEN_FRAMERATE = 15
  43. local screen_refresh_metro
  44. local screen_dirty = true
  45.  
  46. local midi_in_device
  47. local active_notes = {}
  48.  
  49. local pages
  50. local tabs
  51. local tab_titles = {{"Wave", "FM"}, {"Env", "Reverb"}, {"LFO", "Targets"}, {"Fate"}, {"Tunnels"}}
  52.  
  53. local input_indicator_active = false
  54. local wave_table = {}
  55. local wave = {}
  56. local wave_graph
  57. local SUB_SAMPLING = 4
  58. local fm1_dial
  59. local fm2_dial
  60. local env_graph
  61. local env_status = {}
  62. local env_status_metro
  63. local spring_path = {}
  64. local reverb_slider
  65. local lfo_graph
  66. local dice_throw_vel = 0
  67. local dice_throw_progress = 0
  68. local dice_thrown = false
  69. local dice_need_update = false
  70. local dice = {}
  71. local drift_dial
  72.  
  73. local timbre = 0
  74. local wave_shape = {actual = 0, modu = 0, dirty = true}
  75. local wave_folds = {actual = 0, modu = 0, dirty = true}
  76. local fm1_amount = {actual = 0, modu = 0, dirty = true}
  77. local fm2_amount = {actual = 0, modu = 0, dirty = true}
  78. local attack = {actual = 0, modu = 0, dirty = true}
  79. local peak = {actual = 0, modu = 1, dirty = true}
  80. local decay = {actual = 0, modu = 0, dirty = true}
  81. local reverb_mix = {actual = 0, modu = 0, dirty = true}
  82. local lfo_shape = {dirty = true}
  83. local lfo_freq = {dirty = true}
  84. local lfo_destinations = {dirty = true}
  85. local drift = {actual = 0, dirty = true}
  86.  
  87. engine.name = "Passersby"
  88.  
  89. params:bang()
  90.  
  91.  
  92. local function getHz(deg,oct)
  93.   return base * ratios[deg] * (2^oct)
  94. end
  95.  
  96. local function getHzET(note)
  97.   return 55*2^(note/12)
  98. end
  99. -- current count of active voices
  100.  
  101. local nvoices = 0
  102.  
  103. function init()
  104.   m = midi.connect()
  105.   m.event = midi_event
  106.  
  107.  
  108.  
  109.  
  110. local MAX_NUM_VOICES = 16
  111.  
  112.  
  113.  
  114.   engine.noteOffAll()
  115.   stop_all_screen_notes()
  116.  
  117.  
  118.   if g then gridredraw() end
  119.  
  120.  
  121. end
  122. --local tunnelgroup
  123. local tunnelmode = 1
  124. local tgroup
  125. local tunnelmodes_list
  126. local tunnelmodes = {"off", "fractal landscape", "disemboguement", "post-horizon", "coded air", "failing lantern", "blue cat", "crawler"}
  127.  
  128.  
  129. -- Utilities
  130.  
  131. local function generate_wave_table(cycles, length)
  132.   local wave_table = {{},{},{},{}}
  133.   for sx = 1, length do
  134.     local x = util.linlin(1, length, 0, cycles, sx)
  135.     local square = math.abs(x * 2 % 2 - 1) - 0.5
  136.     square = square > 0 and 0.5 or math.floor(square) * 0.5
  137.     table.insert(wave_table[1], math.sin(x * 2 * math.pi)) -- Sine
  138.     table.insert(wave_table[2], math.abs((x * 2 - 0.5) % 2 - 1) * 2 - 1) -- Tri
  139.     table.insert(wave_table[3], square) -- Square
  140.     table.insert(wave_table[4], (1 - (x + 0.25) % 1) * 2 - 1) -- Saw
  141.   end
  142.   return wave_table
  143. end
  144.  
  145. local function generate_wave(x)
  146.  
  147.   x = util.round(x)
  148.   local index_f = wave_shape.actual * (#wave_table - 1) + 1
  149.   local index = util.round(index_f)
  150.   local delta = index_f - index
  151.  
  152.   local index_offset = delta < 0 and -1 or 1
  153.   local y
  154.  
  155.   -- Wave table lookup
  156.   if delta == 0 then
  157.     y = wave_table[index][x]
  158.   else
  159.     y = wave_table[index + index_offset][x] * math.abs(delta) + wave_table[index][x] * (1 - math.abs(delta))
  160.   end
  161.  
  162.   -- Wave folding
  163.   y = y * (1 + wave_folds.actual)
  164.   local abs_y = math.abs(y)
  165.  
  166.   if abs_y > 1 then
  167.     local folded = abs_y % 1
  168.     if math.floor(abs_y - 1) % 2 == 0 then
  169.       folded = 1 - folded
  170.     else
  171.       folded = folded
  172.     end
  173.     folded = folded * 2 - 1
  174.     if y < 0 then folded = folded * -1 end
  175.     y = folded
  176.   end
  177.  
  178.   return y
  179. end
  180.  
  181. local function generate_spring_path(width, height, turns)
  182.   local spring_path = {}
  183.   for y = 0, height - 1 do
  184.     local progress = util.linlin(0, height - 1, 0, math.pi * turns * 2, y)
  185.     table.insert(spring_path, {x = width * 0.5 + math.sin(progress) * width * 0.5, y = y})
  186.   end
  187.   return spring_path
  188. end
  189.  
  190. local function generate_lfo_wave(x)
  191.  
  192.   local lfo_shape = params:get("lfo_shape")
  193.   x = x * util.linlin(Passersby.specs.LFO_FREQ.minval, Passersby.specs.LFO_FREQ.maxval, 0.5, 10, params:get("lfo_freq"))
  194.  
  195.   if lfo_shape == 1 then -- Tri
  196.     x = math.abs((x * 2 - 0.5) % 2 - 1) * 2 - 1
  197.   elseif lfo_shape == 2 then -- Ramp
  198.     x = ((x + 0.25) % 1) * 2 - 1
  199.   elseif lfo_shape == 3 then -- Square
  200.     x = math.abs(x * 2 % 2 - 1) - 0.5
  201.     x = x > 0 and 1 or math.floor(x)
  202.   elseif lfo_shape == 4 then -- Random
  203.     local NOISE = {0.7, -0.65, 0.2, 0.9, -0.1, -0.5, 0.7, -0.9, 0.25, 1.0, -0.6, -0.2, 0.6, -0.35, 0.7, 0.1, -0.5, 0.7, 0.2, -0.85, -0.3}
  204.     x = NOISE[util.round(x * 2) + 1]
  205.   end
  206.  
  207.   return x * 0.75
  208. end
  209.  
  210. local function update_lfo_amounts_list()
  211.   lfo_amounts_list.entries = {
  212.     util.round(params:get("lfo_to_freq_amount") * 100, 1),
  213.     util.round(params:get("lfo_to_wave_shape_amount") * 100, 1),
  214.     util.round(params:get("lfo_to_wave_folds_amount") * 100, 1),
  215.     util.round(params:get("lfo_to_fm_low_amount") * 100, 1),
  216.     util.round(params:get("lfo_to_fm_high_amount") * 100, 1),
  217.     util.round(params:get("lfo_to_attack_amount") * 100, 1),
  218.     util.round(params:get("lfo_to_peak_amount") * 100, 1),
  219.     util.round(params:get("lfo_to_decay_amount") * 100, 1),
  220.     util.round(params:get("lfo_to_reverb_mix_amount") * 100, 1)
  221.   }
  222. end
  223.  
  224. local function randomize_dice()
  225.   for i = 1, 2 do
  226.     local direction = 0
  227.     if dice[i] then
  228.       direction = (dice[i].top_angle - dice[i].table_angle > 0) and 1 or -1
  229.     end
  230.     dice[i] = {}
  231.     dice[i].face = math.random(6)
  232.     dice[i].top_angle = 1 + math.random() * 2
  233.     if math.random() > 0.5 then dice[i].top_angle = dice[i].top_angle * -1 end
  234.     dice[i].table_angle = math.random() * 0.5 - 0.25 + (2 * math.pi * direction)
  235.   end
  236. end
  237.  
  238. local function set_dice_throw_vel(vel_delta)
  239.   dice_throw_vel = util.clamp(dice_throw_vel + vel_delta, -0.35, 0.3)
  240.   dice_need_update = true
  241. end
  242.  
  243. local function start_env_status_timeout(status_text, x, y)
  244.   env_status.text = status_text
  245.   env_status.x, env_status.y = x, y
  246.   if env_status_metro.is_running then
  247.     env_status_metro:stop()
  248.   end
  249.   env_status_metro:start(1, 1)
  250. end
  251.  
  252. local function update_tabs()
  253.  
  254.   wave_graph:set_active(tabs.index == 1)
  255.   env_graph:set_active(tabs.index == 1 or params:get("env_type") == 2)
  256.   lfo_graph:set_active(tabs.index == 1)
  257.  
  258.   if tabs.index == 2 then env_status.text = "" end
  259.   lfo_destinations_list.active = tabs.index == 2
  260.   lfo_amounts_list.active = tabs.index == 2
  261.   fm1_dial.active = tabs.index == 2
  262.   fm2_dial.active = tabs.index == 2
  263.  
  264.   screen_dirty = true
  265. end
  266.  
  267. local function update_pages()
  268.   tabs:set_index(1)
  269.   tabs.titles = tab_titles[pages.index]
  270.   env_status.text = ""
  271.   lfo_destinations_list:set_index(1)
  272.   lfo_amounts_list:set_index(1)
  273.   update_tabs()
  274. end
  275.  
  276. local function init_env_graph(env_type)
  277.   if env_type == 1 then
  278.     env_graph = EnvGraph.new_ar(0, 1, 0, 1, 0.003, util.explin(Passersby.specs.DECAY.minval * 0.5, Passersby.specs.DECAY.maxval, 0, 1, decay.actual), util.explin(Passersby.specs.PEAK.minval * 0.5, Passersby.specs.PEAK.maxval, 0, 1, peak.actual), -4)
  279.   else
  280.     env_graph = EnvGraph.new_asr(0, 1, 0, 1, util.explin(Passersby.specs.ATTACK.minval, Passersby.specs.ATTACK.maxval, 0, 0.4, attack.actual), util.explin(Passersby.specs.DECAY.minval, Passersby.specs.DECAY.maxval, 0, 0.4, decay.actual), 1, -4)
  281.   end
  282.   env_graph:set_position_and_size(8, 22, 49, 36)
  283.   env_graph:set_show_x_axis(true)
  284. end
  285.  
  286.  
  287. -- Engine functions
  288.  
  289. local function note_on(note_num, vel)
  290.   engine.noteOn(note_num, MusicUtil.note_num_to_freq(note_num), vel)
  291.   table.insert(active_notes, note_num)
  292.   input_indicator_active = true
  293.   screen_dirty = true
  294. end
  295.  
  296. local function note_off(note_num)
  297.   engine.noteOff(note_num)
  298.   for i = #active_notes, 1, -1 do
  299.     if active_notes[i] == note_num then
  300.       table.remove(active_notes, i)
  301.     end
  302.   end
  303.   if #active_notes == 0 then
  304.     input_indicator_active = false
  305.     screen_dirty = true
  306.   end
  307. end
  308.  
  309. local function set_pitch_bend(bend_st)
  310.   engine.pitchBendAll(MusicUtil.interval_to_ratio(bend_st))
  311. end
  312.  
  313. local function set_channel_pressure(pressure)
  314.   engine.pressureAll(pressure)
  315. end
  316.  
  317. local function set_channel_timbre(value)
  318.   engine.timbreAll(value)
  319.   timbre = value * 0.5
  320.   wave_folds.dirty = true
  321. end
  322.  
  323. -- tunnels
  324. local function update_tunnels()
  325.   local tm = tunnelmode
  326.   local tg = tgroup
  327.   tn.randomize(tm, tg)
  328. end
  329.  
  330. -- Updaters
  331.  
  332. local function update_wave_shape()
  333.   wave_shape.actual = util.clamp(params:get("wave_shape") + wave_shape.modu, Passersby.specs.WAVE_SHAPE.minval, Passersby.specs.WAVE_SHAPE.maxval)
  334.   wave_graph:update_functions()
  335.   wave_shape.dirty = false
  336.   screen_dirty = true
  337. end
  338.  
  339. local function update_wave_folds()
  340.   wave_folds.actual = util.clamp(params:get("wave_folds") + timbre + wave_folds.modu, Passersby.specs.WAVE_FOLDS.minval, Passersby.specs.WAVE_FOLDS.maxval + 0.5)
  341.   wave_graph:update_functions()
  342.   wave_folds.dirty = false
  343.   screen_dirty = true
  344. end
  345.  
  346. local function update_fm1_amount()
  347.   fm1_amount.actual = util.clamp(params:get("fm_low_amount") + fm1_amount.modu, Passersby.specs.FM_LOW_AMOUNT.minval, Passersby.specs.FM_LOW_AMOUNT.maxval)
  348.   fm1_dial.value = fm1_amount.actual * 100
  349.   fm1_amount.dirty = false
  350.   screen_dirty = true
  351. end
  352.  
  353. local function update_fm2_amount()
  354.   fm2_amount.actual = util.clamp(params:get("fm_high_amount") + fm2_amount.modu, Passersby.specs.FM_HIGH_AMOUNT.minval, Passersby.specs.FM_HIGH_AMOUNT.maxval)
  355.   fm2_dial.value = fm2_amount.actual * 100
  356.   fm2_amount.dirty = false
  357.   screen_dirty = true
  358. end
  359.  
  360. local function update_attack()
  361.   attack.actual = util.clamp(params:get("attack") + attack.modu, Passersby.specs.ATTACK.minval, Passersby.specs.ATTACK.maxval)
  362.   if params:get("env_type") == 2 then
  363.     local norm_attack = util.explin(Passersby.specs.ATTACK.minval, Passersby.specs.ATTACK.maxval, 0, 0.4, attack.actual)
  364.     env_graph:edit_asr(norm_attack)
  365.   end
  366.   attack.dirty = false
  367.   screen_dirty = true
  368. end
  369.  
  370. local function show_attack_status()
  371.   if params:get("env_type") == 2 then
  372.     local norm_attack = util.explin(Passersby.specs.ATTACK.minval, Passersby.specs.ATTACK.maxval, 0, 0.4, params:get("attack") + attack.modu)
  373.     local norm_peak = util.explin(Passersby.specs.PEAK.minval * 0.5, Passersby.specs.PEAK.maxval, 0, 1, params:get("peak") * peak.modu)
  374.     local y
  375.     if norm_peak > 0.6 then y = 46 else y = util.linlin(0, 1, 52, 18, norm_peak) end
  376.     start_env_status_timeout(params:string("attack"), 38, y)
  377.     screen_dirty = true
  378.   end
  379. end
  380.  
  381. local function update_peak()
  382.   peak.actual = util.clamp(params:get("peak") * peak.modu, Passersby.specs.PEAK.minval, Passersby.specs.PEAK.maxval)
  383.   local norm_peak = util.explin(Passersby.specs.PEAK.minval * 0.5, Passersby.specs.PEAK.maxval, 0, 1, peak.actual)
  384.   if params:get("env_type") == 1 then
  385.     env_graph:edit_ar(nil, nil, norm_peak)
  386.   else
  387.     env_graph:edit_asr(nil, nil, norm_peak)
  388.   end
  389.   peak.dirty = false
  390.   screen_dirty = true
  391. end
  392.  
  393. local function show_peak_status()
  394.   local norm_peak = util.explin(Passersby.specs.PEAK.minval * 0.5, Passersby.specs.PEAK.maxval, 0, 1, params:get("peak") * peak.modu)
  395.   if params:get("env_type") == 1 then
  396.     start_env_status_timeout(params:string("peak"), 57, util.linlin(0, 1, 56, 26, norm_peak))
  397.   else
  398.     start_env_status_timeout(params:string("peak"), 45, util.linlin(0, 1, 52, 18, norm_peak))
  399.   end
  400.   screen_dirty = true
  401. end
  402.  
  403. local function update_decay()
  404.   decay.actual = util.clamp(params:get("decay") + decay.modu, Passersby.specs.DECAY.minval, Passersby.specs.DECAY.maxval)
  405.   if params:get("env_type") == 1 then
  406.     local norm_decay = util.explin(Passersby.specs.DECAY.minval * 0.5, Passersby.specs.DECAY.maxval, 0, 1, decay.actual)
  407.     env_graph:edit_ar(nil, norm_decay)
  408.   else
  409.     local norm_decay = util.explin(Passersby.specs.DECAY.minval, Passersby.specs.DECAY.maxval, 0, 0.4, decay.actual)
  410.     env_graph:edit_asr(nil, norm_decay)
  411.   end
  412.   decay.dirty = false
  413.   screen_dirty = true
  414. end
  415.  
  416. local function show_decay_status()
  417.   local norm_decay
  418.   if params:get("env_type") == 1 then
  419.     norm_decay = util.explin(Passersby.specs.DECAY.minval * 0.5, Passersby.specs.DECAY.maxval, 0, 0.4, params:get("decay") + decay.modu)
  420.     start_env_status_timeout(params:string("decay"), util.linlin(0, 1, 38, 80, norm_decay), 48)
  421.   else
  422.     norm_decay = util.explin(Passersby.specs.DECAY.minval, Passersby.specs.DECAY.maxval, 0.4, 0, params:get("decay") + decay.modu)
  423.     local norm_peak = util.explin(Passersby.specs.PEAK.minval * 0.5, Passersby.specs.PEAK.maxval, 0, 1, params:get("peak") * peak.modu)
  424.     local y
  425.     if norm_peak > 0.6 then y = 53 else y = util.linlin(0, 1, 52, 18, norm_peak) end
  426.     start_env_status_timeout(params:string("decay"), util.linlin(0, 1, 39, 74, norm_decay), y)
  427.   end
  428.   screen_dirty = true
  429. end
  430.  
  431. local function update_reverb_mix()
  432.   reverb_mix.actual = util.clamp(params:get("reverb_mix") + reverb_mix.modu, Passersby.specs.REVERB_MIX.minval, Passersby.specs.REVERB_MIX.maxval)
  433.   reverb_slider.value = reverb_mix.actual
  434.   reverb_mix.dirty = false
  435.   screen_dirty = true
  436. end
  437.  
  438.  
  439. local function update_lfo_shape()
  440.   lfo_graph:update_functions()
  441.   lfo_shape.dirty = false
  442.   screen_dirty = true
  443. end
  444.  
  445. local function update_lfo_freq()
  446.   lfo_graph:update_functions()
  447.   lfo_freq.dirty = false
  448.   screen_dirty = true
  449. end
  450.  
  451. local function update_lfo_destinations()
  452.   update_lfo_amounts_list()
  453.   lfo_destinations.dirty = false
  454.   screen_dirty = true
  455. end
  456.  
  457. local function update_drift()
  458.   drift_dial.value = params:get("drift") * 100
  459.   drift.dirty = false
  460.   screen_dirty = true
  461. end
  462.  
  463.  
  464.  
  465. -- Input functions
  466.  
  467. -- Encoder input
  468. function enc(n, delta)
  469.  
  470.   if n == 1 then
  471.     -- Page scroll
  472.     pages:set_index_delta(util.clamp(delta, -1, 1), false)
  473.     update_pages()
  474.   end
  475.  
  476.   if pages.index == 1 then
  477.  
  478.       if tabs.index == 1 then
  479.         -- Wave
  480.         if n == 2 then
  481.           params:delta("wave_shape", delta)
  482.         elseif n == 3 then
  483.           params:delta("wave_folds", delta)
  484.         end
  485.  
  486.       else
  487.         -- FM
  488.         if n == 2 then
  489.           params:delta("fm_low_amount", delta)
  490.         elseif n == 3 then
  491.           params:delta("fm_high_amount", delta)
  492.         end
  493.       end
  494.  
  495.   elseif pages.index == 2 then
  496.  
  497.       if tabs.index == 1 then
  498.         -- LPG
  499.         if n == 2 then
  500.           if params:get("env_type") == 1 then
  501.             params:delta("peak", delta)
  502.           else
  503.             params:delta("attack", delta)
  504.           end
  505.         elseif n == 3 then
  506.           if params:get("env_type") == 1 then
  507.             params:delta("decay", delta)
  508.           else
  509.             params:delta("decay", -delta)
  510.           end
  511.         end
  512.  
  513.       else
  514.         -- Peak
  515.         if n == 2 and params:get("env_type") == 2 then
  516.           params:delta("peak", delta)
  517.         -- Reverb
  518.         elseif n == 3 then
  519.           params:delta("reverb_mix", delta)
  520.         end
  521.       end
  522.  
  523.   elseif pages.index == 3 then
  524.  
  525.     if tabs.index == 1 then
  526.       -- LFO
  527.       if n == 2 then
  528.         params:delta("lfo_shape", util.clamp(delta, -1, 1))
  529.       elseif n == 3 then
  530.         params:delta("lfo_freq", delta)
  531.       end
  532.  
  533.     else
  534.       -- LFO scroll lists
  535.       if n == 2 then
  536.         lfo_destinations_list:set_index_delta(util.clamp(delta, -1, 1), false)
  537.         lfo_amounts_list:set_index(lfo_destinations_list.index)
  538.         screen_dirty = true
  539.  
  540.       -- LFO amounts
  541.       elseif n == 3 then
  542.         if lfo_destinations_list.index == 1 then
  543.           params:delta("lfo_to_freq_amount", delta)
  544.         elseif lfo_destinations_list.index == 2 then
  545.           params:delta("lfo_to_wave_shape_amount", delta)
  546.         elseif lfo_destinations_list.index == 3 then
  547.           params:delta("lfo_to_wave_folds_amount", delta)
  548.         elseif lfo_destinations_list.index == 4 then
  549.           params:delta("lfo_to_fm_low_amount", delta)
  550.         elseif lfo_destinations_list.index == 5 then
  551.           params:delta("lfo_to_fm_high_amount", delta)
  552.         elseif lfo_destinations_list.index == 6 then
  553.           params:delta("lfo_to_attack_amount", delta)
  554.         elseif lfo_destinations_list.index == 7 then
  555.           params:delta("lfo_to_peak_amount", delta)
  556.         elseif lfo_destinations_list.index == 8 then
  557.           params:delta("lfo_to_decay_amount", delta)
  558.         elseif lfo_destinations_list.index == 9 then
  559.           params:delta("lfo_to_reverb_mix_amount", delta)
  560.         end
  561.       end
  562.  
  563.     end
  564.  
  565.   elseif pages.index == 4 then
  566.  
  567.     -- Randomize
  568.     if n == 2 then
  569.       if not dice_thrown then set_dice_throw_vel(delta * 0.05) end
  570.  
  571.     -- Drift
  572.     elseif n == 3 then
  573.       params:delta("drift", delta)
  574.     end
  575.  
  576.   -- tunnels
  577.   elseif pages.index == 5 then
  578.     if n == 2 then
  579.       tunnelmodes_list:set_index_delta(util.clamp(delta, -1, 1))
  580.       tunnelmode = tunnelmodes_list.index
  581.       --softcut.buffer_clear()
  582.       tgroup = 1
  583.       update_tunnels(tunnelmode)
  584.       tgroup = 2
  585.       update_tunnels(tunnelmode)
  586.       screen_dirty = true
  587.     end
  588.   end
  589.  
  590. end
  591.  
  592. -- Key input
  593. function key(n, z)
  594.   if pages.index == 5 then
  595.     if z == 1 then
  596.       if n == 1 then
  597.         softcut.buffer_clear()
  598.       elseif n == 2 then
  599.         tgroup = 1
  600.         update_tunnels(tunnelmode)
  601.         redraw()
  602.       elseif n == 3 then
  603.         tgroup = 2
  604.         update_tunnels(tunnelmode)
  605.         redraw()
  606.       end
  607.     end
  608.   else
  609.     if z == 1 then
  610.       if n == 1 then
  611.         softcut.buffer_clear()
  612.       elseif n == 2 then
  613.         pages:set_index_delta(1, true)
  614.         update_pages()
  615.  
  616.       elseif n == 3 then
  617.         tabs:set_index_delta(1, true)
  618.         update_tabs()
  619.  
  620.       end
  621.     end
  622.   end
  623. end
  624.  
  625. -- GRID input
  626.  
  627.   local pattern_time = require 'pattern_time'
  628.  
  629.   pat = pattern_time.new()
  630.   pat.process = grid_note_trans
  631.  
  632. local MAX_NUM_VOICES = 16
  633.  
  634. function grid_note_trans(e)
  635.   local note = ((7-e.y+(root.y-trans.y))*5) + e.x + (trans.x-root.x)
  636.   if e.state > 0 then
  637.     if nvoices < MAX_NUM_VOICES then
  638.       --engine.start(id, getHz(x, y-1))
  639.       --print("grid > "..id.." "..note)
  640.       engine.noteOn(e.id, getHzET(note))
  641.       start_screen_note(note)
  642.       lit[e.id] = {}
  643.       lit[e.id].x = e.x + trans.x - root.x
  644.       lit[e.id].y = e.y + trans.y - root.y
  645.       nvoices = nvoices + 1
  646.     end
  647.   else
  648.     engine.noteOff(e.id)
  649.     stop_screen_note(note)
  650.     lit[e.id] = nil
  651.     nvoices = nvoices - 1
  652.   end
  653.   gridredraw()
  654. end
  655.  
  656. function g.key(x, y, z)
  657.   if x == 1 then
  658.     if z == 1 then
  659.       if y == 1 and pat.rec == 0 then
  660.         mode_transpose = 0
  661.         trans.x = 5
  662.         trans.y = 5
  663.         pat:stop()
  664.         engine.noteOffAll()
  665.         pat:clear()
  666.         pat:rec_start()
  667.       elseif y == 1 and pat.rec == 1 then
  668.         pat:rec_stop()
  669.         if pat.count > 0 then
  670.           root.x = pat.event[1].x
  671.           root.y = pat.event[1].y
  672.           trans.x = root.x
  673.           trans.y = root.y
  674.           pat:start()
  675.         end
  676.       elseif y == 2 and pat.play == 0 and pat.count > 0 then
  677.         if pat.rec == 1 then
  678.           pat:rec_stop()
  679.         end
  680.         pat:start()
  681.       elseif y == 2 and pat.play == 1 then
  682.         pat:stop()
  683.         engine.noteOffAll()
  684.         stop_all_screen_notes()
  685.         nvoices = 0
  686.         lit = {}
  687.       elseif y == 8 then
  688.         mode_transpose = 1 - mode_transpose
  689.       end
  690.     end
  691.   else
  692.     if mode_transpose == 0 then
  693.       local e = {}
  694.       e.id = x*8 + y
  695.       e.x = x
  696.       e.y = y
  697.       e.state = z
  698.       pat:watch(e)
  699.       grid_note(e)
  700.     else
  701.       trans.x = x
  702.       trans.y = y
  703.     end
  704.   end
  705.   gridredraw()
  706. end
  707.  
  708.  
  709. function grid_note(e)
  710.   local note = ((7-e.y)*5) + e.x
  711.   if e.state > 0 then
  712.     if nvoices < MAX_NUM_VOICES then
  713.       --engine.start(id, getHz(x, y-1))
  714.       --print("grid > "..id.." "..note)
  715.       engine.noteOn(e.id, getHzET(note), vel)
  716.      
  717.       lit[e.id] = {}
  718.       lit[e.id].x = e.x
  719.       lit[e.id].y = e.y
  720.       nvoices = nvoices + 1
  721.     end
  722.   else
  723.     if lit[e.id] ~= nil then
  724.       engine.noteOff(e.id)
  725.      
  726.       lit[e.id] = nil
  727.       nvoices = nvoices - 1
  728.     end
  729.   end
  730.   gridredraw()
  731. end
  732.  
  733.  
  734.  
  735. function gridredraw()
  736.   g:all(0)
  737.   g:led(1,1,2 + pat.rec * 10)
  738.   g:led(1,2,2 + pat.play * 10)
  739.   g:led(1,8,2 + mode_transpose * 10)
  740.  
  741.   if mode_transpose == 1 then g:led(trans.x, trans.y, 4) end
  742.   for i,e in pairs(lit) do
  743.     g:led(e.x, e.y,15)
  744.   end
  745.  
  746.   g:refresh()
  747. end
  748.  
  749. function note_on(note, vel)
  750.   if nvoices < MAX_NUM_VOICES then
  751.     --engine.start(id, getHz(x, y-1))
  752.     engine.start(note, getHzET(note))
  753.     start_screen_note(note)
  754.     nvoices = nvoices + 1
  755.   end
  756. end
  757.  
  758. function note_off(note, vel)
  759.   engine.stop(note)
  760.   stop_screen_note(note)
  761.   nvoices = nvoices - 1
  762. end
  763.  
  764.  
  765. function midi_event(data)
  766.   if #data == 0 then return end
  767.   local msg = midi.to_msg(data)
  768.  
  769.   -- Note off
  770.   if msg.type == "note_off" then
  771.     note_off(msg.note)
  772.  
  773.     -- Note on
  774.   elseif msg.type == "note_on" then
  775.     note_on(msg.note, msg.vel / 127)
  776. end
  777. end
  778. function cleanup()
  779.   stop_all_screen_notes()
  780.   pat:stop()
  781.   pat = nil
  782. end
  783.  
  784.  
  785.  
  786.  
  787. -- MIDI input
  788. local function midi_event(data)
  789.  
  790.   local msg = midi.to_msg(data)
  791.   local channel_param = params:get("midi_channel")
  792.  
  793.   if channel_param == 1 or (channel_param > 1 and msg.ch == channel_param - 1) then
  794.  
  795.     -- Note on
  796.     if msg.type == "note_on" then
  797.       note_on(msg.note, msg.vel / 127)
  798.  
  799.     -- Note off
  800.     elseif msg.type == "note_off" then
  801.       note_off(msg.note)
  802.  
  803.     -- Pitch bend
  804.     elseif msg.type == "pitchbend" then
  805.       local bend_st = (util.round(msg.val / 2)) / 8192 * 2 -1 -- Convert to -1 to 1
  806.       set_pitch_bend(bend_st * params:get("bend_range"))
  807.  
  808.     -- Pressure
  809.     elseif msg.type == "channel_pressure" or msg.type == "key_pressure" then
  810.       set_channel_pressure(msg.val / 127)
  811.  
  812.     end
  813.   end
  814. end
  815.  
  816.  
  817. -- Init
  818.  
  819. function init()
  820.  
  821.   screen.aa(1)
  822.  
  823.   midi_in_device = midi.connect(1)
  824.   midi_in_device.event = midi_event
  825.  
  826.   -- Add params
  827.  
  828.   params:add{type = "number", id = "midi_device", name = "MIDI Device", min = 1, max = 4, default = 1, action = function(value)
  829.     midi_in_device.event = nil
  830.     midi_in_device = midi.connect(value)
  831.     midi_in_device.event = midi_event
  832.   end}
  833.  
  834.   local channels = {"All"}
  835.   for i = 1, 16 do table.insert(channels, i) end
  836.   params:add{type = "option", id = "midi_channel", name = "MIDI Channel", options = channels}
  837.  
  838.   params:add{type = "number", id = "bend_range", name = "Pitch Bend Range", min = 1, max = 48, default = 2}
  839.  
  840.   params:add_separator()
  841.  
  842.   Passersby.add_params()
  843.  
  844.   -- Override param actions
  845.  
  846.   params:set_action("wave_shape", function(value)
  847.     engine.waveShape(value)
  848.     wave_shape.dirty = true
  849.   end)
  850.  
  851.   params:set_action("wave_folds", function(value)
  852.     engine.waveFolds(value)
  853.     wave_folds.dirty = true
  854.   end)
  855.  
  856.   params:set_action("fm_low_amount", function(value)
  857.     engine.fm1Amount(value)
  858.     fm1_amount.dirty = true
  859.   end)
  860.  
  861.   params:set_action("fm_high_amount", function(value)
  862.     engine.fm2Amount(value)
  863.     fm2_amount.dirty = true
  864.   end)
  865.  
  866.   params:set_action("env_type", function(value)
  867.     engine.envType(value - 1)
  868.     init_env_graph(value)
  869.     tab_titles[2][1] = params:string("env_type")
  870.     if value == 1 then
  871.       tab_titles[2][2] = "Reverb"
  872.     else
  873.       tab_titles[2][2] = "Peak/Reverb"
  874.     end
  875.     if pages.index == 2 then
  876.       tabs.titles = tab_titles[2]
  877.       update_tabs()
  878.       screen_dirty = true
  879.     end
  880.   end)
  881.  
  882.   params:set_action("attack", function(value)
  883.     engine.attack(value)
  884.     if pages.index == 2 then show_attack_status() end
  885.     attack.dirty = true
  886.   end)
  887.  
  888.   params:set_action("peak", function(value)
  889.     engine.peak(value)
  890.     if pages.index == 2 then show_peak_status() end
  891.     peak.dirty = true
  892.   end)
  893.  
  894.   params:set_action("decay", function(value)
  895.     engine.decay(value)
  896.     if pages.index == 2 then show_decay_status() end
  897.     decay.dirty = true
  898.   end)
  899.  
  900.   params:set_action("reverb_mix", function(value)
  901.     engine.reverbMix(value)
  902.     reverb_mix.dirty = true
  903.   end)
  904.  
  905.   params:set_action("lfo_shape", function(value)
  906.     engine.lfoShape(value - 1)
  907.     lfo_shape.dirty = true
  908.   end)
  909.  
  910.   params:set_action("lfo_freq", function(value)
  911.     engine.lfoFreq(value)
  912.     lfo_freq.dirty = true
  913.   end)
  914.  
  915.   params:set_action("lfo_to_freq_amount", function(value)
  916.     engine.lfoToFreqAmount(value)
  917.     lfo_destinations.dirty = true
  918.   end)
  919.  
  920.   params:set_action("lfo_to_wave_shape_amount", function(value)
  921.     engine.lfoToWaveShapeAmount(value)
  922.     lfo_destinations.dirty = true
  923.   end)
  924.  
  925.   params:set_action("lfo_to_wave_folds_amount", function(value)
  926.     engine.lfoToWaveFoldsAmount(value)
  927.     lfo_destinations.dirty = true
  928.   end)
  929.  
  930.   params:set_action("lfo_to_fm_low_amount", function(value)
  931.     engine.lfoToFm1Amount(value)
  932.     lfo_destinations.dirty = true
  933.   end)
  934.  
  935.   params:set_action("lfo_to_fm_high_amount", function(value)
  936.     engine.lfoToFm2Amount(value)
  937.     lfo_destinations.dirty = true
  938.   end)
  939.  
  940.   params:set_action("lfo_to_attack_amount", function(value)
  941.     engine.lfoToAttackAmount(value)
  942.     lfo_destinations.dirty = true
  943.   end)
  944.  
  945.   params:set_action("lfo_to_peak_amount", function(value)
  946.     engine.lfoToPeakAmount(value)
  947.     lfo_destinations.dirty = true
  948.   end)
  949.  
  950.   params:set_action("lfo_to_decay_amount", function(value)
  951.     engine.lfoToDecayAmount(value)
  952.     lfo_destinations.dirty = true
  953.   end)
  954.  
  955.   params:set_action("lfo_to_reverb_mix_amount", function(value)
  956.     engine.lfoToReverbMixAmount(value)
  957.     lfo_destinations.dirty = true
  958.   end)
  959.  
  960.   params:set_action("drift", function(value)
  961.     engine.drift(value)
  962.     drift.dirty = true
  963.   end)
  964.  
  965.   wave_shape.actual = params:get("wave_shape")
  966.   wave_folds.actual = params:get("wave_folds")
  967.   fm1_amount.actual = params:get("fm_low_amount")
  968.   fm2_amount.actual = params:get("fm_high_amount")
  969.   attack.actual = params:get("attack")
  970.   peak.actual = params:get("peak")
  971.   decay.actual = params:get("decay")
  972.   reverb_mix.actual = params:get("reverb_mix")
  973.  
  974.   -- tunnels
  975.   tn.init()
  976.   -- need to set to 0 here for some reason
  977.   for i=1, 4 do
  978.     softcut.level(i, 0)
  979.   end
  980.  
  981.   -- Init UI
  982.  
  983.   pages = UI.Pages.new(1, 5)
  984.   tab_titles[2][1] = params:string("env_type")
  985.   tabs = UI.Tabs.new(1, tab_titles[pages.index])
  986.   tunnelmodes_list = UI.ScrollingList.new(8, 8, 1, tunnelmodes)
  987.  
  988.   fm1_dial = UI.Dial.new(72, 19, 22, fm1_amount.actual * 100, 0, 100, 1)
  989.   fm2_dial = UI.Dial.new(97, 34, 22, fm2_amount.actual * 100, 0, 100, 1)
  990.  
  991.   reverb_slider = UI.Slider.new(102, 22, 3, 36, reverb_mix.actual, 0, 1, {0.5})
  992.  
  993.   lfo_destinations_list = UI.ScrollingList.new(71, 18, 1, {"Freq", "Shape", "Folds", "FM Low", "FM High", "Attack", "Peak", "Decay", "Reverb"})
  994.   lfo_destinations_list.num_visible = 4
  995.   lfo_destinations_list.num_above_selected = 0
  996.   lfo_destinations_list.active = false
  997.  
  998.   lfo_amounts_list = UI.ScrollingList.new(120, 18)
  999.   lfo_amounts_list.num_visible = 4
  1000.   lfo_amounts_list.num_above_selected = 0
  1001.   lfo_amounts_list.text_align = "right"
  1002.   lfo_amounts_list.active = false
  1003.   update_lfo_amounts_list()
  1004.  
  1005.   drift_dial = UI.Dial.new(85, 28, 22, params:get("drift") * 100, 0, 100, 1)
  1006.  
  1007.   -- Init graphs
  1008.  
  1009.   wave_graph = Graph.new(0, 2, "lin", -1, 1, "lin", nil, true, false)
  1010.   wave_graph:set_position_and_size(8, 22, 49, 36)
  1011.   wave_table = generate_wave_table(2, wave_graph:get_width() * SUB_SAMPLING)
  1012.   local wave_func = function(x)
  1013.     return generate_wave(util.linlin(0, 2, 1, wave_graph:get_width() * SUB_SAMPLING, x))
  1014.   end
  1015.   wave_graph:add_function(wave_func, SUB_SAMPLING)
  1016.  
  1017.   init_env_graph(params:get("env_type"))
  1018.  
  1019.   lfo_graph = Graph.new(0, 1, "lin", -1, 1, "lin", nil, true, false)
  1020.   lfo_graph:set_position_and_size(8, 18, 49, 36)
  1021.   lfo_graph:add_function(generate_lfo_wave, SUB_SAMPLING)
  1022.  
  1023.   env_status.text = ""
  1024.   env_status.x, env_status.y = 0, 0
  1025.   env_status_metro = metro.init()
  1026.   env_status_metro.event = function()
  1027.     env_status.text = ""
  1028.     screen_dirty = true
  1029.   end
  1030.  
  1031.   spring_path = generate_spring_path(10, 36, 5)
  1032.  
  1033.   randomize_dice()
  1034.  
  1035.   -- Init polls
  1036.  
  1037.   local wave_shape_poll = poll.set("waveShapeMod", function(value)
  1038.     if wave_shape.modu ~= value then
  1039.       wave_shape.modu = value
  1040.       wave_shape.dirty = true
  1041.     end
  1042.   end)
  1043.   wave_shape_poll:start()
  1044.  
  1045.   local wave_folds_poll = poll.set("waveFoldsMod", function(value)
  1046.     if wave_folds.modu ~= value then
  1047.       wave_folds.modu = value
  1048.       wave_folds.dirty = true
  1049.     end
  1050.   end)
  1051.   wave_folds_poll:start()
  1052.  
  1053.   local fm1_amount_poll = poll.set("fm1AmountMod", function(value)
  1054.     if fm1_amount.modu ~= value then
  1055.       fm1_amount.modu = value
  1056.       fm1_amount.dirty = true
  1057.     end
  1058.   end)
  1059.   fm1_amount_poll:start()
  1060.  
  1061.   local fm2_amount_poll = poll.set("fm2AmountMod", function(value)
  1062.     if fm2_amount.modu ~= value then
  1063.       fm2_amount.modu = value
  1064.       fm2_amount.dirty = true
  1065.     end
  1066.   end)
  1067.   fm2_amount_poll:start()
  1068.  
  1069.   local attack_poll = poll.set("attackMod", function(value)
  1070.     if attack.modu ~= value then
  1071.       attack.modu = value
  1072.       attack.dirty = true
  1073.     end
  1074.   end)
  1075.   attack_poll:start()
  1076.  
  1077.   local peak_poll = poll.set("peakMulMod", function(value)
  1078.     if peak.modu ~= value then
  1079.       peak.modu = value
  1080.       peak.dirty = true
  1081.     end
  1082.   end)
  1083.   peak_poll:start()
  1084.  
  1085.   local decay_poll = poll.set("decayMod", function(value)
  1086.     if decay.modu ~= value then
  1087.       decay.modu = value
  1088.       decay.dirty = true
  1089.     end
  1090.   end)
  1091.   decay_poll:start()
  1092.  
  1093.   local reverb_mix_poll = poll.set("reverbMixMod", function(value)
  1094.     if reverb_mix.modu ~= value then
  1095.       reverb_mix.modu = value
  1096.       reverb_mix.dirty = true
  1097.     end
  1098.   end)
  1099.   reverb_mix_poll:start()
  1100.  
  1101.   -- Start drawing to screen
  1102.   screen_refresh_metro = metro.init()
  1103.   screen_refresh_metro.event = function()
  1104.     update()
  1105.     if screen_dirty then
  1106.       screen_dirty = false
  1107.       redraw()
  1108.     end
  1109.   end
  1110.   screen_refresh_metro:start(1 / SCREEN_FRAMERATE)
  1111.  
  1112. end
  1113.  
  1114.  
  1115. -- Draw functions
  1116.  
  1117. local function rotate(x, y, center_x, center_y, angle_rads)
  1118.   local sin_a = math.sin(angle_rads)
  1119.   local cos_a = math.cos(angle_rads)
  1120.   x = x - center_x
  1121.   y = y - center_y
  1122.   return (x * cos_a - y * sin_a) + center_x, (x * sin_a + y * cos_a) + center_y
  1123. end
  1124.  
  1125. local function draw_input_indicator()
  1126.   screen.level(4)
  1127.   screen.move(0, 1)
  1128.   screen.line(5, 1)
  1129.   screen.line(2.5, 4)
  1130.   screen.close()
  1131.   screen.fill()
  1132. end
  1133.  
  1134. local function draw_background_rects()
  1135.   screen.level(1)
  1136.   screen.rect(8, 18, 49, 44)
  1137.   screen.fill()
  1138.   screen.rect(71, 18, 49, 44)
  1139.   screen.fill()
  1140. end
  1141.  
  1142. local function draw_spring(x, y, active)
  1143.   screen.move(x + spring_path[1].x + 0.5, y + spring_path[1].y + 0.5)
  1144.   for i = 2, #spring_path do
  1145.     screen.line(x + spring_path[i].x + 0.5, y + spring_path[i].y + 0.5)
  1146.   end
  1147.   if active then
  1148.     screen.level(15)
  1149.     screen.line_width(0.7)
  1150.   else
  1151.     screen.level(5)
  1152.   end
  1153.   screen.stroke()
  1154.   screen.line_width(1)
  1155. end
  1156.  
  1157. local function draw_die(x, y, rotation_rads, face)
  1158.   screen.level(15)
  1159.   local size = 9
  1160.   screen.move(rotate(x - size + 0.5, y - size + 0.5, x, y, rotation_rads))
  1161.   screen.line(rotate(x + size - 0.5, y - size + 0.5, x, y, rotation_rads))
  1162.   screen.line(rotate(x + size - 0.5, y + size - 0.5, x, y, rotation_rads))
  1163.   screen.line(rotate(x - size + 0.5, y + size - 0.5, x, y, rotation_rads))
  1164.   screen.close()
  1165.   screen.stroke()
  1166.  
  1167.   local dot_size = 1
  1168.   local dx, dy
  1169.   if face == 1 then
  1170.     dot_size = 1.5
  1171.     dx, dy = rotate(x, y, x, y, rotation_rads)
  1172.     screen.circle(dx, dy, dot_size)
  1173.     screen.fill()
  1174.   elseif face == 2 then
  1175.     dx, dy = rotate(x + 3, y - 3, x, y, rotation_rads)
  1176.     screen.circle(dx, dy, dot_size)
  1177.     screen.fill()
  1178.     dx, dy = rotate(x - 3, y + 3, x, y, rotation_rads)
  1179.     screen.circle(dx, dy, dot_size)
  1180.     screen.fill()
  1181.   elseif face == 3 then
  1182.     dx, dy = rotate(x + 4, y - 4, x, y, rotation_rads)
  1183.     screen.circle(dx, dy, dot_size)
  1184.     screen.fill()
  1185.     dx, dy = rotate(x, y, x, y, rotation_rads)
  1186.     screen.circle(dx, dy, dot_size)
  1187.     screen.fill()
  1188.     dx, dy = rotate(x - 4, y + 4, x, y, rotation_rads)
  1189.     screen.circle(dx, dy, dot_size)
  1190.     screen.fill()
  1191.   elseif face == 4 then
  1192.     dx, dy = rotate(x - 3, y - 3, x, y, rotation_rads)
  1193.     screen.circle(dx, dy, dot_size)
  1194.     screen.fill()
  1195.     dx, dy = rotate(x + 3, y - 3, x, y, rotation_rads)
  1196.     screen.circle(dx, dy, dot_size)
  1197.     screen.fill()
  1198.     dx, dy = rotate(x + 3, y + 3, x, y, rotation_rads)
  1199.     screen.circle(dx, dy, dot_size)
  1200.     screen.fill()
  1201.     dx, dy = rotate(x - 3, y + 3, x, y, rotation_rads)
  1202.     screen.circle(dx, dy, dot_size)
  1203.     screen.fill()
  1204.   elseif face == 5 then
  1205.     dx, dy = rotate(x, y, x, y, rotation_rads)
  1206.     screen.circle(dx, dy, dot_size)
  1207.     screen.fill()
  1208.     dx, dy = rotate(x - 4, y - 4, x, y, rotation_rads)
  1209.     screen.circle(dx, dy, dot_size)
  1210.     screen.fill()
  1211.     dx, dy = rotate(x + 4, y - 4, x, y, rotation_rads)
  1212.     screen.circle(dx, dy, dot_size)
  1213.     screen.fill()
  1214.     dx, dy = rotate(x + 4, y + 4, x, y, rotation_rads)
  1215.     screen.circle(dx, dy, dot_size)
  1216.     screen.fill()
  1217.     dx, dy = rotate(x - 4, y + 4, x, y, rotation_rads)
  1218.     screen.circle(dx, dy, dot_size)
  1219.     screen.fill()
  1220.   elseif face == 6 then
  1221.     dx, dy = rotate(x - 3, y - 4, x, y, rotation_rads)
  1222.     screen.circle(dx, dy, dot_size)
  1223.     screen.fill()
  1224.     dx, dy = rotate(x + 3, y - 4, x, y, rotation_rads)
  1225.     screen.circle(dx, dy, dot_size)
  1226.     screen.fill()
  1227.     dx, dy = rotate(x - 3, y, x, y, rotation_rads)
  1228.     screen.circle(dx, dy, dot_size)
  1229.     screen.fill()
  1230.     dx, dy = rotate(x + 3, y, x, y, rotation_rads)
  1231.     screen.circle(dx, dy, dot_size)
  1232.     screen.fill()
  1233.     dx, dy = rotate(x - 3, y + 4, x, y, rotation_rads)
  1234.     screen.circle(dx, dy, dot_size)
  1235.     screen.fill()
  1236.     dx, dy = rotate(x + 3, y + 4, x, y, rotation_rads)
  1237.     screen.circle(dx, dy, dot_size)
  1238.     screen.fill()
  1239.   end
  1240. end
  1241.  
  1242. local function draw_dice()
  1243.   draw_die(20, util.linlin(0, 1, 32, 17, dice_throw_progress), util.linlin(0, 1, dice[1].table_angle, dice[1].top_angle, dice_throw_progress), dice[1].face)
  1244.   draw_die(45, util.linlin(0, 1, 46, 61, dice_throw_progress), util.linlin(0, 1, dice[2].table_angle, dice[2].top_angle, dice_throw_progress), dice[2].face)
  1245. end
  1246.  
  1247. local function update_dice()
  1248.   if not dice_need_update then return end
  1249.  
  1250.   if dice_thrown then
  1251.     if dice_throw_progress < 0.05 then
  1252.       for i = 1, 2 do
  1253.         local direction = (dice[i].table_angle > 0) and 1 or -1
  1254.         dice[i].table_angle = dice[i].table_angle - (2 * math.pi * direction)
  1255.       end
  1256.       dice_thrown = false
  1257.     end
  1258.     set_dice_throw_vel(-0.08)
  1259.   else
  1260.     if dice_throw_progress > 0.9 then
  1261.       dice_thrown = true
  1262.       randomize_dice()
  1263.       Passersby.randomize_params()
  1264.       set_dice_throw_vel(-0.3)
  1265.     else
  1266.       set_dice_throw_vel(util.linlin(0, 1, -0.02, -0.03, dice_throw_progress))
  1267.     end
  1268.   end
  1269.  
  1270.   if dice_throw_progress <= 0 then
  1271.     dice_throw_vel = math.max(dice_throw_vel, 0)
  1272.   end
  1273.  
  1274.   dice_throw_progress = util.clamp(dice_throw_progress + dice_throw_vel, 0, 1)
  1275.  
  1276.   if pages.index == 4 then screen_dirty = true end
  1277.   if dice_throw_progress == 0 and not dice_thrown then dice_need_update = false end
  1278. end
  1279.  
  1280. function update()
  1281.  
  1282.   if pages.index == 1 then
  1283.     if wave_shape.dirty then update_wave_shape() end
  1284.     if wave_folds.dirty then update_wave_folds() end
  1285.     if fm1_amount.dirty then update_fm1_amount() end
  1286.     if fm2_amount.dirty then update_fm2_amount() end
  1287.   elseif pages.index == 2 then
  1288.     if attack.dirty then update_attack() end
  1289.     if peak.dirty then update_peak() end
  1290.     if decay.dirty then update_decay() end
  1291.     if reverb_mix.dirty then update_reverb_mix() end
  1292.   elseif pages.index == 3 then
  1293.     if lfo_shape.dirty then update_lfo_shape() end
  1294.     if lfo_freq.dirty then update_lfo_freq() end
  1295.     if lfo_destinations.dirty then update_lfo_destinations() end
  1296.   elseif pages.index == 4 then
  1297.     if drift.dirty then update_drift() end
  1298.   elseif pages.index == 5 then
  1299.     --update_tunnels()
  1300.   end
  1301.  
  1302.   update_dice()
  1303. end
  1304.  
  1305. function redraw()
  1306.   screen.clear()
  1307.  
  1308.   pages:redraw()
  1309.   tabs:redraw()
  1310.  
  1311.   if input_indicator_active then draw_input_indicator() end
  1312.  
  1313.   -- draw_background_rects()
  1314.  
  1315.   if pages.index == 1 then
  1316.  
  1317.     -- Wave
  1318.     wave_graph:redraw()
  1319.  
  1320.     -- FM
  1321.     fm1_dial:redraw()
  1322.     fm2_dial:redraw()
  1323.     screen.level(3)
  1324.     screen.move(83, 33)
  1325.     screen.text_center("L")
  1326.     screen.move(108, 48)
  1327.     screen.text_center("H")
  1328.     screen.fill() -- Prevents extra line
  1329.  
  1330.   elseif pages.index == 2 then
  1331.  
  1332.     -- Env
  1333.     env_graph:redraw()
  1334.     screen.level(3)
  1335.     screen.move(env_status.x, env_status.y)
  1336.     screen.text_right(env_status.text)
  1337.  
  1338.     -- Reverb
  1339.     screen.fill()
  1340.     draw_spring(82, 22, tabs.index == 2)
  1341.     reverb_slider:redraw()
  1342.  
  1343.   elseif pages.index == 3 then
  1344.  
  1345.     -- LFO
  1346.     lfo_graph:redraw()
  1347.     screen.level(3)
  1348.     screen.move(8, 62)
  1349.     screen.text(params:string("lfo_freq"))
  1350.  
  1351.     -- LFO Targets
  1352.     if tabs.index == 2 then screen.level(15) else screen.level(3) end
  1353.     lfo_destinations_list:redraw()
  1354.     lfo_amounts_list:redraw()
  1355.  
  1356.   elseif pages.index == 4 then
  1357.  
  1358.     -- Dice
  1359.     draw_dice()
  1360.  
  1361.     -- Drift
  1362.     screen.move(96, 23)
  1363.     screen.text_center("Drift")
  1364.     screen.fill()
  1365.     drift_dial:redraw()
  1366.  
  1367.   elseif pages.index == 5 then
  1368.     tunnelmodes_list:redraw()
  1369.   end
  1370.  
  1371.   screen.update()
  1372. end
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top