2016-02-23 09:44:41 -05:00
|
|
|
ardour {
|
|
|
|
["type"] = "dsp",
|
|
|
|
name = "Simple Synth",
|
2016-04-28 19:40:06 -04:00
|
|
|
category = "Instrument",
|
2016-02-23 09:44:41 -05:00
|
|
|
license = "MIT",
|
2016-07-12 09:21:23 -04:00
|
|
|
author = "Ardour Lua Task Force",
|
2020-04-23 23:47:02 -04:00
|
|
|
description = [[An Example synth for prototyping: Sine-wave with a basic attack/sustain/release envelope, variable number of output channels.]]
|
2016-02-23 09:44:41 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
function dsp_ioconfig ()
|
|
|
|
return
|
|
|
|
{
|
2016-08-04 11:47:38 -04:00
|
|
|
-- { midi_in = 1, audio_in = 0, audio_out = -1}, -- any number of channels
|
|
|
|
-- { midi_in = 1, audio_in = 0, audio_out = 1}, -- values > 0, precisely N channels
|
|
|
|
{ midi_in = 1, audio_in = 0, audio_out = 2}, -- values > 0, precisely N channels
|
|
|
|
{ midi_in = 1, audio_in = 0, audio_out = 4}, -- values > 0, precisely N channels
|
|
|
|
{ midi_in = 1, audio_in = 0, audio_out = 8}, -- values > 0, precisely N channels
|
|
|
|
-- { midi_in = 1, audio_in = 0, audio_out = -6}, -- values < -2, up to -N channels, here 1,..,6
|
2016-02-23 09:44:41 -05:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
local note_table = {}
|
|
|
|
local active_notes = {}
|
|
|
|
local phases = {}
|
|
|
|
local env = .01;
|
|
|
|
|
|
|
|
function dsp_init (rate)
|
|
|
|
for n = 1,128 do
|
|
|
|
note_table [n] = (440 / 32) * 2^((n - 10.0) / 12.0) / rate
|
|
|
|
end
|
|
|
|
env = 100 / rate
|
|
|
|
end
|
|
|
|
|
|
|
|
function dsp_run (ins, outs, n_samples)
|
|
|
|
-- initialize output buffer
|
|
|
|
local a = {}
|
|
|
|
for s = 1, n_samples do a[s] = 0 end
|
|
|
|
|
|
|
|
|
|
|
|
-- very basic synth, simple sine, basic envelope
|
|
|
|
local function synth (s_start, s_end)
|
|
|
|
for n,v in pairs (active_notes) do
|
|
|
|
local vel = v["vel"] or 0
|
|
|
|
local tgt = v["tvel"];
|
|
|
|
for s = s_start,s_end do
|
|
|
|
local phase = phases[n] or 0
|
|
|
|
vel = vel + env * (tgt - vel)
|
|
|
|
a[s] = a[s] + math.sin(6.283185307 * phase) * vel / 167
|
|
|
|
phase = phase + note_table[n]
|
|
|
|
if (phase > 1.0) then
|
|
|
|
phases[n] = phase - 2.0
|
|
|
|
else
|
|
|
|
phases[n] = phase
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if vel < 1 and tgt == 0 then
|
|
|
|
active_notes[n] = nil
|
|
|
|
else
|
|
|
|
active_notes[n]["vel"] = vel;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local tme = 1
|
|
|
|
-- parse midi messages
|
2016-05-29 14:36:16 -04:00
|
|
|
assert (type(midiin) == "table") -- global table of midi events (for now)
|
|
|
|
for _,b in pairs (midiin) do
|
2016-02-23 09:44:41 -05:00
|
|
|
local t = b["time"] -- t = [ 1 .. n_samples ]
|
|
|
|
|
|
|
|
-- synth sound until event
|
|
|
|
synth(tme, t)
|
|
|
|
tme = t + 1
|
|
|
|
|
|
|
|
local d = b["data"] -- get midi-event
|
|
|
|
-- we ignore the midi channel
|
2018-03-17 16:13:06 -04:00
|
|
|
if (#d == 3 and (d[1] & 240) == 144) then -- note on
|
2016-02-23 09:44:41 -05:00
|
|
|
local n = 1 + d[2];
|
|
|
|
active_notes[n] = active_notes[n] or {}
|
|
|
|
active_notes[n]["tvel"] = d[3]
|
|
|
|
end
|
2018-03-17 16:13:06 -04:00
|
|
|
if (#d == 3 and (d[1] & 240) == 128) then -- note off
|
2016-02-23 09:44:41 -05:00
|
|
|
local n = 1 + d[2];
|
|
|
|
active_notes[n] = active_notes[n] or {}
|
|
|
|
active_notes[n]["tvel"] = 0
|
|
|
|
end
|
2018-03-17 16:13:06 -04:00
|
|
|
if (#d == 3 and (d[1] & 240) == 176) then -- CC
|
2016-02-23 09:44:41 -05:00
|
|
|
if (d[2] == 120 or d[2] == 123) then -- panic
|
|
|
|
active_notes = {}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- synth rest of cycle
|
|
|
|
synth(tme, n_samples)
|
|
|
|
|
|
|
|
-- copy
|
2016-04-14 18:17:09 -04:00
|
|
|
for c = 1,#outs do
|
|
|
|
outs[c]:set_table(a, n_samples)
|
|
|
|
end
|
2016-02-23 09:44:41 -05:00
|
|
|
end
|