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