Last active
January 11, 2022 01:14
-
-
Save ypxk/db3083372935300f3c093de81e7a1e1d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- lofi OB4 | |
-- holds the input in softcut in case you need it | |
-- enc 2 = scrub buffer | |
-- key 2 = rewind?? | |
-- key 3 = jump to real time | |
-- arc 1 = scrub buffer | |
-- arc 2 = not interactive, graphics only | |
rate = 1 --longer values increase buffer but cost fidelity | |
local live_playback = 0 | |
local tape_position = 0 | |
local display_tape_position = 0 | |
local buffer_length = 340 | |
local scrub_resolution = .1 * rate | |
local overwriting = false | |
local rewinding= false | |
local relative_buffer_start | |
local start_time = util.time() | |
local live = true | |
local state_change=false | |
local initital_monitor_level | |
local initital_reverb_onoff | |
local initital_compressor_onoff | |
local ar = arc.connect() | |
local arcDirty = true | |
local tau = math.pi * 2 | |
local framerate = 20 | |
function update_positions(i,pos) | |
--if the buffer runs long enough to loop we want to be able to rewind into the previous buffer up to tape head | |
if not overwriting then | |
buffer_check = (util.time() - start_time) | |
if buffer_check>=buffer_length/rate then | |
overwriting= true | |
end | |
end | |
if i==1 then | |
live_playback=(pos) | |
end | |
if i==3 and pos > live_playback and not overwriting then | |
if rewinding then | |
tape_position = 0 | |
rewinding=false | |
for i=3,4 do softcut.rate(i,rate) end | |
else | |
tape_position = live_playback - .001 | |
end | |
end | |
--logic for what voices to hear | |
if live then | |
tape_position = live_playback - .001 --untested belief that this address crunchiness | |
display_tape_position = live_playback | |
params:set('monitor_level',0) | |
for x=3,4 do softcut.level(x,0.0) end | |
elseif not live then | |
if i==3 then | |
display_tape_position = pos | |
tape_position = pos | |
if rewinding then tape_position = pos end | |
end | |
for x=3,4 do softcut.level(x,1.0) end | |
params:set('monitor_level', -math.huge) | |
end | |
redraw() | |
end | |
function scrubber(d) | |
--ban negative numbers | |
if tape_position < 0 then | |
if overwriting then | |
tape_position = buffer_length | |
else | |
tape_position = 0.1 | |
end | |
--ban portions of the loop not yet used | |
elseif tape_position > live_playback then | |
if overwriting then | |
if tape_position > live_playback then | |
tape_position = tape_position + d*scrub_resolution | |
end | |
elseif not overwriting then | |
live = true | |
tape_position = live_playback - .002 | |
end | |
--normal use within buffer | |
elseif tape_position >= 0 and tape_position < live_playback then | |
tape_position = tape_position + d*scrub_resolution | |
end | |
--updates position | |
for i=3,4 do | |
softcut.position(i,tape_position) | |
end | |
end | |
function rewinder() | |
if rewinding then | |
--ban negative numbers | |
if tape_position < 0 then | |
if overwriting then | |
tape_position = buffer_length | |
for i=3,4 do softcut.rate(i,-1.5*rate) end | |
else | |
tape_position = 0 | |
for i=3,4 do softcut.rate(i,1*rate) end | |
rewinding = false | |
end | |
--ban portions of the loop not yet used | |
elseif tape_position > live_playback and not overwriting then | |
live = true | |
tape_position = live_playback - .002 | |
rewinding = false | |
elseif tape_position > 0 and tape_position < live_playback then | |
for i=3,4 do softcut.rate(i,-1.5*rate) end | |
end | |
end | |
if not rewinding then | |
for i=3,4 do softcut.rate(i,rate) end | |
end | |
end | |
function enc(n,d) | |
if n==1 then | |
elseif n==2 then | |
if live then | |
tape_position = display_tape_position | |
live = false | |
scrubber(d) | |
elseif not live then | |
scrubber(d) | |
end | |
elseif n==3 then | |
end | |
end | |
function ar.delta(n, delta) | |
if n==1 then | |
if live then | |
tape_position = display_tape_position | |
live = false | |
scrubber(delta/10) | |
elseif not live then | |
scrubber(delta/10) | |
end | |
end | |
end | |
function key(n,z) | |
relative_buffer_start= util.time()-start_time | |
if n==1 then | |
elseif n==2 then | |
tape_position = display_tape_position-1 | |
if z==1 then | |
if live then | |
live = false | |
end | |
rewinding = true | |
rewinder() | |
elseif z==0 then | |
rewinding = false | |
rewinder() | |
end | |
elseif n==3 then | |
if z==1 then | |
if not live then | |
live = true | |
tape_position = live_playback | |
for i=3,4 do softcut.position(i,tape_position) end | |
end | |
end | |
end | |
end | |
function init() | |
local panning = {-1,1,-1,1} | |
-- send audio input to softcut input | |
audio.level_adc_cut(1) | |
-- Turn off the built-in monitoring, reverb, etc. | |
initital_monitor_level = params:get('monitor_level') | |
params:set('monitor_level', -math.huge) | |
initital_reverb_onoff = params:get('reverb') | |
params:set('reverb', 1) -- 1 is OFF | |
initital_compressor_onoff = params:get('compressor') | |
params:set('compressor', 1) -- 1 is OFF | |
--recordhead | |
for i=1,2 do | |
softcut.enable(i,1) | |
softcut.buffer(i,i) | |
softcut.level(i,1.0) | |
softcut.pan(i,panning[i]) | |
softcut.loop(i,1) | |
softcut.loop_start(i,0) | |
softcut.loop_end(i,buffer_length) | |
softcut.position(i,0) | |
softcut.rate(i,rate) | |
softcut.level_input_cut(i,i,1.0) | |
softcut.level_input_cut(i,i,1.0) | |
softcut.rec_level(i,1) | |
softcut.pre_level(i,0) | |
softcut.rec(i,1) | |
softcut.phase_quant(i,scrub_resolution) | |
end | |
--playhead | |
for i=3,4 do | |
softcut.enable(i,1) | |
softcut.buffer(i,i-2) | |
softcut.pan(i,panning[i]) | |
softcut.loop(i,1) | |
softcut.loop_start(i,0) | |
softcut.loop_end(i,buffer_length) | |
softcut.position(i,0) | |
softcut.rate(i,rate) | |
softcut.pre_level(i,0) | |
softcut.rec(i,0) | |
softcut.phase_quant(i,scrub_resolution) | |
softcut.level(i,0.0) | |
end | |
--polls | |
softcut.event_phase(update_positions) | |
softcut.poll_start_phase() | |
local arc_redraw_metro = metro.init() | |
arc_redraw_metro.event = function() | |
arc_redraw() | |
redraw() | |
end | |
arc_redraw_metro:start(1 /framerate) | |
for i = 3,4 do softcut.play(i,1) end | |
end | |
function arc_redraw() | |
local brightness | |
local tape_led = tape_position/buffer_length | |
local live_led = live_playback/buffer_length | |
ar:all(0) | |
if not overwriting then | |
ar:segment(2,0,live_led*tau,8) | |
ar:led(2,math.ceil(live_led*64),15) | |
ar:led(2,math.ceil(tape_led*64),15) | |
else | |
for i=1,64 do ar:led(2,i,8) end | |
ar:segment(2,tau*live_led+.2,live_led*tau,13) | |
end | |
ar:segment(1,tape_led*tau,tau*tape_led+.2,15) | |
ar:refresh() | |
end | |
function redraw() | |
screen.clear() | |
screen.move(0,20) | |
screen.font_size(25) | |
screen.font_face(8) | |
if live then | |
screen.text('LIVE') | |
else | |
screen.text('TAPE') | |
end | |
screen.font_face(1) | |
screen.font_size(8) | |
screen.move(128,25) | |
screen.text_right('(' .. string.format("%.2f",(buffer_length/rate)/60) ..' minutes)') | |
screen.font_size(8) | |
screen.move(5,35) | |
screen.text('SIZE:') | |
screen.move(128,35) | |
screen.text_right(string.format("%.2f",(buffer_length/rate)).. ' seconds') | |
screen.move(5,45) | |
screen.text("LIVE: ") | |
screen.move(128,45) | |
screen.text_right(string.format("%.2f",live_playback/rate) .. ' seconds') | |
screen.move(5,55) | |
screen.text("TAPE: ") | |
screen.move(128,55) | |
screen.text_right(string.format("%.2f",display_tape_position/rate).. ' seconds') | |
screen.update() | |
end | |
function cleanup() | |
-- Put user's audio settings back where they were | |
params:set('monitor_level', initital_monitor_level) | |
params:set('reverb', initital_reverb_onoff) | |
params:set('compressor', initital_compressor_onoff) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment