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