-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtest.lua
221 lines (180 loc) · 5.46 KB
/
test.lua
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
if os.getenv('LOCAL_LUA_DEBUGGER_VSCODE') == '1' then
require('lldebugger').start()
end
local ext = {
Linux = 'so'
, Windows = 'dll'
, OSX = 'dylib'
}
local ffi = require('ffi')
package.cpath = './?.'..ext[ffi.os]..';'..package.cpath
local Pd = require('luapd') ---@type Pd
local inChannels ,outChannels ,sampleRate ,queued
= 1 ,2 ,48000 ,false
-- our pd engine
local pd = Pd.Base()
-- custom receiver object for messages and midi
local obj = Pd.Object{
-- message callbacks
print = function(msg) print('Lua: print ' ..msg) end
, bang = function(dest) print('Lua: bang ' ..dest) end
, float = function(dest, num) print('Lua: float ' ..dest..': '..num) end
, symbol = function(dest, sym) print('Lua: symbol '..dest..': '..sym) end
, list = function(dest, list)
print('Lua: list '..dest..': '..table.concat(list, ' '))
end
, message = function(dest, msg, list)
print('Lua: message '..dest..': |'..msg..'|'..table.concat(list, ' '))
end
-- midi callbacks
, noteOn = function(channel, pitch, velocity)
print('Lua MIDI: note on: '..channel..' '..pitch..' '..velocity)
end
, controlChange = function(channel, controller, value)
print('Lua MIDI: control change: '..channel..' '..controller..' '..value)
end
, programChange = function(channel, value)
print('Lua MIDI: program change: '..channel..' '..value)
end
, pitchBend = function(channel, value)
print('Lua MIDI: pitch bend: '..channel..' '..value)
end
, aftertouch = function(channel, value)
print('Lua MIDI: aftertouch: '..channel..' '..value)
end
, polyAftertouch = function(channel, pitch, value)
print('Lua MIDI: poly aftertouch: '..channel..' '..pitch..' '..value)
end
, midiByte = function(port, byte)
print('Lua MIDI: midi byte: '..port..' '..byte)
end
}
local block = pd.blockSize() -- or Pd.Base.blockSize()
local inbuf = Pd.Array(block * inChannels)
local outbuf = Pd.Array(block * outChannels)
-- init pd
--
-- set 4th arg to true for queued message passing using an internal ringbuffer
--
-- in this test, messages should return immediately when not queued otherwise
-- they should all return at once when pd is processing at the end of this
-- function
--
if not pd:init(inChannels, outChannels, sampleRate, queued) then
print('Could not init pd')
os.exit()
end
local midiChan = 1 -- midi channels are 0-15
-- subscribe to receive source names
pd:subscribe('toLua')
pd:subscribe('env')
-- set receivers
pd:setReceiver(obj)
pd:setMidiReceiver(obj)
-- add the data/pd folder to the search path
pd:addToSearchPath('pd/lib')
-- audio processing on
pd:computeAudio(true)
print('BEGIN Patch Test')
-- open patch
local patch = pd:openPatch('pd/test.pd', '.')
-- close patch
pd:closePatch(patch)
-- open patch again
patch = pd:openPatch(patch)
-- process any received messages
--
-- in a normal case (not a test like this), you would call this in
-- your application main loop
pd:processFloat(1, inbuf(), outbuf())
-- pd:receiveMessages()
print('FINISH Patch Test\n')
-- (re)assign a callback function
function obj.print(msg)
print('foobar: '..msg)
end
-- (re)assign multiple callback functions
obj:setFuncs{
noteOn = function(channel, pitch, velocity)
print('noteOn: '..channel..' '..pitch..' '..velocity)
end
, midiByte = function(port, byte)
print('\nfoo-midi-byte: '..port..' '..byte..'\n')
end
}
print('BEGIN Message Test')
-- test basic atoms
pd:sendBang ('fromLua')
pd:sendFloat ('fromLua', 100)
pd:sendSymbol ('fromLua', 'test string')
-- send a list
pd:startMessage()
pd:addFloat (1.23)
pd:addSymbol ('a symbol')
pd:finishList('fromLua')
-- send a message to the $0 receiver ie $0-toOF
pd:startMessage()
pd:addAtom(1.23)
pd:addAtom('a symbol')
pd:finishList(patch:dollarZeroStr()..'-fromLua')
-- send a list using a table
local t = {1.23, 'sent from a Lua table'}
pd:sendList ('fromLua', t)
pd:sendMessage ('fromLua', 'msg', t)
print('FINISH Message Test\n')
print('BEGIN MIDI Test')
-- send functions
pd:sendNoteOn (midiChan, 60)
pd:sendControlChange (midiChan, 0, 64)
pd:sendProgramChange (midiChan, 100)
pd:sendPitchBend (midiChan, 2000)
pd:sendAftertouch (midiChan, 100)
pd:sendPolyAftertouch (midiChan, 64, 100)
pd:sendMidiByte (0, 239)
pd:sendSysex (0, 239)
pd:sendSysRealTime (0, 239)
print('FINISH MIDI Test\n')
print('BEGIN Array Test')
-- array check length
print('array1 len: '..pd:arraySize('array1'))
local array1 = Pd.Array()
local function readArray1()
pd:readArray('array1', array1)
local msg = 'array1'
for i=1, #array1 do
msg = msg..' '..array1[i]
end
print(msg)
end
-- read array
readArray1()
-- write array
for i=1, #array1 do
array1[i] = i
end
pd:writeArray('array1', array1);
readArray1()
-- clear array
pd:clearArray('array1', 10);
readArray1()
print('FINISH Array Test\n')
print('BEGIN PD Test')
pd:sendSymbol('fromLua', 'test');
print('FINISH PD Test\n')
-- play a tone by sending a list
-- [list tone pitch 72 (
pd:sendList('tone', {'pitch', 72});
pd:sendBang('tone');
-- now run pd for ten seconds (logical time)
-- you should see all the messages from pd print now
-- since processFloat actually runs the pd dsp engine and the recieve
-- functions pass messages to our PdObject
print('Processing PD')
for _ = 0, (10 * sampleRate / block) do
pd:processFloat(1, inbuf(), outbuf())
-- pd:receiveMessages()
-- pd:receiveMidi()
end
-- be nice and clean up on exit
pd:closePatch(patch)
pd:computeAudio(false)