3 name = "Biquad Filter",
6 author = "Robin Gareus",
7 email = "robin@gareus.org",
8 site = "http://gareus.org",
10 An Example DSP Plugin for processing audio, to
11 be used with Ardour's Lua scripting facility.]]
14 function dsp_ioconfig ()
17 { audio_in = -1, audio_out = -1},
22 function dsp_params ()
25 { ["type"] = "input", name = "Type", min = 0, max = 4, default = 0, enum = true, scalepoints =
34 { ["type"] = "input", name = "Gain", min = -20, max = 20, default = 0, unit="dB" },
35 { ["type"] = "input", name = "Freq", min = 20, max = 20000, default = 1000, unit="Hz", logarithmic = true },
36 { ["type"] = "input", name = "Q", min = 0.1, max = 8, default = .707, logarithmic = true },
40 -- these globals are *not* shared between DSP and UI
41 local filt -- the filter instance
42 local cur = {0, 0, 0, 0} -- current settings
44 function dsp_init (rate)
45 self:shmem ():allocate (1) -- shared mem to tell UI about samplerate
46 local cfg = self:shmem ():to_int (0):array ()
48 filt = ARDOUR.DSP.Biquad (rate) -- initialize filter
52 -- apply parameters, re-compute filter coefficients if needed
53 function apply_params (ctrl)
54 if ctrl[1] == cur[1] and ctrl[2] == cur[2] and ctrl[3] == cur[3] and ctrl[4] == cur[4] then
60 ft = ARDOUR.DSP.BiQuadType.LowShelf
61 elseif ctrl[1] == 2 then
62 ft = ARDOUR.DSP.BiQuadType.HighShelf
63 elseif ctrl[1] == 3 then
64 ft = ARDOUR.DSP.BiQuadType.LowPass
65 elseif ctrl[1] == 4 then
66 ft = ARDOUR.DSP.BiQuadType.HighPass
68 ft = ARDOUR.DSP.BiQuadType.Peaking
71 -- TODO low-pass filter ctrl values, smooth transition
72 filt:compute (ft, ctrl[3], ctrl[4], ctrl[2])
81 -- the actual DSP callback
82 function dsp_run (ins, outs, n_samples)
83 if apply_params (CtrlPorts:array ()) then
87 if ins[c]:sameinstance (outs[c]) then
88 filt:run (ins[c], n_samples) -- in-place
90 ARDOUR.DSP.copy_vector (outs[c], ins[c], n_samples)
91 filt:run (outs[c], n_samples)
97 -------------------------------------------------------------------------------
101 return math.floor (n + .5)
104 function freq_at_x (x, w)
105 return 20 * 1000 ^ (x / w)
108 function x_at_freq (f, w)
109 return w * math.log (f / 20.0) / math.log (1000.0)
112 function db_to_y (db, h)
113 if db < -20 then db = -20 end
114 if db > 20 then db = 20 end
115 return -.5 + 0.5 * h * (1 - db / 20)
118 function grid_db (ctx, w, h, db)
119 local y = -.5 + round (db_to_y (db, h))
125 function grid_freq (ctx, w, h, f)
126 local x = -.5 + round (x_at_freq (f, w))
132 function render_inline (ctx, w, max_h)
134 -- instantiate filter (to calculate the transfer function)
135 local shmem = self:shmem () -- get shared memory region
136 local cfg = shmem:to_int (0):array () -- "cast" into lua-table
137 filt = ARDOUR.DSP.Biquad (cfg[1])
140 apply_params (CtrlPorts:array ())
142 -- calc height of inline display
143 local h = math.ceil (w * 10 / 16) -- 16:10 aspect
144 h = 2 * round (h / 2) -- even number of vertical px
150 ctx:rectangle (0, 0, w, h)
151 ctx:set_source_rgba (.2, .2, .2, 1.0)
154 ctx:set_line_width (1.0)
157 local dash3 = C.DoubleVector ()
159 ctx:set_dash (dash3, 2)
160 ctx:set_source_rgba (.5, .5, .5, .5)
161 grid_db (ctx, w, h, 0)
162 grid_db (ctx, w, h, 6)
163 grid_db (ctx, w, h, 12)
164 grid_db (ctx, w, h, 18)
165 grid_db (ctx, w, h, -6)
166 grid_db (ctx, w, h, -12)
167 grid_db (ctx, w, h, -18)
168 grid_freq (ctx, w, h, 100)
169 grid_freq (ctx, w, h, 1000)
170 grid_freq (ctx, w, h, 10000)
173 -- draw transfer function
174 ctx:set_source_rgba (.8, .8, .8, 1.0)
175 ctx:move_to (-.5, db_to_y (filt:dB_at_freq (freq_at_x (0, w)), h))
177 local db = filt:dB_at_freq (freq_at_x (x, w))
178 ctx:line_to (-.5 + x, db_to_y (db, h))
180 ctx:stroke_preserve ()
182 -- fill area to zero under the curve
183 ctx:line_to (w, -.5 + h * .5)
184 ctx:line_to (0, -.5 + h * .5)
186 ctx:set_source_rgba (.5, .5, .5, .5)