1ardour {
2	["type"]    = "dsp",
3	name        = "Simple Synth",
4	category    = "Instrument",
5	license     = "MIT",
6	author      = "Ardour Team",
7	description = [[An Example synth for prototyping: Sine-wave with a basic attack/sustain/release envelope, variable number of output channels.]]
8}
9
10function dsp_ioconfig ()
11	return
12	{
13	--	{ midi_in = 1, audio_in = 0, audio_out = -1}, -- any number of channels
14	--	{ midi_in = 1, audio_in = 0, audio_out =  1}, -- values >  0, precisely N channels
15		{ midi_in = 1, audio_in = 0, audio_out =  2}, -- values >  0, precisely N channels
16		{ midi_in = 1, audio_in = 0, audio_out =  4}, -- values >  0, precisely N channels
17		{ midi_in = 1, audio_in = 0, audio_out =  8}, -- values >  0, precisely N channels
18	--	{ midi_in = 1, audio_in = 0, audio_out = -6}, -- values < -2, up to -N channels, here 1,..,6
19	}
20end
21
22local note_table = {}
23local active_notes = {}
24local phases = {}
25local env = .01;
26
27function dsp_init (rate)
28	for n = 1,128 do
29		note_table [n] = (440 / 32) * 2^((n - 10.0) / 12.0) / rate
30	end
31	env = 100 / rate
32end
33
34function dsp_run (ins, outs, n_samples)
35	-- initialize output buffer
36	local a = {}
37	for s = 1, n_samples do a[s] = 0 end
38
39
40	-- very basic synth, simple sine, basic envelope
41	local function synth (s_start, s_end)
42		for n,v in pairs (active_notes) do
43			local vel = v["vel"] or 0
44			local tgt = v["tvel"];
45			for s = s_start,s_end do
46				local phase = phases[n] or 0
47				vel = vel + env * (tgt - vel)
48				a[s] = a[s] + math.sin(6.283185307 * phase) * vel / 167
49				phase = phase + note_table[n]
50				if (phase > 1.0) then
51					phases[n] = phase - 2.0
52				else
53					phases[n] = phase
54				end
55			end
56			if vel < 1 and tgt == 0 then
57				active_notes[n] = nil
58			else
59				active_notes[n]["vel"] = vel;
60			end
61		end
62	end
63
64	local tme = 1
65	-- parse midi messages
66	assert (type(midiin) == "table") -- global table of midi events (for now)
67	for _,b in pairs (midiin) do
68		local t = b["time"] -- t = [ 1 .. n_samples ]
69
70		-- synth sound until event
71		synth(tme, t)
72		tme = t + 1
73
74		local d = b["data"] -- get midi-event
75		-- we ignore the midi channel
76		if (#d == 3 and (d[1] & 240) == 144) then -- note on
77			local n = 1 + d[2];
78			active_notes[n] = active_notes[n] or {}
79			active_notes[n]["tvel"] = d[3]
80		end
81		if (#d == 3 and (d[1] & 240) == 128) then -- note off
82			local n = 1 + d[2];
83			active_notes[n] = active_notes[n] or {}
84			active_notes[n]["tvel"] = 0
85		end
86		if (#d == 3 and (d[1] & 240) == 176) then -- CC
87			if (d[2] == 120 or d[2] == 123) then -- panic
88				active_notes = {}
89			end
90		end
91	end
92
93	-- synth rest of cycle
94	synth(tme, n_samples)
95
96	-- copy
97	for c = 1,#outs do
98		outs[c]:set_table(a, n_samples)
99	end
100end
101