cool, thanks.
well i have good news and bad news.
bad: that does indeed seem like a regression, which i can’t quite explain yet. thanks for spotting it and i’ll try and fix it quickly.
under the hood, there are two R/W head pairs in each voice, for crossfading, and it sounds like the wrong one is getting activated in this condition: enabling record while already playing, and loop/crossfade hasn’t occurred since the last explicit position change / voice-state change / something.
this isn’t too surprising since there are actually different sample callback functions depending on which state the voice is in, this was done relatively recently in a refactor, so i will double check on the logic around that.
good: there is a better way to implement this, which is to use rec_level
instead of the rec
flag. the former is intended for realtime modulation. the latter should be thought of as a configuration / optimization setting. so here’s a version that seems to work as expected and doesn’t have clicks on punch-in/out:
-- Simple Looper (updated)
--
amirecording = 0
base_loop = 0
end_of_loop = 61
time_ref = 0
pan = {-0.75, 0.75}
function init()
print("simple hello")
softcut.buffer_clear()
audio.level_adc_cut(0.75)
for i = 1,2 do
softcut.level_input_cut(i,i,1)
softcut.buffer(i,i)
softcut.pan(i, pan[i])
softcut.play(i,1)
softcut.rec(i,1)
softcut.enable(i,1)
softcut.rec_offset(i,-0.06)
softcut.pre_level(i,1)
softcut.rec_level(i, 1)
softcut.level(i,0.75)
softcut.loop(i,1)
softcut.loop_start(i,1)
softcut.loop_end(i,end_of_loop + 1)
softcut.position(i,1)
softcut.rate(i,1.0)
softcut.fade_time(i,0)
softcut.level_slew_time(i,0.5)
softcut.rate_slew_time(i,0.05)
end
redraw()
end
function key(n,z)
if n==3 and z==1 then
if amirecording == 1 then
softcut.rec_level(1,0)
softcut.rec_level(2,0)
amirecording = 0
if base_loop == 0 then
end_of_loop = util.time() - time_ref + 1
print("end_of_loop: "..end_of_loop)
softcut.loop_end(1,end_of_loop)
softcut.loop_end(2,end_of_loop)
base_loop = 1
end
elseif amirecording == 0 then
if base_loop == 0 then
time_ref = util.time()
softcut.position(1,1)
softcut.position(2,1)
end
softcut.rec_level(1,1)
softcut.rec_level(2,1)
amirecording = 1
end
end
redraw()
end
function redraw()
screen.clear()
screen.aa(0)
screen.level(10)
screen.font_size(8)
screen.move(64,25)
if amirecording == 0 and base_loop == 0 then
screen.text_center("K3 to Record")
elseif amirecording == 1 and base_loop == 0 then
screen.text_center("Recording ... K3 to Stop")
elseif amirecording == 0 and base_loop == 1 then
screen.text_center("Got It ... K3 to Overdub")
elseif amirecording == 1 and base_loop == 1 then
screen.text_center("Overdubbing ... K3 to Stop")
end
screen.update()
end
setting pre_level=1
and rec_level=0
makes a lossless loop.