Browse Source

Attempts at making a multi-track looper for Norns. Mostly unsuccessful.

master
suroh 2 years ago
parent
commit
47c9497d1e
5 changed files with 651 additions and 25 deletions
  1. +25
    -25
      norns/looper.lua
  2. +141
    -0
      norns/softCutter/2bufLoop.lua
  3. +195
    -0
      norns/softCutter/2trackLooper.lua
  4. +187
    -0
      norns/softCutter/sepBuffLooper.lua
  5. +103
    -0
      norns/softCutter/simpleLoop.lua

+ 25
- 25
norns/looper.lua View File

@ -1,11 +1,11 @@
-- LOOPS
-- Little looper for
-- a Pickles Prodution.
--
-- A butchered version of
-- cranes by dndrks with
-- a hacked reverse.
--
-- ...
-- TODO:
-- FIX: Glitchy Playback with reverse
engine.name = 'SoftCut'
@ -19,13 +19,13 @@ end
rec = 0
function init()
engine.loop_start(1,0)
engine.loop_start(1,5)
engine.loop_end(1,60)
engine.loop_on(1,1)
engine.pre(1,1)
engine.amp(1,1)
engine.rec_on(1,1)
engine.rec(1,1)
engine.rec(1,0)
engine.adc_rec(1,1,1)
engine.adc_rec(1,2,1)
engine.play_dac(1,1,1)
@ -42,17 +42,17 @@ function init()
engine.amp(2, 1)
engine.rec_on(2, 1)
engine.loop_on(2, 1)
engine.loop_start(2, 0)
engine.loop_start(2, 5)
engine.loop_end(2, 60)
engine.reset(2)
engine.rate(2,1)
engine.rate_lag(2,0.35)
engine.rate_lag(2,0.6)
engine.clear()
engine.stop(1)
engine.stop(2)
params:add_control("speed_voice_1","speed voice 1",controlspec.new(0,2,'lin',0,1,''))
params:add_control("speed_voice_1","speed voice 1",controlspec.new(-2,2,'lin',0,1,''))
params:set_action("speed_voice_1", function(x) engine.rate(1, x) end)
params:set("speed_voice_1", 1.0)
params:add_control("speed_voice_2","speed voice 2",controlspec.new(-2,2,'lin',0,1,''))
@ -81,12 +81,12 @@ function clear_all()
engine.stop(2)
engine.clear()
ray = speed_voice_1
engine.loop_start(1,0)
engine.loop_end(1,60)
engine.loop_start(2,0)
engine.loop_end(2,60)
start_point_1 = 0
start_point_2 = 0
engine.loop_start(1,5)
engine.loop_end(1,65)
engine.loop_start(2,5)
engine.loop_end(2,65)
start_point_1 = 5
start_point_2 = 5
end_point_1 = 60
clear = 1
rec_time = 0
@ -102,8 +102,8 @@ end
-- do any of these need to be 'local'?
down_time = 0
hold_time = 0
start_point_1 = 0
start_point_2 = 0
start_point_1 = 5
start_point_2 = 5
end_point_1 = 60
end_point_2 = 60
rec_toggle = 0
@ -122,7 +122,7 @@ function key(n,z)
if rec % 2 == 1 and clear == 1 then
engine.clear()
engine.reset(1)
engine.rec_on(1,1)
engine.rec(1,1)
rec_toggle = 1
engine.start(1)
engine.start(2)
@ -133,27 +133,27 @@ function key(n,z)
elseif rec % 2 == 0 and clear == 1 then
clear = 0
engine.reset(1)
engine.rec_on(1,0)
engine.rec(1,0)
rec_toggle = 0
counter:stop()
print("loop length: "..rec_time)
end_point_1 = rec_time
end_point_2 = end_point_1
engine.loop_end(1,end_point_1)
engine.loop_end(2,end_point_1)
engine.loop_end(1,end_point_1 + 5)
engine.loop_end(2,end_point_1 + 5)
redraw()
rec_time = 0
end
-- if the buffer is NOT clear and key 2 is pressed:
-- overwrite/overdub behavior will enable
if rec % 2 == 1 and clear == 0 then
engine.rec_on(1,1)
engine.rec(1,1)
rec_toggle = 1
redraw()
-- if the buffer is NOT clear and key 2 is pressed again:
-- overwrite/overdub behavior will disable
elseif rec % 2 == 0 and clear == 0 then
engine.rec_on(1,0)
engine.rec(1,0)
rec_toggle = 0
redraw()
end
@ -203,7 +203,7 @@ function enc(n,d)
-- encoder 3: voice 1's loop end point
if n == 3 and KEY1_hold == false then
end_point_1 = util.clamp((end_point_1 + d/100),0.0,60.0)
print("voice 1 loop end "..end_point_1)
print("voice 1 loop end "..end_point_1 + 5)
engine.loop_end(1,end_point_1)
redraw()
@ -216,7 +216,7 @@ function enc(n,d)
elseif n == 3 and KEY1_hold == true then
end_point_2 = util.clamp((end_point_2 + d/100),0.0,60.0)
print("voice 2 loop end "..end_point_2)
print("voice 2 loop end "..end_point_2 + 5)
engine.loop_end(2,end_point_2)
redraw()

+ 141
- 0
norns/softCutter/2bufLoop.lua View File

@ -0,0 +1,141 @@
-- 2bufLooper
--
-- a 2 buffer looper
-- putting the rec buff
-- into a play buff.
--
-- ADC1 --> BuffRec
-- BuffRec --> BuffPly
-- BuffPly --> DAC1+2
--
-- Buffers (for now) have
-- set duration.
--
engine.name = 'SoftCut'
-- track recording state
rec = 0
function init()
print("init")
-- BuffRec
-- loop_**(buff, val)
engine.loop_start(1,5)
engine.loop_end(1,10)
engine.loop_on(1,1)
-- preAmp(input/buff, amp)
engine.pre(1,1)
engine.amp(1,1)
-- rec_on(buffer, amp)
engine.rec_on(1,1)
engine.rec(1,1)
-- adc_rec(inChannel, buffer, amplitude)
engine.adc_rec(1,1,1)
-- recordRate
engine.rate(1,1)
engine.rate_lag(1,0.6)
-- cleanup(?)
engine.reset(1)
-- BuffPly
-- play_rec(srcBuff, destBuff, amp)
engine.play_rec(1, 2, 1)
-- loop_**(buff, val)
engine.loop_start(2,5)
engine.loop_end(2,10)
engine.loop_on(2,1)
-- preAmp(input/buff, amp)
engine.pre(2,1)
engine.amp(2,1)
-- rec_on(buffer, amp)
engine.rec_on(2,1)
engine.rec(2,0)
-- recordRate
engine.rate(2,1)
engine.rate_lag(2,0)
-- out to DAC
-- plac_dac(buffer, channel, amp)
engine.play_dac(2,1,1)
engine.play_dac(2,2,1)
-- cleanup(?)
engine.reset(2)
-- stop engines
engine.clear()
engine.stop(1)
engine.stop(2)
-- PARAMETERS
params:add_control("recBufRate","rec.Buffer speed",controlspec.new(0,2,'lin',0,1,''))
params:set_action("recBufRate", function(x) engine.rate(1, x) end)
params:set("recBufRate", 1.0)
params:add_control("plyBufRate","ply.Buffer speed",controlspec.new(-2,2,'lin',0,1,''))
params:set_action("plyBufRate", function(x) engine.rate(2, x) end)
params:set("plyBufRate", 1.0)
end
rec_toggle = 0
clear = 1
function key(n,z)
--KEY 2
if n == 2 and z == 1 then
rec = rec + 1
if rec % 2 == 1 and clear == 1 then
rec_toggle = 1
engine.clear()
engine.rec_on(1,1)
engine.start(1)
engine.start(2)
redraw()
elseif rec % 2 == 0 and clear == 1 then
rec_toggle = 0
clear = 0
engine.rec_on(1,0)
engine.stop(1)
redraw()
end
-- if buffer1 is NOT clear
if rec % 2 == 1 and clear == 0 then
engine.start(1)
engine.rec_on(1,1)
rec_toggle = 1
redraw()
elseif rec % 2 == 0 and clear == 0 then
engine.stop(1)
engine.rec_on(1,0)
rec_toggle = 0
redraw()
end
end
end
function redraw()
screen.clear()
screen.level(15)
-- recording
screen.move(112, 60)
if rec_toggle == 1 then
screen.text('rec1')
end
screen.update()
end

+ 195
- 0
norns/softCutter/2trackLooper.lua View File

@ -0,0 +1,195 @@
-- 2trackLooper
--
-- an 2 track independent looper
-- with speed manipulation.
--
-- Based on cranes by dndrks.
--
-- ...
engine.name = "SoftCut"
-- track recording state
rec_1 = 0
rec_2 = 0
clear = 1
start_point_1 = 0
start_point_2 = 0
end_point_1 = 60
end_point_2 = 60
-- counting ms between key 2 taps
-- sets loop length
function count()
rec_time = rec_time + 0.01
end
function init()
print("init")
-- BUFFER 1
-- Loop Settings
engine.loop_start(1, 0)
engine.loop_end(1, 60)
engine.loop_on(1, 1)
-- input settings
engine.pre(1, 1)
engine.amp(1, 1)
engine.adc_rec(1, 1, 1)
engine.rec_on(1, 1)
engine.rec(1, 0)
engine.rate(1, 1)
engine.rate_lag(1, 0.2)
engine.reset(1)
-- BUFFER 2
-- Loop Settings
engine.loop_start(2, 0)
engine.loop_end(2, 60)
engine.loop_on(2, 1)
-- input settings
engine.pre(2, 1)
engine.amp(2, 1)
engine.adc_rec(2, 2, 1)
engine.rec_on(2, 1)
engine.rec(2, 0)
engine.rate(2, 1)
engine.rate_lag(2, 0.2)
engine.reset(2)
-- output settings
engine.play_dac(1, 1, 1)
engine.play_dac(2, 2, 1)
-- resets
engine.clear()
engine.stop(1)
engine.stop(2)
params:add_control("speed_voice_1", "speed voice 1", controlspec.new(-2, 2, 'lin', 0, 1, ''))
params:set_action("speed_voice_1", function(x) engine.rate(1, x) end)
params:set("speed_voice_1", 1.0)
params:add_control("speed_voice_2", "speed voice 2", controlspec.new(-2, 2, 'lin', 0, 1, ''))
params:set_action("speed_voice_2", function(x) engine.rate(2, x) end)
params:set("speed_voice_2", 1.0)
counter = metro.alloc(count, 0.01, - 1)
rec_time = 0
KEY3_hold = false
KEY1_hold = false
end
function key(n, z)
--KEY 2
if n == 2 and z == 1 and KEY1_hold == false then
rec_1 = rec_1 + 1
if rec_1 % 2 == 1 and clear == 1 then
print("channel 1 init record start")
engine.clear()
engine.reset(1)
engine.reset(2)
engine.rec(1, 1)
engine.start(1)
redraw()
counter:start()
elseif rec_1 % 2 == 0 and clear == 1 then
print("channel 1 init record stop")
clear = 0
engine.reset(1)
engine.reset(2)
engine.rec(1, 0)
counter:stop()
print("loop length: "..rec_time)
end_point_1 = rec_time
engine.loop_end(1, end_point_1)
engine.loop_end(2, end_point_1)
redraw()
end
-- if buffer1 is NOT clear
if rec_1 % 2 == 1 and clear == 0 then
print("channel 1 overdub start")
engine.rec(1, 1)
redraw()
elseif rec_1 % 2 == 0 and clear == 0 then
print("channel 1 overdub stop")
engine.rec(1, 0)
redraw()
end
elseif n == 2 and z == 1 and KEY1_hold == true then
rec_2 = rec_2 + 1
-- if either buffer is clear
if rec_2 % 2 == 1 and clear == 1 then
print("channel 2 init record start")
engine.clear()
engine.reset(1)
engine.reset(2)
engine.rec(2, 1)
engine.start(2)
redraw()
counter:start()
elseif rec_2 % 2 == 0 and clear == 1 then
print("channel 2 init record stop")
clear = 0
engine.reset(1)
engine.reset(2)
engine.rec(2, 0)
counter:stop()
print("loop length: "..rec_time)
end_point_1 = rec_time
engine.loop_end(1, end_point_1)
engine.loop_end(2, end_point_1)
redraw()
end
-- if buffer2 is NOT clear
if rec_2 % 2 == 1 and clear == 0 then
print("channel 2 overdub start")
engine.rec(2, 1)
redraw()
elseif rec_2 % 2 == 0 and clear == 0 then
print("channel 2 overdub stop")
engine.rec(2, 0)
redraw()
end
end
if n == 1 and z == 1 then
KEY1_hold = true
redraw()
elseif n == 1 and z == 0 then
KEY1_hold = false
redraw()
end
end
function redraw()
screen.clear()
screen.level(15)
screen.move(2, 10)
if KEY1_hold == true then
screen.text("^")
end
-- loop length
-- show per voice settings
screen.move(0, 60)
screen.text("length: "..math.ceil(end_point_1 * (10^2)) / (10^2))
-- recording
screen.move(110, 50)
if rec_1 % 2 == 1 then
screen.text('rec1')
end
screen.move(110, 60)
if rec_2 % 2 == 1 then
screen.text('rec2')
end
screen.update()
end

+ 187
- 0
norns/softCutter/sepBuffLooper.lua View File

@ -0,0 +1,187 @@
-- 2bufLooper
--
-- a 2 buffer looper
-- putting the rec buff
-- into a play buff.
--
-- ADC1 --> BuffRec
-- BuffRec --> BuffPly
-- BuffPly --> DAC1+2
engine.name = 'SoftCut'
-- counting ms between key 2 taps
-- sets loop length
function count()
rec_time = rec_time + 0.01
end
-- track recording state
rec = 0
clear = 1
start_point_1 = 0
start_point_2 = 0
end_point_1 = 60
end_point_2 = 60
function init()
print("init")
-- BuffRec
-- loop_**(buff, val)
engine.loop_start(1, 0)
engine.loop_end(1, 60)
engine.loop_on(1, 1)
-- preAmp(input/buff, amp)
engine.pre(1, 1)
engine.amp(1, 1)
-- rec_on(buffer, amp)
engine.rec_on(1, 1)
engine.rec(1, 1)
-- adc_rec(inChannel, buffer, amplitude)
engine.adc_rec(1, 1, 1)
-- recordRate
engine.rate(1, 1)
engine.rate_lag(1, 0.2)
-- cleanup(?)
engine.reset(1)
-- BuffPly1
-- play_rec(srcBuff, destBuff, amp)
engine.play_rec(1, 2, 1)
-- loop_**(buff, val)
engine.loop_start(2, 0)
engine.loop_end(2, 60)
engine.loop_on(2, 1)
-- preAmp(input/buff, amp)
engine.pre(2, 1)
engine.amp(2, 1)
-- rec_on(buffer, amp)
engine.rec_on(2, 1)
engine.rec(2, 0)
-- recordRate
engine.rate(2, 1)
engine.rate_lag(2, 0.2)
-- out to DAC
-- plac_dac(buffer, channel, amp)
engine.play_dac(2, 1, 1)
engine.play_dac(2, 2, 1)
-- cleanup(?)
engine.reset(2)
-- BuffPly2
-- play_rec(srcBuff, destBuff, amp)
engine.play_rec(2, 3, 1)
-- loop_**(buff, val)
engine.loop_start(3, 0)
engine.loop_end(3, 60)
engine.loop_on(3, 1)
-- preAmp(input/buff, amp)
engine.pre(3, 1)
engine.amp(3, 1)
-- rec_on(buffer, amp)
engine.rec_on(3, 1)
engine.rec(3, 0)
-- recordRate
engine.rate(3, 1)
engine.rate_lag(3, 0.2)
-- out to DAC
-- plac_dac(buffer, channel, amp)
engine.play_dac(2, 1, 1)
engine.play_dac(3, 2, 1)
-- cleanup(?)
engine.reset(3)
-- stop engines
engine.clear()
engine.stop(1)
engine.stop(2)
engine.stop(3)
-- PARAMETERS
params:add_control("recBufRate", "rec.Buffer speed", controlspec.new(0, 2, 'lin', 0, 1, ''))
params:set_action("recBufRate", function(x) engine.rate(1, x) end)
params:set("recBufRate", 1.0)
params:add_control("plyBufRate1", "1.Buffer speed", controlspec.new(-2, 2, 'lin', 0, 1, ''))
params:set_action("plyBufRate1", function(x) engine.rate(2, x) end)
params:set("plyBufRate1", 1.0)
params:add_control("plyBufRate2", "2.Buffer speed", controlspec.new(-2, 2, 'lin', 0, 1, ''))
params:set_action("plyBufRate2", function(x) engine.rate(3, x) end)
params:set("plyBufRate2", 1.0)
counter = metro.alloc(count, 0.01, - 1)
rec_time = 0
end
function key(n,z)
--KEY 2
if n == 2 and z == 1 then
rec = rec + 1
if rec % 2 == 1 and clear == 1 then
engine.clear()
engine.rec(1,1)
engine.start(1)
engine.start(2)
engine.start(3)
redraw()
counter:start()
elseif rec % 2 == 0 and clear == 1 then
clear = 0
engine.rec_on(1,0)
engine.stop(1)
redraw()
counter:stop()
print("loop length: "..rec_time)
end_point_1 = rec_time
engine.loop_end(1, end_point_1)
engine.loop_end(2, end_point_1)
engine.loop_end(3, end_point_1)
end
-- if buffer1 is NOT clear
if rec % 2 == 1 and clear == 0 then
engine.start(1)
engine.rec_on(1,1)
redraw()
elseif rec % 2 == 0 and clear == 0 then
engine.stop(1)
engine.rec_on(1,0)
redraw()
end
end
end
function redraw()
screen.clear()
screen.level(15)
-- loop length
screen.move(0, 60)
screen.text("length: "..math.ceil(end_point_1 * (10^2)) / (10^2))
-- recording
screen.move(112, 60)
if rec % 2 == 1 then
screen.text('rec1')
end
screen.update()
end

+ 103
- 0
norns/softCutter/simpleLoop.lua View File

@ -0,0 +1,103 @@
-- simpleLooper
--
-- a simple looper to
-- decipher how the
-- softCut engine works.
--
-- ADC1 --> Buffer1 --> DAC
--
-- Buffer1 (for now) has
-- set duration.
--
engine.name = 'SoftCut'
-- track recording state
rec = 0
function init()
print("init")
-- start Looping(?)
engine.loop_start(1,0)
engine.loop_end(1,5)
engine.loop_on(1,1)
-- preAmp(?)
engine.pre(1,1)
engine.amp(1,1)
-- record Arm(?)
engine.rec_on(1,1)
engine.rec(1,1)
-- adc in rec (?)
-- adc_rec(inChannel, buffer, amplitude)
engine.adc_rec(1,1,1)
-- engine.adc_rec(1,2,1)
-- out to DAC
-- plac_dac(buffer, channel, amp)
engine.play_dac(1,1,1)
engine.play_dac(1,2,1)
-- out speed
engine.rate(1,1)
engine.rate_lag(1,0.6)
-- cleanup(?)
engine.reset(1)
-- stop engines
engine.clear()
engine.stop(1)
end
rec_toggle = 0
clear = 1
function key(n,z)
--KEY 2
if n == 2 and z == 1 then
rec = rec + 1
if rec % 2 == 1 and clear == 1 then
rec_toggle = 1
engine.clear()
engine.reset(1)
engine.rec_on(1,1)
engine.start(1)
redraw()
elseif rec % 2 == 0 and clear == 1 then
rec_toggle = 0
clear = 0
engine.reset(1)
engine.rec_on(1,0)
redraw()
end
-- if buffer1 is NOT clear
if rec % 2 == 1 and clear == 0 then
engine.rec_on(1,1)
rec_toggle = 1
redraw()
elseif rec % 2 == 0 and clear == 0 then
engine.rec_on(1,0)
rec_toggle = 0
redraw()
end
end
end
function redraw()
screen.clear()
screen.level(15)
-- recording
screen.move(112, 60)
if rec_toggle == 1 then
screen.text('rec1')
end
screen.update()
end

Loading…
Cancel
Save