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