Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 211 additions & 0 deletions otis.lua
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ local skip_pos = {nil, nil}
local spds = include("lib/spds")
local speed_index = {4, 4} -- maybe move this to spds.lua?

local buf_snapshots = {{}, {}}
local buf_positions = {0, 0}
local buf_snapshots_max = {0, 0}

-- flip, skip, and speed controls
local function skip(n)
Expand Down Expand Up @@ -606,9 +609,40 @@ function init()
grid_metro.event = function() grid_redraw() end
grid_metro:start()


-- timer to query buffer snapshot and play position
local buf_snapshot_size = 128
local buf_snapshot_metro = metro.init()
buf_snapshot_metro.time = 1/15
softcut.event_render(function (ch, start, secpersample, samples)
buf_snapshots[ch] = samples
buf_snapshots_max[ch] = table_getmax(samples)
end)
softcut.event_position(function (ch, position)
buf_positions[ch] = position
end)
buf_snapshot_metro.event = function()
softcut.render_buffer(1, 0, params:get("1loop_end"), buf_snapshot_size)
softcut.render_buffer(2, 0, params:get("2loop_end"), buf_snapshot_size)
softcut.query_position(1)
softcut.query_position(2)
end
buf_snapshot_metro:start()

audio.level_eng_cut(0)
end


function table_getmax(t)
local max = 0
for _,v in pairs(t) do
if math.abs(v) > max then
max = math.abs(v)
end
end
return util.clamp(max, 0.01, 1)
end

-- screen drawing
local function draw_left()
-- tape direction indicator
Expand Down Expand Up @@ -794,8 +828,185 @@ local function draw_lfo_info()
screen.text("3. offset: " .. params:get(lfo_index .. "offset"))
end

function draw_single_page()
screen.clear()
screen.aa(0)
screen.font_face(25)
screen.font_size(6)

draw_buffer(1, 28, 12)
draw_buffer(2, 28, 45)

draw_vbar(0, 20, params:get("1vol"), muted_L, (page == 1 and alt == 0))
draw_vbar(0, 56, params:get("2vol"), muted_R, (page == 1 and alt == 0))

draw_vbar(20, 20, params:get("1feedback"), false, (page == 2 and alt == 1))
draw_vbar(20, 56, params:get("2feedback"), false, (page == 2 and alt == 1))

draw_pan(12, 8, params:get("1pan"))
draw_pan(12, 45, params:get("2pan"))

draw_button(11, 17, rec1 and "REC" or "")
draw_button(11, 54, rec2 and "REC" or "")

draw_page_status()

screen.update()
end

function draw_page_status()
screen.level(10)
local bt = "mute"
local knobs = "level"
if page == 1 then
if alt == 1 then
knobs = "pan"
end
elseif page == 2 then
if alt == 0 then
bt = "flip"
knobs = "speed"
else
bt = "skip"
knobs = "fdbk"
end
elseif page == 3 then
if alt == 0 then
bt = "rec"
knobs = "start"
else
bt = "clear"
knobs = "end"
end
end
local txt = pages[page] .. ": " .. bt .. "/" .. knobs .. (fine_adjust and "(f)" or "(c)")
if page == 1 then
screen.move(0, 63)
screen.text(txt)
elseif page == 2 then
screen.move(63, 63)
screen.text_center(txt)
elseif page == 3 then
screen.move(127, 63)
screen.text_right(txt)
end
end


function draw_button(x, y, char)
screen.level(10)
screen.move(x, y)
screen.text_center(char)
end

function draw_pan(x, y, val)
-- draw "LR" for panning, crossfading the level to indicate position
-- center if full level
if math.abs(val) < 0.05 then
screen.level(10)
screen.move(x-1, y)
screen.text_center("C")
return
end
screen.level(util.linlin(-1, 1, 15, 0, val)//1)
screen.move(x-1, y)
screen.text_right("L")
screen.level(util.linlin(-1, 1, 0, 15, val)//1)
screen.move(x, y)
screen.text("R")
end

function draw_vbar(x, y, val, off, active)
local width = 2
local max_height = 18
local height = util.linlin(0, 1, 0, max_height, val)

screen.level(3)
screen.move(x, y-max_height+1)
screen.line_rel(width, 0)
screen.stroke()
if off then
screen.level(1)
else
screen.level(active and 15 or 4)
end
screen.rect(x, y-height, width, height)
screen.fill()
end

function draw_buffer(n, x_off, y_off)
screen.level(6)

local max_height = 6
local y_top = y_off - max_height
local buf_width = 128 - x_off

local buf = buf_snapshots[n]
if #buf == 0 then return end -- not initialized
local max = buf_snapshots_max[n]
max = 1

local x_pos = 0
for i, s in ipairs(buf) do
local height = util.round(math.abs(s) / max * max_height)
screen.move(util.linlin(0, #buf-1, x_off, x_off+buf_width, x_pos), y_off - height)
screen.line_rel(0, 2 * height)
screen.stroke()
x_pos = x_pos + 1
end

screen.level(3)
screen.move(util.linlin(0, params:get(n .. "loop_end"), x_off, x_off+buf_width, buf_positions[n]), y_off - max_height)
screen.line_rel(0, 2 * max_height)
screen.stroke()

-- edit: start
local l_start = x_off + params:get(n .. "loop_start") / params:get(n .. "loop_end") * buf_width
screen.level((page == 3 and alt == 0) and 15 or 3)
screen.move(l_start+1, y_off - max_height)
screen.line_rel(0, 2 * max_height)
screen.stroke()

l_start = util.clamp(l_start, x_off+8, x_off+buf_width - 32)
screen.move(l_start, y_off + 2*max_height)
screen.text_center(string.format("%.2f", params:get(n .. "loop_start")))

-- edit: end
screen.level((page == 3 and alt == 1) and 15 or 3)
screen.move(x_off+buf_width, y_off - max_height)
screen.line_rel(0, 2 * max_height)
screen.stroke()
screen.move(x_off+buf_width, y_off + 2*max_height)
screen.text_right(string.format("%.2f", params:get(n .. "loop_end")))

-- play: speed
screen.level((page == 2 and alt == 0) and 15 or 5)
local center = x_off + buf_width//2
screen.move(center, y_top)
local speed = params:get(n .. "speed")
screen.text_center(string.format("%.2f", speed))

screen.move(center, y_top+1)
screen.line_rel(util.linlin(-4.0, 4.0, -45, 45, speed), 0)
screen.stroke()

local l,r,lfo = check_for_speed_modulation()
if (n == 1 and l) or (n == 2 and r) then
-- draw offset as small tick
local offset = params:get(n .. "offset")
screen.level(10)
screen.move(center + util.linlin(-4.0, 4.0, -45, 45, offset), y_top-1)
screen.line_rel(0, 3)
screen.stroke()
end

end

function redraw()
-- TODO
draw_single_page()
do return end

screen.clear()
screen.aa(0)
screen.font_face(25)
Expand Down