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