mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 15:25:01 +01:00
188 lines
5 KiB
Lua
188 lines
5 KiB
Lua
ardour {
|
|
["type"] = "dsp",
|
|
name = "Lua IR Capture",
|
|
license = "MIT",
|
|
author = "Ardour Team",
|
|
description = [[
|
|
1. Calibrate I/O Latency (Menu > Window > Audio/MIDI Setup)
|
|
2. Create a mono track - this will be used to record the IR.
|
|
3. Disconnect the input and output of that track.
|
|
4. Add a mono bus and load this plugin on the bus.
|
|
5. Connect the left output of the bus to the mono track's input.
|
|
The deconvolved Impulse Response will be output on that channel.
|
|
6. Connect the right output of the bus to a hardware playback port, matching the system you want to capture.
|
|
A sine-sweep will be played on that channel.
|
|
7. Connect the bus' input to the return signal (hardware capture) of the system under test.
|
|
8. Record Arm the track (from 2)
|
|
9. Record Arm the session
|
|
10. Open the GUI of this plugin, enable "Capture"
|
|
11. Roll the transport.
|
|
12. Wait 10 sec (recording stops automatically).
|
|
13. Select the region on the mono track: Region > Edit > Strip Silence and/or manually tweak the region start:
|
|
move it close to the initial impulse.
|
|
14. Region > Gain > Normalize, or manually adjust gain.
|
|
15. Disable region-fades of the region: Region > Fades
|
|
16. Export the region to save the IR file (Region > Export)
|
|
]]
|
|
}
|
|
|
|
function dsp_ioconfig () return
|
|
{
|
|
connect_all_audio_outputs = true, -- override strict-i/o
|
|
{ audio_in = 1, audio_out = 2},
|
|
}
|
|
end
|
|
|
|
function dsp_params ()
|
|
return {
|
|
{ ["type"] = "input", name = "Capture", min = 0, max = 1, default = 0, toggled = true },
|
|
{ ["type"] = "output", name = "State", min = 0, max = 2, enum = true, scalepoints =
|
|
{
|
|
["Idle"] = 0,
|
|
["Capturing"] = 1,
|
|
["Finalize"] = 2,
|
|
}
|
|
},
|
|
{ ["type"] = "output", name = "IR Signal Level", min = -120, max = 0 },
|
|
}
|
|
end
|
|
|
|
local conv
|
|
local state
|
|
local sweep_sin
|
|
local peak
|
|
local rec_len
|
|
local n_captured
|
|
local n_playback
|
|
|
|
function gen_sweep (fmin, fmax, t_sec, rate)
|
|
local n_samples_pre = rate * 0.1
|
|
local n_samples_sin = rate * t_sec
|
|
local n_samples_end = rate * 0.03
|
|
local n_samples = n_samples_pre + n_samples_sin + n_samples_end
|
|
|
|
local amp = 0.5
|
|
|
|
local a = math.log (fmax / fmin) / n_samples_sin
|
|
local b = fmin / (a * rate)
|
|
local r = 4.0 * a * a / amp
|
|
|
|
local cmem = ARDOUR.DSP.DspShm (n_samples * 2)
|
|
local ss = cmem:to_float (0):array()
|
|
local si = cmem:to_float (n_samples):array()
|
|
|
|
for i = 0, n_samples - 1 do
|
|
local j = n_samples - i - 1
|
|
|
|
local gain = 1.0
|
|
|
|
if i < n_samples_pre then
|
|
gain = math.sin (0.5 * math.pi * i / n_samples_pre)
|
|
elseif j < n_samples_end then
|
|
gain = math.sin (0.5 * math.pi * j / n_samples_end)
|
|
end
|
|
|
|
local d = b * math.exp (a * (i - n_samples_pre))
|
|
local p = d - b
|
|
local x = gain * math.sin (2 * math.pi * (p - math.floor (p)))
|
|
|
|
ss[i + 1] = x * amp
|
|
si[j + 1] = x * d * r
|
|
end
|
|
|
|
sweep_sin = ARDOUR.AudioRom.new_rom (cmem:to_float (0), n_samples)
|
|
|
|
-- de-convolver
|
|
local sweep_inv = ARDOUR.AudioRom.new_rom (cmem:to_float (n_samples), n_samples)
|
|
conv = ARDOUR.DSP.Convolution (Session, 1, 1)
|
|
conv:add_impdata (0, 0, sweep_inv, 1.0, 0, 0, 0, 0)
|
|
conv:restart ()
|
|
|
|
sweep_inv = nil
|
|
cmem = nil
|
|
collectgarbage ()
|
|
end
|
|
|
|
function dsp_init (rate)
|
|
local fmax = 20000
|
|
local slen = 5 -- sec
|
|
local rlen = slen + 5 -- sec
|
|
|
|
if fmax > rate * .47 then
|
|
fmax = rate * .47
|
|
end
|
|
gen_sweep (20, fmax, slen, rate)
|
|
|
|
rec_len = rlen * rate
|
|
|
|
n_captured = 0
|
|
n_playback = 0
|
|
peak = 0
|
|
state = 0
|
|
end
|
|
|
|
function dsp_latency ()
|
|
return conv:latency()
|
|
end
|
|
|
|
function reset ()
|
|
state = 0
|
|
if n_captured > 0 then
|
|
conv:restart ()
|
|
end
|
|
n_captured = 0
|
|
n_playback = 0
|
|
end
|
|
|
|
function dsp_runmap (bufs, in_map, out_map, n_samples, offset)
|
|
local ctrl = CtrlPorts:array() -- get control port array
|
|
local capture = ctrl[1] > 0
|
|
|
|
if state == 0 and capture and Session:actively_recording () then
|
|
state = 1
|
|
peak = 0
|
|
print ("START CAPTURE")
|
|
end
|
|
if state == 2 then
|
|
Session:request_stop (false, false, ARDOUR.TransportRequestSource.TRS_UI)
|
|
reset ()
|
|
end
|
|
|
|
-- check I/O mapping
|
|
local input = in_map:get (ARDOUR.DataType ("audio"), 0)
|
|
local outir = out_map:get (ARDOUR.DataType ("audio"), 0)
|
|
local outsw = out_map:get (ARDOUR.DataType ("audio"), 1)
|
|
|
|
if input == ARDOUR.ChanMapping.Invalid or outir == ARDOUR.ChanMapping.Invalid or outsw == ARDOUR.ChanMapping.Invalid or input ~= outir then
|
|
reset ();
|
|
end
|
|
|
|
if state ~= 1 then
|
|
bufs:get_audio (outir):silence (n_samples, offset)
|
|
end
|
|
|
|
if state == 1 then -- capture
|
|
conv:run_mono_buffered (bufs:get_audio(input):data (offset), n_samples)
|
|
|
|
if n_samples + n_captured > rec_len then
|
|
state = 2
|
|
end
|
|
|
|
peak = ARDOUR.DSP.compute_peak (bufs:get_audio(input):data (offset), n_samples, peak) -- compute digital peak
|
|
n_captured = n_captured + n_samples
|
|
end
|
|
|
|
if state == 1 then
|
|
-- play back sine-sweep
|
|
local copied = sweep_sin:read (bufs:get_audio (outsw):data (offset), n_playback, n_samples, 0)
|
|
n_playback = n_playback + copied
|
|
if copied < n_samples then
|
|
bufs:get_audio (outsw):silence (n_samples - copied, offset + copied)
|
|
end
|
|
else
|
|
bufs:get_audio (outsw):silence (n_samples, offset)
|
|
end
|
|
|
|
ctrl[2] = state
|
|
ctrl[3] = ARDOUR.DSP.accurate_coefficient_to_dB (peak)
|
|
end
|