rt300@9
|
1 /*
|
rt300@9
|
2 * Copyright (c) 2011 Dan Wilcox <danomatika@gmail.com>
|
rt300@9
|
3 *
|
rt300@9
|
4 * BSD Simplified License.
|
rt300@9
|
5 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
|
rt300@9
|
6 * WARRANTIES, see the file, "LICENSE.txt," in this distribution.
|
rt300@9
|
7 *
|
rt300@9
|
8 * See https://github.com/danomatika/ofxPd for documentation
|
rt300@9
|
9 *
|
rt300@9
|
10 */
|
rt300@9
|
11 #include "AppCore.h"
|
rt300@9
|
12
|
rt300@9
|
13 //--------------------------------------------------------------
|
rt300@9
|
14 void AppCore::setup(const int numOutChannels, const int numInChannels,
|
rt300@9
|
15 const int sampleRate, const int ticksPerBuffer) {
|
rt300@9
|
16
|
rt300@9
|
17 ofSetFrameRate(60);
|
rt300@9
|
18 ofSetVerticalSync(true);
|
rt300@9
|
19 //ofSetLogLevel(OF_LOG_VERBOSE);
|
rt300@9
|
20
|
rt300@9
|
21 // double check where we are ...
|
rt300@9
|
22 cout << ofFilePath::getCurrentWorkingDirectory() << endl;
|
rt300@9
|
23
|
rt300@9
|
24 if(!pd.init(numOutChannels, numInChannels, sampleRate, ticksPerBuffer)) {
|
rt300@9
|
25 ofLog(OF_LOG_ERROR, "Could not init pd");
|
rt300@9
|
26 OF_EXIT_APP(1);
|
rt300@9
|
27 }
|
rt300@9
|
28
|
rt300@9
|
29 midiChan = 1; // midi channels are 1-16
|
rt300@9
|
30
|
rt300@9
|
31 // subscribe to receive source names
|
rt300@9
|
32 pd.subscribe("toOF");
|
rt300@9
|
33 pd.subscribe("env");
|
rt300@9
|
34
|
rt300@9
|
35 // add message receiver, disables polling (see processEvents)
|
rt300@9
|
36 pd.addReceiver(*this); // automatically receives from all subscribed sources
|
rt300@9
|
37 pd.ignore(*this, "env"); // don't receive from "env"
|
rt300@9
|
38 //pd.ignore(*this); // ignore all sources
|
rt300@9
|
39 //pd.receive(*this, "toOF"); // receive only from "toOF"
|
rt300@9
|
40
|
rt300@9
|
41 // add midi receiver
|
rt300@9
|
42 pd.addMidiReceiver(*this); // automatically receives from all channels
|
rt300@9
|
43 //pd.ignoreMidi(*this, 1); // ignore midi channel 1
|
rt300@9
|
44 //pd.ignoreMidi(*this); // ignore all channels
|
rt300@9
|
45 //pd.receiveMidi(*this, 1); // receive only from channel 1
|
rt300@9
|
46
|
rt300@9
|
47 // add the data/pd folder to the search path
|
rt300@9
|
48 pd.addToSearchPath("pd");
|
rt300@9
|
49
|
rt300@9
|
50 // audio processing on
|
rt300@9
|
51 pd.start();
|
rt300@9
|
52
|
rt300@9
|
53 // open patch
|
rt300@9
|
54 Patch patch = pd.openPatch("mytest.pd");
|
rt300@9
|
55 cout << patch << endl;
|
rt300@9
|
56
|
rt300@9
|
57
|
rt300@9
|
58 }
|
rt300@9
|
59
|
rt300@9
|
60 //--------------------------------------------------------------
|
rt300@9
|
61 void AppCore::update() {
|
rt300@9
|
62 ofBackground(100, 100, 100);
|
rt300@9
|
63
|
rt300@9
|
64 // update scope array from pd
|
rt300@9
|
65 pd.readArray("scope", scopeArray);
|
rt300@9
|
66 }
|
rt300@9
|
67
|
rt300@9
|
68 //--------------------------------------------------------------
|
rt300@9
|
69 void AppCore::draw() {
|
rt300@9
|
70
|
rt300@9
|
71 // draw scope
|
rt300@9
|
72 ofSetColor(0, 255, 0);
|
rt300@9
|
73 ofSetRectMode(OF_RECTMODE_CENTER);
|
rt300@9
|
74 float x = 0, y = ofGetHeight()/2;
|
rt300@9
|
75 float w = ofGetWidth() / (float) scopeArray.size(), h = ofGetHeight()/2;
|
rt300@9
|
76 for(int i = 0; i < scopeArray.size()-1; ++i) {
|
rt300@9
|
77 ofLine(x, y+scopeArray[i]*h, x+w, y+scopeArray[i+1]*h);
|
rt300@9
|
78 x += w;
|
rt300@9
|
79 }
|
rt300@9
|
80 }
|
rt300@9
|
81
|
rt300@9
|
82 //--------------------------------------------------------------
|
rt300@9
|
83 void AppCore::exit() {}
|
rt300@9
|
84
|
rt300@9
|
85 //--------------------------------------------------------------
|
rt300@9
|
86 void AppCore::playTone(int pitch) {
|
rt300@9
|
87 pd << StartMessage() << "pitch" << pitch << FinishList("tone") << Bang("tone");
|
rt300@9
|
88 }
|
rt300@9
|
89
|
rt300@9
|
90 //--------------------------------------------------------------
|
rt300@9
|
91 void AppCore::keyPressed (int key) {
|
rt300@9
|
92
|
rt300@9
|
93 switch(key) {
|
rt300@9
|
94
|
rt300@9
|
95 case 'a':
|
rt300@9
|
96 playTone(60);
|
rt300@9
|
97 break;
|
rt300@9
|
98 case 'w':
|
rt300@9
|
99 playTone(61);
|
rt300@9
|
100 break;
|
rt300@9
|
101 case 's':
|
rt300@9
|
102 playTone(62);
|
rt300@9
|
103 break;
|
rt300@9
|
104 case 'e':
|
rt300@9
|
105 playTone(63);
|
rt300@9
|
106 break;
|
rt300@9
|
107 case 'd':
|
rt300@9
|
108 playTone(64);
|
rt300@9
|
109 break;
|
rt300@9
|
110 case 'f':
|
rt300@9
|
111 playTone(65);
|
rt300@9
|
112 break;
|
rt300@9
|
113 case 't':
|
rt300@9
|
114 playTone(66);
|
rt300@9
|
115 break;
|
rt300@9
|
116 case 'g':
|
rt300@9
|
117 playTone(67);
|
rt300@9
|
118 break;
|
rt300@9
|
119 case 'y':
|
rt300@9
|
120 playTone(68);
|
rt300@9
|
121 break;
|
rt300@9
|
122 case 'h':
|
rt300@9
|
123 playTone(69);
|
rt300@9
|
124 break;
|
rt300@9
|
125 case 'u':
|
rt300@9
|
126 playTone(70);
|
rt300@9
|
127 break;
|
rt300@9
|
128 case 'j':
|
rt300@9
|
129 playTone(71);
|
rt300@9
|
130 break;
|
rt300@9
|
131 case 'k':
|
rt300@9
|
132 playTone(72);
|
rt300@9
|
133 break;
|
rt300@9
|
134
|
rt300@9
|
135 case ' ':
|
rt300@9
|
136 if(pd.isReceiving(*this, "env")) {
|
rt300@9
|
137 pd.ignore(*this, "env");
|
rt300@9
|
138 cout << "ignoring env" << endl;
|
rt300@9
|
139 }
|
rt300@9
|
140 else {
|
rt300@9
|
141 pd.receive(*this, "env");
|
rt300@9
|
142 cout << "receiving from env" << endl;
|
rt300@9
|
143 }
|
rt300@9
|
144 break;
|
rt300@9
|
145
|
rt300@9
|
146 default:
|
rt300@9
|
147 break;
|
rt300@9
|
148 }
|
rt300@9
|
149 }
|
rt300@9
|
150
|
rt300@9
|
151 //--------------------------------------------------------------
|
rt300@9
|
152 void AppCore::audioReceived(float * input, int bufferSize, int nChannels) {
|
rt300@9
|
153 pd.audioIn(input, bufferSize, nChannels);
|
rt300@9
|
154 }
|
rt300@9
|
155
|
rt300@9
|
156 //--------------------------------------------------------------
|
rt300@9
|
157 void AppCore::audioRequested(float * output, int bufferSize, int nChannels) {
|
rt300@9
|
158 pd.audioOut(output, bufferSize, nChannels);
|
rt300@9
|
159 }
|
rt300@9
|
160
|
rt300@9
|
161 //--------------------------------------------------------------
|
rt300@9
|
162 void AppCore::print(const std::string& message) {
|
rt300@9
|
163 cout << message << endl;
|
rt300@9
|
164 }
|
rt300@9
|
165
|
rt300@9
|
166 //--------------------------------------------------------------
|
rt300@9
|
167 void AppCore::receiveBang(const std::string& dest) {
|
rt300@9
|
168 cout << "OF: bang " << dest << endl;
|
rt300@9
|
169 }
|
rt300@9
|
170
|
rt300@9
|
171 void AppCore::receiveFloat(const std::string& dest, float value) {
|
rt300@9
|
172 cout << "OF: float " << dest << ": " << value << endl;
|
rt300@9
|
173 }
|
rt300@9
|
174
|
rt300@9
|
175 void AppCore::receiveSymbol(const std::string& dest, const std::string& symbol) {
|
rt300@9
|
176 cout << "OF: symbol " << dest << ": " << symbol << endl;
|
rt300@9
|
177 }
|
rt300@9
|
178
|
rt300@9
|
179 void AppCore::receiveList(const std::string& dest, const List& list) {
|
rt300@9
|
180 cout << "OF: list " << dest << ": ";
|
rt300@9
|
181
|
rt300@9
|
182 // step through the list
|
rt300@9
|
183 for(int i = 0; i < list.len(); ++i) {
|
rt300@9
|
184 if(list.isFloat(i))
|
rt300@9
|
185 cout << list.getFloat(i) << " ";
|
rt300@9
|
186 else if(list.isSymbol(i))
|
rt300@9
|
187 cout << list.getSymbol(i) << " ";
|
rt300@9
|
188 }
|
rt300@9
|
189
|
rt300@9
|
190 // you can also use the built in toString function or simply stream it out
|
rt300@9
|
191 // cout << list.toString();
|
rt300@9
|
192 // cout << list;
|
rt300@9
|
193
|
rt300@9
|
194 // print an OSC-style type string
|
rt300@9
|
195 cout << list.types() << endl;
|
rt300@9
|
196 }
|
rt300@9
|
197
|
rt300@9
|
198 void AppCore::receiveMessage(const std::string& dest, const std::string& msg, const List& list) {
|
rt300@9
|
199 cout << "OF: message " << dest << ": " << msg << " " << list.toString() << list.types() << endl;
|
rt300@9
|
200 }
|
rt300@9
|
201
|
rt300@9
|
202 //--------------------------------------------------------------
|
rt300@9
|
203 void AppCore::receiveNoteOn(const int channel, const int pitch, const int velocity) {
|
rt300@9
|
204 cout << "OF MIDI: note on: " << channel << " " << pitch << " " << velocity << endl;
|
rt300@9
|
205 }
|
rt300@9
|
206
|
rt300@9
|
207 void AppCore::receiveControlChange(const int channel, const int controller, const int value) {
|
rt300@9
|
208 cout << "OF MIDI: control change: " << channel << " " << controller << " " << value << endl;
|
rt300@9
|
209 }
|
rt300@9
|
210
|
rt300@9
|
211 // note: pgm nums are 1-128 to match pd
|
rt300@9
|
212 void AppCore::receiveProgramChange(const int channel, const int value) {
|
rt300@9
|
213 cout << "OF MIDI: program change: " << channel << " " << value << endl;
|
rt300@9
|
214 }
|
rt300@9
|
215
|
rt300@9
|
216 void AppCore::receivePitchBend(const int channel, const int value) {
|
rt300@9
|
217 cout << "OF MIDI: pitch bend: " << channel << " " << value << endl;
|
rt300@9
|
218 }
|
rt300@9
|
219
|
rt300@9
|
220 void AppCore::receiveAftertouch(const int channel, const int value) {
|
rt300@9
|
221 cout << "OF MIDI: aftertouch: " << channel << " " << value << endl;
|
rt300@9
|
222 }
|
rt300@9
|
223
|
rt300@9
|
224 void AppCore::receivePolyAftertouch(const int channel, const int pitch, const int value) {
|
rt300@9
|
225 cout << "OF MIDI: poly aftertouch: " << channel << " " << pitch << " " << value << endl;
|
rt300@9
|
226 }
|
rt300@9
|
227
|
rt300@9
|
228 // note: pd adds +2 to the port num, so sending to port 3 in pd to [midiout],
|
rt300@9
|
229 // shows up at port 1 in ofxPd
|
rt300@9
|
230 void AppCore::receiveMidiByte(const int port, const int byte) {
|
rt300@9
|
231 cout << "OF MIDI: midi byte: " << port << " " << byte << endl;
|
rt300@9
|
232 }
|
rt300@9
|
233
|
rt300@9
|
234 //--------------------------------------------------------------
|
rt300@9
|
235 void AppCore::processEvents() {
|
rt300@9
|
236
|
rt300@9
|
237 cout << "Number of waiting messages: " << pd.numMessages() << endl;
|
rt300@9
|
238
|
rt300@9
|
239 while(pd.numMessages() > 0) {
|
rt300@9
|
240 Message& msg = pd.nextMessage();
|
rt300@9
|
241
|
rt300@9
|
242 switch(msg.type) {
|
rt300@9
|
243
|
rt300@9
|
244 case pd::PRINT:
|
rt300@9
|
245 cout << "OF: " << msg.symbol << endl;
|
rt300@9
|
246 break;
|
rt300@9
|
247
|
rt300@9
|
248 // events
|
rt300@9
|
249 case pd::BANG:
|
rt300@9
|
250 cout << "OF: bang " << msg.dest << endl;
|
rt300@9
|
251 break;
|
rt300@9
|
252 case pd::FLOAT:
|
rt300@9
|
253 cout << "OF: float " << msg.dest << ": " << msg.num << endl;
|
rt300@9
|
254 break;
|
rt300@9
|
255 case pd::SYMBOL:
|
rt300@9
|
256 cout << "OF: symbol " << msg.dest << ": " << msg.symbol << endl;
|
rt300@9
|
257 break;
|
rt300@9
|
258 case pd::LIST:
|
rt300@9
|
259 cout << "OF: list " << msg.list << msg.list.types() << endl;
|
rt300@9
|
260 break;
|
rt300@9
|
261 case pd::MESSAGE:
|
rt300@9
|
262 cout << "OF: message " << msg.dest << ": " << msg.symbol << " "
|
rt300@9
|
263 << msg.list << msg.list.types() << endl;
|
rt300@9
|
264 break;
|
rt300@9
|
265
|
rt300@9
|
266 // midi
|
rt300@9
|
267 case pd::NOTE_ON:
|
rt300@9
|
268 cout << "OF MIDI: note on: " << msg.channel << " "
|
rt300@9
|
269 << msg.pitch << " " << msg.velocity << endl;
|
rt300@9
|
270 break;
|
rt300@9
|
271 case pd::CONTROL_CHANGE:
|
rt300@9
|
272 cout << "OF MIDI: control change: " << msg.channel
|
rt300@9
|
273 << " " << msg.controller << " " << msg.value << endl;
|
rt300@9
|
274 break;
|
rt300@9
|
275 case pd::PROGRAM_CHANGE:
|
rt300@9
|
276 cout << "OF MIDI: program change: " << msg.channel << " "
|
rt300@9
|
277 << msg.value << endl;
|
rt300@9
|
278 break;
|
rt300@9
|
279 case pd::PITCH_BEND:
|
rt300@9
|
280 cout << "OF MIDI: pitch bend: " << msg.channel << " "
|
rt300@9
|
281 << msg.value << endl;
|
rt300@9
|
282 break;
|
rt300@9
|
283 case pd::AFTERTOUCH:
|
rt300@9
|
284 cout << "OF MIDI: aftertouch: " << msg.channel << " "
|
rt300@9
|
285 << msg.value << endl;
|
rt300@9
|
286 break;
|
rt300@9
|
287 case pd::POLY_AFTERTOUCH:
|
rt300@9
|
288 cout << "OF MIDI: poly aftertouch: " << msg.channel << " "
|
rt300@9
|
289 << msg.pitch << " " << msg.value << endl;
|
rt300@9
|
290 break;
|
rt300@9
|
291 case pd::BYTE:
|
rt300@9
|
292 cout << "OF MIDI: midi byte: " << msg.port << " 0x"
|
rt300@9
|
293 << hex << (int) msg.byte << dec << endl;
|
rt300@9
|
294 break;
|
rt300@9
|
295
|
rt300@9
|
296 case pd::NONE:
|
rt300@9
|
297 cout << "OF: NONE ... empty message" << endl;
|
rt300@9
|
298 break;
|
rt300@9
|
299 }
|
rt300@9
|
300 }
|
rt300@9
|
301 }
|