From 1d5ced6846784f2bd6c33911546a6b8dcb34c872 Mon Sep 17 00:00:00 2001 From: Zack Scholl Date: Sat, 28 Aug 2021 23:48:44 +0700 Subject: [PATCH 1/6] works --- lib/Engine_SimpleDelay.sc | 32 ++++++---- oooooo.lua | 131 ++++++++++++++++++-------------------- 2 files changed, 82 insertions(+), 81 deletions(-) diff --git a/lib/Engine_SimpleDelay.sc b/lib/Engine_SimpleDelay.sc index 8245b92..5032777 100644 --- a/lib/Engine_SimpleDelay.sc +++ b/lib/Engine_SimpleDelay.sc @@ -1,5 +1,5 @@ Engine_SimpleDelay : CroneEngine { - //var =4) then - -- print("incoming signal = "..val) - if val>params:get("rec thresh")/10000 then - tape_rec(i) - end - end - end - end - p_amp_in:start() - - -- and initiate recording on incoming on audio input 2 - p_amp_in2=poll.set("amp_in_r") - -- set period low when primed, default 1 second - p_amp_in2.time=1 - p_amp_in2.callback=function(val) - for i=1,6 do - if uS.recording[i]==1 and (params:get("input type")==2 or params:get("input type")>=4) then - -- print("incoming signal = "..val) - if val>params:get("rec thresh")/10000 then - tape_rec(i) - end - end - end - end - p_amp_in2:start() + -- -- and initiate recording on incoming audio on input 1 + -- p_amp_in=poll.set("amp_in_l") + -- -- set period low when primed, default 1 second + -- p_amp_in.time=1 + -- p_amp_in.callback=function(val) + -- for i=1,6 do + -- if uS.recording[i]==1 and (params:get("input type")==1 or params:get("input type")>=4) then + -- -- print("incoming signal = "..val) + -- if val>params:get("rec thresh")/10000 then + -- tape_rec(i) + -- end + -- end + -- end + -- end + -- p_amp_in:start() + + -- -- and initiate recording on incoming on audio input 2 + -- p_amp_in2=poll.set("amp_in_r") + -- -- set period low when primed, default 1 second + -- p_amp_in2.time=1 + -- p_amp_in2.callback=function(val) + -- for i=1,6 do + -- if uS.recording[i]==1 and (params:get("input type")==2 or params:get("input type")>=4) then + -- -- print("incoming signal = "..val) + -- if val>params:get("rec thresh")/10000 then + -- tape_rec(i) + -- end + -- end + -- end + -- end + -- p_amp_in2:start() for i=1,6 do params:set_action(i.."vol",function(x) uP[i].volUpdate=true end) @@ -785,14 +785,14 @@ function update_softcut_input_lag(on) uS.lagActivated=on if on then print("update_softcut_input_lag: activated") - engine.volume(1.0) + -- engine.volume(1.0) -- add lag to recording using a simple delay engine audio.level_monitor(0) -- turn off monitor to keep from hearing doubled audio audio.level_eng_cut(1) audio.level_adc_cut(0) else print("update_softcut_input_lag: deactivated") - engine.volume(0.0) + -- engine.volume(0.0) audio.level_monitor(1) -- turn on monitor audio.level_eng_cut(0) audio.level_adc_cut(1) @@ -1120,11 +1120,11 @@ function tape_stop_rec(i,change_loop) do return end end print("tape_stop_rec "..i) - if uS.recording[i]==1 and (params:get("input type")==1 or params:get("input type")>=4) then - p_amp_in.time=1 - elseif uS.recording[i]==1 and (params:get("input type")==2 or params:get("input type")>=4) then - p_amp_in2.time=1 - end + -- if uS.recording[i]==1 and (params:get("input type")==1 or params:get("input type")>=4) then + -- p_amp_in.time=1 + -- elseif uS.recording[i]==1 and (params:get("input type")==2 or params:get("input type")>=4) then + -- p_amp_in2.time=1 + -- end update_softcut_input_lag(false) still_armed=(uS.recording[i]==1) uS.recording[i]=0 @@ -1278,11 +1278,11 @@ function tape_arm_rec(i) uS.recordingLoopNum[i]=0 uS.timeSinceArming=clock.get_beats()*clock.get_beat_sec() -- monitor input - if uS.recording[i]==1 and (params:get("input type")==1 or params:get("input type")>=4) then - p_amp_in.time=uC.pampfast - elseif uS.recording[i]==1 and (params:get("input type")==2 or params:get("input type")>=4) then - p_amp_in2.time=uC.pampfast - end + -- if uS.recording[i]==1 and (params:get("input type")==1 or params:get("input type")>=4) then + -- p_amp_in.time=uC.pampfast + -- elseif uS.recording[i]==1 and (params:get("input type")==2 or params:get("input type")>=4) then + -- p_amp_in2.time=uC.pampfast + -- end end function tape_rec(i) @@ -1299,11 +1299,11 @@ function tape_rec(i) uP[i].volUpdate=true uP[i].isStopped=false end - if uS.recording[i]==1 and (params:get("input type")==1 or params:get("input type")>=4) then - p_amp_in.time=1 - elseif uS.recording[i]==1 and (params:get("input type")==2 or params:get("input type")>=4) then - p_amp_in2.time=1 - end + -- if uS.recording[i]==1 and (params:get("input type")==1 or params:get("input type")>=4) then + -- p_amp_in.time=1 + -- elseif uS.recording[i]==1 and (params:get("input type")==2 or params:get("input type")>=4) then + -- p_amp_in2.time=1 + -- end uS.recordingTime[i]=0 uS.recording[i]=2 -- recording is live params:set(i.."isempty",1) @@ -1955,19 +1955,14 @@ end -- -- -- -- osc -- -- --- function osc_in(path, args, from) --- if path == "onset" then --- cur_onset = args[2] --- print("onset "..cur_onset) --- if (cur_onset-uS.lastOnset) < 0.5 then --- do return end --- end --- print("onset detected") --- uS.lastOnset = cur_onset --- for i=1,6 do --- if uS.recording[i]==1 and (params:get("input type")==1 or params:get("input type")==4) then --- tape_rec(i) --- end --- end --- end --- end +function osc_in(path, args, from) + print(path) + if path == "onset" then + for i=1,6 do + if uS.recording[i]==1 and (params:get("input type")==1 or params:get("input type")>=4) then + -- print("incoming signal = "..val) + tape_rec(i) + end + end + end +end From 54b1ece396f83835ec07ff66f464eea32a66e89a Mon Sep 17 00:00:00 2001 From: Zack Scholl Date: Fri, 3 Sep 2021 05:50:08 +0700 Subject: [PATCH 2/6] -60 works! --- lib/Engine_SimpleDelay.sc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Engine_SimpleDelay.sc b/lib/Engine_SimpleDelay.sc index 5032777..2b52dcc 100644 --- a/lib/Engine_SimpleDelay.sc +++ b/lib/Engine_SimpleDelay.sc @@ -20,7 +20,7 @@ Engine_SimpleDelay : CroneEngine { // BufDelayC.ar([bufnum1,bufnum2], input, delayTime:0.03, mul:volume) // }.play(context.server); - synth = { arg threshold=(-36), volume=0.0; + synth = { arg threshold=(-60), volume=0.0; var input = Mix.new(SoundIn.ar([0, 1])); var onset = Trig.kr(Coyote.kr(input,fastLag:0.05,fastMul:0.9,thresh:threshold.dbamp,minDur:0.2)); SendTrig.kr(onset,0,1); @@ -52,4 +52,4 @@ Engine_SimpleDelay : CroneEngine { buffer1.free; buffer2.free; } -} \ No newline at end of file +} From 5d2c9c8a4fa61def06f1f8a3deda680a89275316 Mon Sep 17 00:00:00 2001 From: Zack Scholl Date: Fri, 3 Sep 2021 06:25:32 +0700 Subject: [PATCH 3/6] better defaults --- oooooo.lua | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/oooooo.lua b/oooooo.lua index bb3b359..70a1eb6 100644 --- a/oooooo.lua +++ b/oooooo.lua @@ -1,4 +1,4 @@ --- oooooo v1.8.1 +-- oooooo v1.9.0 -- 6 x digital tape loops -- -- llllllll.co/t/oooooo @@ -120,21 +120,22 @@ function init() params:add_option("use middy","use middy (restart req)",{"no","yes"},1) params:set_action("use middy",update_parameters) - params:add_group("recording",9) + params:add_group("recording",8) params:add_control("pre level","pre level",controlspec.new(0,1,"lin",0.01,1,"",0.01)) - params:add_control("rec level","rec level",controlspec.new(0,1,"lin",0.01,1,"",0.01)) - params:add_control("rec thresh","rec thresh",controlspec.new(1,1000,'exp',1,85,'amp/10k')) - params:set_action("rec thresh",update_parameters) - params:add_control("vol pinch","vol pinch",controlspec.new(0,1000,'lin',1,3,'ms',1/1000)) + params:add_control("rec level","rec level",controlspec.new(0,1,"lin",0.01,0.5,"",0.01)) + params:add_control("rec thresh","rec thresh",controlspec.new(-70,-32,'lin',1,-60,'dB')) + params:set_action("rec thresh",function (x) + engine.threshold(x) + update_parameters() + end) + params:add_control("vol pinch","vol pinch",controlspec.new(0,1000,'lin',1,0,'ms',1/1000)) params:set_action("vol pinch",function(x) for i=1,6 do - softcut.fade_time(i,x/1000+0.1) + softcut.fade_time(i,x/1000) softcut.recpre_slew_time(i,x/1000) end update_parameters() end) - params:add_option("catch transients w lag","catch transients w lag",{"no","yes"},1) - params:set_action("catch transients w lag",update_parameters) params:add_option("rec thru loops","rec thru loops",{"no","yes"},1) params:set_action("rec thru loops",update_parameters) params:add_control("stop rec after","stop rec after",controlspec.new(1,64,"lin",1,1,"loops")) @@ -360,7 +361,7 @@ function init() params_read_silent(DATA_DIR.."oooooo.pset") params:set('save_message',"") params:set('load_name',name_folder) - + init_loops(7) -- make data directory @@ -478,6 +479,12 @@ function init() -- simply setup oooooo grid oooooo_grid = grido:new() end + + -- bang some special parameters + params:delta("rec thresh",1) + params:delta("rec thresh",-1) + params:delta("vol pinch",1) + params:delta("vol pinch",-1) -- DEV comment this out -- params:set("scale_mode",9) -- params:set("choose mode",3) @@ -667,7 +674,6 @@ function activate_mode_default() ["pre level"]=1, ["rec level"]=1, ["rec thresh"]=85, - ["catch transients w lag"]=1, ["rec thru loops"]=1, ["stop rec after"]=1, ["input type"]=4, @@ -1272,17 +1278,8 @@ function tape_arm_rec(i) print("tape_arm_rec "..i) -- arm recording uS.recording[i]=1 - if params:get("catch transients w lag")==2 then - update_softcut_input_lag(true) - end uS.recordingLoopNum[i]=0 uS.timeSinceArming=clock.get_beats()*clock.get_beat_sec() - -- monitor input - -- if uS.recording[i]==1 and (params:get("input type")==1 or params:get("input type")>=4) then - -- p_amp_in.time=uC.pampfast - -- elseif uS.recording[i]==1 and (params:get("input type")==2 or params:get("input type")>=4) then - -- p_amp_in2.time=uC.pampfast - -- end end function tape_rec(i) From 42f9da8a9c7e35d42f286c2ebe8cb6cecc5e147e Mon Sep 17 00:00:00 2001 From: Zack Scholl Date: Fri, 3 Sep 2021 10:08:42 +0700 Subject: [PATCH 4/6] good --- oooooo.lua | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/oooooo.lua b/oooooo.lua index 70a1eb6..17650d3 100644 --- a/oooooo.lua +++ b/oooooo.lua @@ -128,7 +128,7 @@ function init() engine.threshold(x) update_parameters() end) - params:add_control("vol pinch","vol pinch",controlspec.new(0,1000,'lin',1,0,'ms',1/1000)) + params:add_control("vol pinch","vol pinch",controlspec.new(1,1000,'exp',0.1,150,'ms')) params:set_action("vol pinch",function(x) for i=1,6 do softcut.fade_time(i,x/1000) @@ -850,9 +850,9 @@ function update_timer() uS.recordingTime[i]=0 end elseif params:get("vol pinch") > 0 and uS.recordingTime[i]>=uP[i].loopLength/2 and previousRecordingTime=4) then -- p_amp_in2.time=1 -- end - update_softcut_input_lag(false) still_armed=(uS.recording[i]==1) uS.recording[i]=0 uS.recordingLoopNum[i]=0 @@ -1142,10 +1141,13 @@ function tape_stop_rec(i,change_loop) end uS.recordingTime[i]=0 -- slowly stop - softcut.rec_level(i,0) - softcut.pre_level(i,1) clock.run(function() -- allow pre level to go down + softcut.rec_level(i,0.5) + softcut.pre_level(i,1) + clock.sleep(params:get("vol pinch")/1000) + softcut.rec_level(i,0.0) + softcut.pre_level(i,1) clock.sleep(params:get("vol pinch")/1000) softcut.rec(i,0) -- DEBUGGING PURPOSES @@ -1290,24 +1292,24 @@ function tape_rec(i) do return end end print("tape_rec "..i) - if uP[i].isStopped then - softcut.play(i,1) - softcut.rate(i,uP[i].rate) - uP[i].volUpdate=true - uP[i].isStopped=false - end -- if uS.recording[i]==1 and (params:get("input type")==1 or params:get("input type")>=4) then -- p_amp_in.time=1 -- elseif uS.recording[i]==1 and (params:get("input type")==2 or params:get("input type")>=4) then -- p_amp_in2.time=1 -- end - uS.recordingTime[i]=0 uS.recording[i]=2 -- recording is live params:set(i.."isempty",1) -- start recording softcut.rec_level(i,params:get("rec level")) softcut.pre_level(i,params:get("pre level")) softcut.rec(i,1) + if uP[i].isStopped then + softcut.play(i,1) + softcut.rate(i,uP[i].rate) + uP[i].volUpdate=true + uP[i].isStopped=false + end + uS.recordingTime[i]=0 redraw() end From decf6b5d48ef0c0faf70ef0b119840aa435996f6 Mon Sep 17 00:00:00 2001 From: Zack Scholl Date: Fri, 3 Sep 2021 18:47:15 +0700 Subject: [PATCH 5/6] crossfade per loop --- oooooo.lua | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/oooooo.lua b/oooooo.lua index 17650d3..db4ce93 100644 --- a/oooooo.lua +++ b/oooooo.lua @@ -120,7 +120,7 @@ function init() params:add_option("use middy","use middy (restart req)",{"no","yes"},1) params:set_action("use middy",update_parameters) - params:add_group("recording",8) + params:add_group("recording",7) params:add_control("pre level","pre level",controlspec.new(0,1,"lin",0.01,1,"",0.01)) params:add_control("rec level","rec level",controlspec.new(0,1,"lin",0.01,0.5,"",0.01)) params:add_control("rec thresh","rec thresh",controlspec.new(-70,-32,'lin',1,-60,'dB')) @@ -128,14 +128,6 @@ function init() engine.threshold(x) update_parameters() end) - params:add_control("vol pinch","vol pinch",controlspec.new(1,1000,'exp',0.1,150,'ms')) - params:set_action("vol pinch",function(x) - for i=1,6 do - softcut.fade_time(i,x/1000) - softcut.recpre_slew_time(i,x/1000) - end - update_parameters() - end) params:add_option("rec thru loops","rec thru loops",{"no","yes"},1) params:set_action("rec thru loops",update_parameters) params:add_control("stop rec after","stop rec after",controlspec.new(1,64,"lin",1,1,"loops")) @@ -224,7 +216,7 @@ function init() filter_resonance=controlspec.new(0.05,1,'lin',0,1,'') filter_freq=controlspec.new(20,20000,'exp',0,20000,'Hz') for i=1,6 do - params:add_group("loop "..i,39) + params:add_group("loop "..i,40) -- id name min max default k units params:add_control(i.."start","start",controlspec.new(0,uC.loopMinMax[2],"lin",0.01,0,"s",0.01/uC.loopMinMax[2])) params:add_control(i.."start lfo amp","start lfo amp",controlspec.new(0,1,"lin",0.01,0.2,"",0.01)) @@ -281,6 +273,12 @@ function init() params:add_control(i.."filter lfo amp","filter lfo amp",controlspec.new(0,1,"lin",0.01,0.25,"",0.01)) params:add_control(i.."filter lfo period","filter lfo period",controlspec.new(0,60,"lin",0,0,"s",0.1/60)) params:add_control(i.."filter lfo offset","filter lfo offset",controlspec.new(0,60,"lin",0,0,"s",0.1/60)) + params:add_control(i.."crossfade","crossfade",controlspec.new(1,1000,'exp',0.1,150,'ms')) + params:set_action(i.."crossfade",function(x) + softcut.fade_time(i,x/1000) + softcut.recpre_slew_time(i,x/1000) + end) + params:add{type='binary',name="play trig",id=i..'play trig',behavior='momentary', action=function(v) if v==1 then @@ -483,8 +481,6 @@ function init() -- bang some special parameters params:delta("rec thresh",1) params:delta("rec thresh",-1) - params:delta("vol pinch",1) - params:delta("vol pinch",-1) -- DEV comment this out -- params:set("scale_mode",9) -- params:set("choose mode",3) @@ -593,7 +589,8 @@ function init_loops(j,ignore_pan) -- softcut.fade_time(i,params:get("vol pinch")/1000) softcut.level_slew_time(i,params:get("slew rate")) softcut.rate_slew_time(i,params:get("slew rate")) - softcut.recpre_slew_time(i,params:get("vol pinch")/1000) + softcut.recpre_slew_time(i,params:get(i.."crossfade")/1000) + softcut.fade_time(i,params:get(i.."crossfade")/1000) softcut.rec_level(i,params:get("rec level")) softcut.pre_level(i,params:get("pre level")) @@ -849,7 +846,7 @@ function update_timer() else uS.recordingTime[i]=0 end - elseif params:get("vol pinch") > 0 and uS.recordingTime[i]>=uP[i].loopLength/2 and previousRecordingTime 0 and uS.recordingTime[i]>=uP[i].loopLength/2 and previousRecordingTime Date: Fri, 3 Sep 2021 19:07:29 +0700 Subject: [PATCH 6/6] update readme --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index adedaa2..c90fbe6 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ digital tape loops x 6. ![Image](https://user-images.githubusercontent.com/6550035/91628872-c47b8c80-e978-11ea-9d07-df79ef337a0f.gif) +https://vimeo.com/590419704 + i call this script *"oooooo"* because it is composed of six loops. they are like digital tape loops - you can level, pan, speed, slow, shorten, lengthen, dub, overdub, destroy any loop at any time. i was inspired to make this after seeing tape loops circulating (pun sorta intended) all over the place. i like the idea of having multiple independent different loops, with different sizes, played on a different tape players with different eccentricities. i don't have any cassette tapes but i have norns so i wrote this script to try to make digital tape loops. @@ -50,7 +52,7 @@ all parameters are available via the global menu. - in tape mode, press K1+K3 to prime recording. when primed, recording will automatically begin when incoming audio rises above a threshold. the recording threshold can be set by global parameter "`recording -> rec thresh`". - in tape mode, you can force recording by hitting K1+K3 a second time. - recording stops after traversing the whole loop. you can stop it earlier with K2 or K3 (in tape mode) and that will shrink the loop to that point. you can set recording to continue to the next loop by setting the global parameter "`recording -> rec thru loops`" to `yes`. -- by default, volume in "pinched" when starting/stopping recording to avoid pops from discontinuous signals. you can lower/raise the pinching by adjusting the global parameter "`vol pinch`". +- by default, loops will be recorded with a crossfade for gapless playback. if you are recording something with initial transients (like drums), I recommend reducing the crossfade (`loop X -> crossfade`) to 1 ms. - to record a loop over and over, infinitely, change `recording -> stop rec after` to its max value. **quick menu:** @@ -62,6 +64,7 @@ all parameters are available via the global menu. **A loop:** +- the "A" loop is found by turning E1 all the way to the right. - "A" loop can control all loops. the tape mode works as before, but affects all loops. - the quick menu differs from loops but is also activated by K2 or K3, and modulated with E3 @@ -86,11 +89,6 @@ all parameters are available via the global menu.

Demo of playing

-## my other norns - -- [barcode](https://github.com/schollz/barcode): replays a buffer six times, at different levels & pans & rates & positions, modulated by lfos on every parameter. -- [blndr](https://github.com/schollz/blndr): a quantized delay with time morphing -- [clcks](https://github.com/schollz/clcks): a tempo-locked repeater for monome norns ## license