The infinitedigits solution is super tidy compared to mine but I thought I’d share this as I’ve found it really useful to allow me to have the polling set fast but not get loads of re-triggers. This one is using crow but you could just just pinch the re-trigger stuff or swap in the p_amp_in code wherever the crow stuff is. If you just need one then dump the socket stuff but you could also re-purpose that to be L/R inputs.
I’ve got this as a separate object that I can drop into the lib folder. Then you just add the include at the top of the client script, run the init at the bottom of your app’s init code, pass whatever method you want to call into the init and specify which port.
The threshold, hysteresis and hold time all come up in params so you can tweak while you tap.
I should warn you that the amplitude reading is probably not the peak. I guess it’s a trade off, if you want fast response then there’s alway the chance that you are triggering as the amplitude rises rather than at it’s peak.
Summary
– Crow Audio input driven event triggers
– Pass in callback function and it calls it with the amplitude, I think thresh->1, as the return argument
– Second init argument can be 1 or 2 or specify the input to listen to, defaults to 1.
local tr = {}
local function callback() end
local input_socket = 1
–audio input polling variables
local refresh_rate = 0.005
local amp_in = 0
local triggered = false
local hold_timer
local retrigger_hold = false
local function retriggerholdtimer()
clock.sleep(params:get(“retrigger_hold_time”)/100.0) – params map to 100ths of a second
retrigger_hold = false
end
local function triggerhold()
if retrigger_hold then – cancel the previous hold timer, edge case, prevent double offs.
clock.cancel(triggerholdtimer)
else
retrigger_hold = true
end
clock.run(retriggerholdtimer)
end
local function inputreading(amp)
amp_in = amp
–print(amp_in)
if triggered then --if we were already above theshold then see if we are now low enough to be ready for another transient
if amp_in < (params:get(“trigger_threshold”)/10) - (params:get(“trigger_hysteresis”)/10) then
triggered = false
end
elseif retrigger_hold then – if too close to a recent trigger
elseif not triggered and not retrigger_hold then – if not already above threshold or close to previous trigger
if amp_in > (params:get(“trigger_threshold”)/10) then
triggered = true
triggerhold()
print('trigger ’ … string.format("%.4f", amp_in) )
callback(amp_in)
end
end
end
function tr.init(cb, socket)
if socket == 1 then
input_socket = socket
elseif socket == 2 then
input_socket = socket
end
callback = cb
crow.input[input_socket].mode( ‘volume’, refresh_rate )
crow.input[input_socket].volume = inputreading
params:add_separator()
params:add{type = “number”, id = “trigger_threshold”, name = "trigger threshold "…input_socket, min = 10, max = 50, default = 30}
params:add{type = “number”, id = “trigger_hysteresis”, name = "trigger hysteresis "… input_socket, min = 1, max = 30, default = 10}
params:add{type = “number”, id = “retrigger_hold_time”, name = "retrigger hold time "… input_socket, min = 1, max = 30, default = 8}
end
return tr