Skip to content

Instantly share code, notes, and snippets.

@dndrks
Last active July 27, 2024 04:40
Show Gist options
  • Save dndrks/48affab46f87bcebac252bb17393db77 to your computer and use it in GitHub Desktop.
Save dndrks/48affab46f87bcebac252bb17393db77 to your computer and use it in GitHub Desktop.
W/Tape: i2c recording sequencer
-- W/Tape: i2c recording sequencer
-- as shown in https://youtu.be/2RUHr-iX1VE?si=Ny_3t0TNqKlAaWoQ&t=1216
-- requires crow
-- patch crow output 1 to an oscillator's v/8
-- patch crow output 2 to an envelope generator
-- execute 'auto_rec()' to start recording loops at different speeds
-- execute 'auto_play()' to play through each of the loops
tl = timeline
function init()
notes = sequins{0, 4, 7, 9, 11}
clock.run(play_note)
clock.run(trigger_envelope)
record_speeds = {1, 0.5, 2, 2/3} -- for 'auto_rec()'
record_duration = 12 -- 12 beats of recording
playback_durations = {8, 6, 12, 14} -- for 'auto_play()'
-- keep track of our loop points and their playback speeds:
loops = {
id = {},
speed = {}
}
loop_index = 1
-- default state:
ii.wtape[1].loop_active(0) -- no loop
ii.wtape[1].speed(1) -- 1x playback
ii.wtape[1].record(0) -- no recording
-- clear all audio (optional):
-- ii.wtape[1].WARNING_clear_tape()
end
function play_note()
while true do
clock.sync(1/3)
output[1].volts = notes()/12
end
end
function trigger_envelope()
while true do
clock.sync(1 / 2)
state = state == 10 and 0 or 10
output[2].volts = state
end
end
-- a callback event for 'loop_start' commands:
ii.wtape[1].event = function(event, value)
if event.name == 'loop_start' then
ii.wtape[1].timestamp(value) -- move tape playback to the value
ii.wtape[1].loop_active(1) -- activate looping
end
end
function auto_rec()
tl.score{
0, function() capture_loop(record_speeds[1]) end,
record_duration, function() capture_loop(record_speeds[2]) end,
record_duration * 2, function() capture_loop(record_speeds[3]) end,
record_duration * 3, function() capture_loop(record_speeds[4]) end,
}
end
function auto_play()
tl.loop{
playback_durations[1], function() jump_to_loop(1) end,
playback_durations[2], function() jump_to_loop(2) end,
playback_durations[3], function() jump_to_loop(3) end,
playback_durations[4], function() jump_to_loop(4) end,
}
end
function capture_loop(speed)
speed = speed and speed or 1
local next_loop = false
if loops.id[loop_index] then
next_loop = true
ii.wtape[1].loop_next(1)
loop_index = loop_index + 1
print("next loop", loop_index)
end
tl.score{
0,
function()
if not next_loop then
print("loop start")
ii.wtape[1].loop_start()
else
print("jump to start")
ii.wtape[1].get("loop_start")
end
ii.wtape[1].play(1)
ii.wtape[1].record(1)
ii.wtape[1].speed(1)
end,
3,
function()
if not next_loop then
print("loop end")
ii.wtape[1].loop_end()
end
ii.wtape[1].record(0)
ii.wtape[1].speed(speed)
loops.id[loop_index] = true
loops.speed[loop_index] = speed
end
}
end
function jump_to_loop(id)
if loops.id[id] then
local move_by = id - loop_index
if move_by < 0 then
for i = move_by,-1 do
ii.wtape[1].loop_next(-1)
end
else
for i = 1,move_by do
ii.wtape[1].loop_next(1)
end
end
print("jumping by "..id - loop_index)
ii.wtape[1].get("loop_start")
ii.wtape[1].speed(loops.speed[id])
loop_index = id
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment