Move 'round()' / 'trunc()' etc so that they won't conflict with any versions already...
[ardour.git] / scripts / synth1.lua
1 ardour {
2         ["type"]    = "dsp",
3         name        = "Simple Synth",
4         category    = "Instrument",
5         license     = "MIT",
6         author      = "Ardour Lua Task Force",
7         description = [[An Example Synth for Prototyping.]]
8 }
9
10 function 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         }
20 end
21
22 local note_table = {}
23 local active_notes = {}
24 local phases = {}
25 local env = .01;
26
27 function 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
32 end
33
34 function 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 bit32.band (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 bit32.band (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 bit32.band (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
100 end