1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
ardour {
["type"] = "dsp",
name = "a-Pong",
category = "Visualization",
license = "MIT",
author = "Ardour Lua Task Force",
description = [[classic game of mixer pong]]
}
-- return possible i/o configurations
function dsp_ioconfig ()
-- -1, -1 = any number of channels as long as input and output count matches
return { [1] = { audio_in = -1, audio_out = -1}, }
end
function dsp_params ()
return
{
{ ["type"] = "input", name = "Bar", min = 0, max = 1, default = 0.5 },
}
end
local gametime
local fps
local ball_x, ball_y
local dx, dy
local pingsound
local lotsound
local pingnote
function dsp_init (rate)
self:shmem ():allocate (4)
self:shmem ():clear ()
fps = rate / 25
pingnote = 352 / rate
ball_x = 0.5
ball_y = 0
dx = 0.011
dy = 0.021
end
function dsp_configure (ins, outs)
gametime = fps
pingsound = fps
lostsound = 3 * fps
end
function dsp_run (ins, outs, n_samples)
local ctrl = CtrlPorts:array () -- get control port array (read/write)
local shmem = self:shmem ()
local state = shmem:to_float (0):array () -- "cast" into lua-table
local changed = false
gametime = gametime + n_samples
-- simple game engine
while gametime > fps do
changed = true
gametime = gametime - fps
ball_x = ball_x + dx
ball_y = ball_y + dy
if ball_x >= 1 or ball_x <= 0 then dx = -dx end
if ball_y <= 0 then dy = - dy end
if ball_y > 1 then
local bar = ctrl[1]
if math.abs (bar - ball_x) < 0.1 then
dy = - dy
ball_y = 1.0
dx = dx + 0.1 * (bar - ball_x)
-- queue sound (unless it's playing)
if (pingsound > fps) then
pingsound = 0
end
phase = 0
else
-- game over
lostsound = 0
ball_y = 0
dx = 0.011
end
end
end
-- simple synth -- TODO Optimize
if pingsound <= fps then
for s = 1, n_samples do
pingsound = pingsound + 1
if pingsound > fps then goto note_end end
phase = phase + pingnote
local snd = 0.7 * math.sin(6.283185307 * phase) * math.sin (3.141592 * pingsound / fps)
for c = 1,#outs do
-- don't copy this code, it's quick/dirty and not efficient
outs[c]:array()[s] = outs[c]:array()[s] + snd
end
::note_end::
end
end
if lostsound <= 3 * fps then
for s = 1, n_samples do
lostsound = lostsound + 1
if lostsound > 3 * fps then goto noise_end end
local snd = 0.5 * (math.random () - 0.5)
for c = 1,#outs do
-- don't copy this code, it's quick/dirty and not efficient
outs[c]:array()[s] = outs[c]:array()[s] + snd
end
::noise_end::
end
end
if changed then
state[1] = ball_x
state[2] = ball_y
self:queue_draw ()
end
end
function render_inline (ctx, w, max_h)
local ctrl = CtrlPorts:array () -- get control port array (read/write)
local shmem = self:shmem () -- get shared memory region
local state = shmem:to_float (0):array () -- "cast" into lua-table
if (w > max_h) then
h = max_h
else
h = w
end
-- clear background
ctx:rectangle (0, 0, w, h)
ctx:set_source_rgba (.2, .2, .2, 1.0)
ctx:fill ()
-- display bar
local bar_width = w * .1
local bar_space = w - bar_width
ctx:set_line_cap (Cairo.LineCap.Round)
ctx:set_source_rgba (.8, .8, .8, 1.0)
ctx:set_line_width (3.0)
ctx:move_to (bar_space * ctrl[1], h - 3)
ctx:rel_line_to (bar_width, 0)
ctx:stroke ()
-- display ball
ctx:move_to (state[1] * w, state[2] * (h - 5))
ctx:close_path ()
ctx:stroke ()
return {w, h}
end
|