rt300@9: /* rt300@9: * Copyright (c) 2011 Dan Wilcox rt300@9: * rt300@9: * BSD Simplified License. rt300@9: * For information on usage and redistribution, and for a DISCLAIMER OF ALL rt300@9: * WARRANTIES, see the file, "LICENSE.txt," in this distribution. rt300@9: * rt300@9: * See https://github.com/danomatika/ofxPd for documentation rt300@9: * rt300@9: */ rt300@9: #include "AppCore.h" rt300@9: rt300@9: //-------------------------------------------------------------- rt300@9: void AppCore::setup(const int numOutChannels, const int numInChannels, rt300@9: const int sampleRate, const int ticksPerBuffer) { rt300@9: rt300@9: ofSetFrameRate(60); rt300@9: ofSetVerticalSync(true); rt300@9: //ofSetLogLevel(OF_LOG_VERBOSE); rt300@9: rt300@9: // double check where we are ... rt300@9: cout << ofFilePath::getCurrentWorkingDirectory() << endl; rt300@9: rt300@9: if(!pd.init(numOutChannels, numInChannels, sampleRate, ticksPerBuffer)) { rt300@9: ofLog(OF_LOG_ERROR, "Could not init pd"); rt300@9: OF_EXIT_APP(1); rt300@9: } rt300@9: midiChan = 1; // midi channels are 1-16 rt300@9: rt300@9: // subscribe to receive source names rt300@9: pd.subscribe("toOF"); rt300@9: pd.subscribe("env"); rt300@9: rt300@9: // add message receiver, disables polling (see processEvents) rt300@9: pd.addReceiver(*this); // automatically receives from all subscribed sources rt300@9: pd.ignore(*this, "env"); // don't receive from "env" rt300@9: //pd.ignore(*this); // ignore all sources rt300@9: //pd.receive(*this, "toOF"); // receive only from "toOF" rt300@9: rt300@9: // add midi receiver rt300@39: //pd.addMidiReceiver(*this); // automatically receives from all channels rt300@9: //pd.ignoreMidi(*this, 1); // ignore midi channel 1 rt300@39: pd.ignoreMidi(*this); // ignore all channels rt300@9: //pd.receiveMidi(*this, 1); // receive only from channel 1 rt300@9: rt300@9: // add the data/pd folder to the search path rt300@9: pd.addToSearchPath("pd"); rt300@9: rt300@9: // audio processing on rt300@9: pd.start(); rt300@9: rt300@9: // open patch rt300@45: patchName = "synth10param.pd"; rt300@45: Patch patch = pd.openPatch(patchName); rt300@9: cout << patch << endl; rt300@9: rt300@9: rt300@9: } rt300@9: rt300@9: //-------------------------------------------------------------- rt300@9: void AppCore::update() { rt300@9: ofBackground(100, 100, 100); rt300@9: rt300@9: // update scope array from pd rt300@9: pd.readArray("scope", scopeArray); rt300@9: } rt300@9: rt300@9: //-------------------------------------------------------------- rt300@9: void AppCore::draw() { rt300@9: rt300@9: // draw scope rt300@9: ofSetColor(0, 255, 0); rt300@9: ofSetRectMode(OF_RECTMODE_CENTER); rt300@9: float x = 0, y = ofGetHeight()/2; rt300@9: float w = ofGetWidth() / (float) scopeArray.size(), h = ofGetHeight()/2; rt300@9: for(int i = 0; i < scopeArray.size()-1; ++i) { rt300@9: ofLine(x, y+scopeArray[i]*h, x+w, y+scopeArray[i+1]*h); rt300@9: x += w; rt300@9: } rt300@9: } rt300@9: rt300@9: //-------------------------------------------------------------- rt300@27: void AppCore::exit() { rt300@27: pd.stop(); rt300@27: } rt300@9: rt300@9: //-------------------------------------------------------------- rt300@9: void AppCore::playTone(int pitch) { rt300@9: pd << StartMessage() << "pitch" << pitch << FinishList("tone") << Bang("tone"); rt300@9: } rt300@9: rt300@9: //-------------------------------------------------------------- rt300@9: void AppCore::keyPressed (int key) { rt300@9: rt300@9: switch(key) { rt300@9: rt300@9: case 'a': rt300@9: playTone(60); rt300@9: break; rt300@9: case 'w': rt300@9: playTone(61); rt300@9: break; rt300@9: case 's': rt300@9: playTone(62); rt300@9: break; rt300@9: case 'e': rt300@9: playTone(63); rt300@9: break; rt300@9: case 'd': rt300@9: playTone(64); rt300@9: break; rt300@9: case 'f': rt300@9: playTone(65); rt300@9: break; rt300@9: case 't': rt300@9: playTone(66); rt300@9: break; rt300@9: case 'g': rt300@9: playTone(67); rt300@9: break; rt300@9: case 'y': rt300@9: playTone(68); rt300@9: break; rt300@9: case 'h': rt300@9: playTone(69); rt300@9: break; rt300@9: case 'u': rt300@9: playTone(70); rt300@9: break; rt300@9: case 'j': rt300@9: playTone(71); rt300@9: break; rt300@9: case 'k': rt300@9: playTone(72); rt300@9: break; rt300@9: rt300@9: case ' ': rt300@9: if(pd.isReceiving(*this, "env")) { rt300@9: pd.ignore(*this, "env"); rt300@9: cout << "ignoring env" << endl; rt300@9: } rt300@9: else { rt300@9: pd.receive(*this, "env"); rt300@9: cout << "receiving from env" << endl; rt300@9: } rt300@9: break; rt300@9: rt300@9: default: rt300@9: break; rt300@9: } rt300@9: } rt300@9: rt300@9: //-------------------------------------------------------------- rt300@9: void AppCore::audioReceived(float * input, int bufferSize, int nChannels) { rt300@9: pd.audioIn(input, bufferSize, nChannels); rt300@9: } rt300@9: rt300@9: //-------------------------------------------------------------- rt300@9: void AppCore::audioRequested(float * output, int bufferSize, int nChannels) { rt300@9: pd.audioOut(output, bufferSize, nChannels); rt300@9: } rt300@9: rt300@9: //-------------------------------------------------------------- rt300@9: void AppCore::print(const std::string& message) { rt300@9: cout << message << endl; rt300@9: } rt300@9: rt300@9: //-------------------------------------------------------------- rt300@9: void AppCore::receiveBang(const std::string& dest) { rt300@9: cout << "OF: bang " << dest << endl; rt300@9: } rt300@9: rt300@9: void AppCore::receiveFloat(const std::string& dest, float value) { rt300@9: cout << "OF: float " << dest << ": " << value << endl; rt300@9: } rt300@9: rt300@9: void AppCore::receiveSymbol(const std::string& dest, const std::string& symbol) { rt300@9: cout << "OF: symbol " << dest << ": " << symbol << endl; rt300@9: } rt300@9: rt300@9: void AppCore::receiveList(const std::string& dest, const List& list) { rt300@9: cout << "OF: list " << dest << ": "; rt300@9: rt300@9: // step through the list rt300@9: for(int i = 0; i < list.len(); ++i) { rt300@9: if(list.isFloat(i)) rt300@9: cout << list.getFloat(i) << " "; rt300@9: else if(list.isSymbol(i)) rt300@9: cout << list.getSymbol(i) << " "; rt300@9: } rt300@9: rt300@9: // you can also use the built in toString function or simply stream it out rt300@9: // cout << list.toString(); rt300@9: // cout << list; rt300@9: rt300@9: // print an OSC-style type string rt300@9: cout << list.types() << endl; rt300@9: } rt300@9: rt300@9: void AppCore::receiveMessage(const std::string& dest, const std::string& msg, const List& list) { rt300@9: cout << "OF: message " << dest << ": " << msg << " " << list.toString() << list.types() << endl; rt300@9: } rt300@9: rt300@9: //-------------------------------------------------------------- rt300@9: void AppCore::receiveNoteOn(const int channel, const int pitch, const int velocity) { rt300@9: cout << "OF MIDI: note on: " << channel << " " << pitch << " " << velocity << endl; rt300@9: } rt300@9: rt300@9: void AppCore::receiveControlChange(const int channel, const int controller, const int value) { rt300@9: cout << "OF MIDI: control change: " << channel << " " << controller << " " << value << endl; rt300@9: } rt300@9: rt300@9: // note: pgm nums are 1-128 to match pd rt300@9: void AppCore::receiveProgramChange(const int channel, const int value) { rt300@9: cout << "OF MIDI: program change: " << channel << " " << value << endl; rt300@9: } rt300@9: rt300@9: void AppCore::receivePitchBend(const int channel, const int value) { rt300@9: cout << "OF MIDI: pitch bend: " << channel << " " << value << endl; rt300@9: } rt300@9: rt300@9: void AppCore::receiveAftertouch(const int channel, const int value) { rt300@9: cout << "OF MIDI: aftertouch: " << channel << " " << value << endl; rt300@9: } rt300@9: rt300@9: void AppCore::receivePolyAftertouch(const int channel, const int pitch, const int value) { rt300@9: cout << "OF MIDI: poly aftertouch: " << channel << " " << pitch << " " << value << endl; rt300@9: } rt300@9: rt300@9: // note: pd adds +2 to the port num, so sending to port 3 in pd to [midiout], rt300@9: // shows up at port 1 in ofxPd rt300@9: void AppCore::receiveMidiByte(const int port, const int byte) { rt300@9: cout << "OF MIDI: midi byte: " << port << " " << byte << endl; rt300@9: } rt300@9: rt300@9: //-------------------------------------------------------------- rt300@9: void AppCore::processEvents() { rt300@9: rt300@9: cout << "Number of waiting messages: " << pd.numMessages() << endl; rt300@9: rt300@9: while(pd.numMessages() > 0) { rt300@9: Message& msg = pd.nextMessage(); rt300@9: rt300@9: switch(msg.type) { rt300@9: rt300@9: case pd::PRINT: rt300@9: cout << "OF: " << msg.symbol << endl; rt300@9: break; rt300@9: rt300@9: // events rt300@9: case pd::BANG: rt300@9: cout << "OF: bang " << msg.dest << endl; rt300@9: break; rt300@9: case pd::FLOAT: rt300@9: cout << "OF: float " << msg.dest << ": " << msg.num << endl; rt300@9: break; rt300@9: case pd::SYMBOL: rt300@9: cout << "OF: symbol " << msg.dest << ": " << msg.symbol << endl; rt300@9: break; rt300@9: case pd::LIST: rt300@9: cout << "OF: list " << msg.list << msg.list.types() << endl; rt300@9: break; rt300@9: case pd::MESSAGE: rt300@9: cout << "OF: message " << msg.dest << ": " << msg.symbol << " " rt300@9: << msg.list << msg.list.types() << endl; rt300@9: break; rt300@9: rt300@9: // midi rt300@9: case pd::NOTE_ON: rt300@9: cout << "OF MIDI: note on: " << msg.channel << " " rt300@9: << msg.pitch << " " << msg.velocity << endl; rt300@9: break; rt300@9: case pd::CONTROL_CHANGE: rt300@9: cout << "OF MIDI: control change: " << msg.channel rt300@9: << " " << msg.controller << " " << msg.value << endl; rt300@9: break; rt300@9: case pd::PROGRAM_CHANGE: rt300@9: cout << "OF MIDI: program change: " << msg.channel << " " rt300@9: << msg.value << endl; rt300@9: break; rt300@9: case pd::PITCH_BEND: rt300@9: cout << "OF MIDI: pitch bend: " << msg.channel << " " rt300@9: << msg.value << endl; rt300@9: break; rt300@9: case pd::AFTERTOUCH: rt300@9: cout << "OF MIDI: aftertouch: " << msg.channel << " " rt300@9: << msg.value << endl; rt300@9: break; rt300@9: case pd::POLY_AFTERTOUCH: rt300@9: cout << "OF MIDI: poly aftertouch: " << msg.channel << " " rt300@9: << msg.pitch << " " << msg.value << endl; rt300@9: break; rt300@9: case pd::BYTE: rt300@9: cout << "OF MIDI: midi byte: " << msg.port << " 0x" rt300@9: << hex << (int) msg.byte << dec << endl; rt300@9: break; rt300@9: rt300@9: case pd::NONE: rt300@9: cout << "OF: NONE ... empty message" << endl; rt300@9: break; rt300@9: } rt300@9: } rt300@9: }