├── .gitignore ├── bindings └── max │ ├── MaxPiPo.h │ ├── MaxPiPoHost.cpp │ ├── MaxPiPoHost.h │ ├── maxmimo.h │ ├── maxmimohost.cpp │ └── maxmimohost.h ├── doc └── pipo.doxygen ├── examples ├── jucepipo │ ├── PiPoGain-osc.maxpat │ ├── PiPoGain-osc.pd │ ├── PiPoGain.h │ ├── PiPoGain.xcodeproj │ │ └── project.pbxproj │ ├── PipoGain.cpp │ └── PipoGain.dylib └── maxpipo │ ├── PiPoGain.h │ ├── external.plist │ ├── maxpipo-example-debug.xcconfig │ ├── maxpipo-example-release.xcconfig │ ├── maxpipo-example-shared.xcconfig │ ├── maxpipo-example.xcodeproj │ └── project.pbxproj │ ├── pipo.gain.cpp │ ├── pipo.gain.maxhelp │ └── pipo.gain.mxo │ └── Contents │ ├── Info.plist │ ├── MacOS │ └── pipo.gain │ └── PkgInfo ├── makefile ├── readme.md └── src ├── PiPo.h ├── PiPoParallel.h ├── PiPoSequence.h ├── RingBuffer.h ├── host ├── PiPoChain.h ├── PiPoCollection.h ├── PiPoGraph.h ├── PiPoHost.cpp ├── PiPoHost.h ├── PiPoModule.h ├── PiPoModuleClass.h ├── PiPoOp.h └── mimo_host.h └── mimo.h /.gitignore: -------------------------------------------------------------------------------- 1 | **/.DS_Store 2 | **/Thumbs.db 3 | 4 | examples/maxpipo/maxpipo-example.xcodeproj/* 5 | !examples/maxpipo/maxpipo-example.xcodeproj/project.pbxproj 6 | examples/jucepipo/PiPoGain.xcodeproj/* 7 | !examples/jucepipo/PiPoGain.xcodeproj/project.pbxproj 8 | examples/maxpipo/DerivedData 9 | -------------------------------------------------------------------------------- /bindings/max/MaxPiPo.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @file MaxPiPo.h 4 | * @author Norbert.Schnell@ircam.fr 5 | * 6 | * @brief Max/MSP extension of Plugin Interface for Processing Objects 7 | * 8 | * Copyright (C) 2012-2014 by IRCAM – Centre Pompidou, Paris, France. 9 | * All rights reserved. 10 | * 11 | */ 12 | #ifndef _MAX_PIPO_H_ 13 | #define _MAX_PIPO_H_ 14 | 15 | #include "PiPo.h" 16 | #include "ext.h" 17 | #include "ext_obex.h" 18 | #include "ext_obex_util.h" 19 | 20 | #ifdef PIPO_MAX_WITH_DOC 21 | #include "ircammaxcapi.h" 22 | #include 23 | #include 24 | #endif // PIPO_MAX_WITH_DOC 25 | 26 | typedef struct MaxPiPoSt { 27 | t_object head; 28 | PiPo *pipo; 29 | 30 | #ifdef PIPO_MAX_WITH_DOC 31 | void *dummy_attr[2]; 32 | long dummy_attr_long; 33 | 34 | t_symbol classdigest; 35 | t_symbol classdescription; 36 | t_symbol classseealso; 37 | t_symbol externalversion; 38 | #endif // PIPO_MAX_WITH_DOC 39 | 40 | } MaxPiPoT; 41 | 42 | #ifdef PIPO_MAX_WITH_DOC 43 | 44 | #define atom_isnum(a) ((a)->a_type == A_LONG || (a)->a_type == A_FLOAT) 45 | #define atom_issym(a) ((a)->a_type == A_SYM) 46 | #define atom_isobj(p) ((p)->a_type == A_OBJ) 47 | #define mysneg(s) ((s)->s_name) 48 | 49 | #define atom_islong(p) ((p)->a_type == A_LONG) 50 | #define atom_isfloat(p) ((p)->a_type == A_FLOAT) 51 | #define atom_getnum(p) (((p)->a_type == A_FLOAT)? (double)((p)->a_w.w_float): (double)((p)->a_w.w_long)) 52 | #define atom_setvoid(p) ((p)->a_type = A_NOTHING) 53 | 54 | #define PIPO_MAX_CLASS(pipoName, pipoClass, digest, description, numAttrs, attrNames, attrDescriptions) \ 55 | static t_class *max ## pipoClass ## Class = NULL; \ 56 | static const unsigned int maxWordLen = 256; \ 57 | static bool getPiPoInstanceAndAttrName(const char *attrName, char *instanceName, char *pipoAttrName){ \ 58 | const char *dot = strrchr(attrName, '.');\ 59 | if(dot != NULL){ \ 60 | unsigned int pipoAttrNameLen = dot - attrName; \ 61 | strcpy(pipoAttrName, dot + 1); \ 62 | if(pipoAttrNameLen > maxWordLen) pipoAttrNameLen = maxWordLen; \ 63 | strncpy(instanceName, attrName, pipoAttrNameLen); \ 64 | instanceName[pipoAttrNameLen] = '\0';\ 65 | return true;} \ 66 | return false;}\ 67 | static void getMaxAttributeList(PiPo *pipo, unsigned int attrId, long *pac, t_atom **pat){ \ 68 | PiPo::Attr *attr = pipo->getAttr(attrId); \ 69 | enum PiPo::Type type = attr->getType(); \ 70 | switch(type){ \ 71 | case PiPo::Undefined: \ 72 | break; \ 73 | case PiPo::Bool: \ 74 | case PiPo::Enum: \ 75 | case PiPo::Int: { \ 76 | for(unsigned int i = 0; i < attr->getSize(); i++) atom_setlong((*pat) + i, attr->getInt(i)); \ 77 | break; } \ 78 | case PiPo::Float: \ 79 | case PiPo::Double: { \ 80 | for(unsigned int i = 0; i < attr->getSize(); i++) atom_setfloat((*pat) + i, attr->getDbl(i)); \ 81 | break; } \ 82 | case PiPo::String: \ 83 | case PiPo::Dictionary: { \ 84 | for(unsigned int i = 0; i < attr->getSize(); i++) atom_setsym((*pat) + i, gensym(attr->getStr(i))); \ 85 | break; } \ 86 | default: break;}} \ 87 | static t_max_err setPiPoAttr(MaxPiPoT *self, void *attr, long ac, t_atom *at) { \ 88 | const char *attrName = ((t_symbol *)object_method((t_object *)attr, gensym("getname")))->s_name;\ 89 | char instanceName[maxWordLen]; \ 90 | char pipoAttrName[maxWordLen]; \ 91 | if(getPiPoInstanceAndAttrName(attrName, instanceName, pipoAttrName)) { \ 92 | PiPo *pipo = self->pipo; \ 93 | if(pipo != NULL) { \ 94 | PiPo::Attr *attr = pipo->getAttr(pipoAttrName);\ 95 | if(attr != NULL){ \ 96 | for(int i = 0; i < ac; i++){ if(!atom_isnum(at + i) && !atom_issym(at + i)) ac = i; } \ 97 | if(ac > 0) { \ 98 | attr->setSize(ac); \ 99 | if(atom_isnum(at) || atom_issym(at)){ \ 100 | for(int i = 0; i < ac; i++) { \ 101 | if(atom_issym(at + i)) { attr->set(i, (const char *)mysneg(atom_getsym(at + i)), true);} \ 102 | else if(atom_islong(at + i)) { attr->set(i, (int)atom_getlong(at + i), true); } \ 103 | else if(atom_isfloat(at + i)) { attr->set(i, (double)atom_getfloat(at + i), true);} \ 104 | else { attr->set(i, 0, true);}} \ 105 | attr->changed(true);}}}}} \ 106 | return MAX_ERR_NONE; } \ 107 | static t_max_err getPiPoAttr(MaxPiPoT *self, void *attr, long *pac, t_atom **pat) { \ 108 | const char *attrName = ((t_symbol *)object_method((t_object *)attr, gensym("getname")))->s_name;\ 109 | if(pac != NULL && pat != NULL){ \ 110 | char instanceName[maxWordLen]; \ 111 | char pipoAttrName[maxWordLen]; \ 112 | *pac = 0; \ 113 | if(getPiPoInstanceAndAttrName(attrName, instanceName, pipoAttrName)){ \ 114 | PiPo *pipo = self->pipo; \ 115 | if(pipo != NULL){ \ 116 | PiPo::Attr *attr = pipo->getAttr(pipoAttrName);\ 117 | if(attr != NULL){ \ 118 | unsigned int attrSize = attr->getSize(); \ 119 | char alloc; \ 120 | if(atom_alloc_array(attrSize, pac, pat, &alloc) == MAX_ERR_NONE){ \ 121 | getMaxAttributeList(pipo, attr->getIndex(), pac, pat); \ 122 | *pac = attrSize; }}}}} \ 123 | return MAX_ERR_NONE; } \ 124 | static const char *getAttrDescription(const char *attrName){\ 125 | for(int i = 0; i < numAttrs; i++){if((strcmp(attrName, attrNames[i])) == 0) return attrDescriptions[i];} \ 126 | return ""; } \ 127 | static void class_add_attributes_from_pipo(t_class *c) { \ 128 | PiPo *pipo = new pipoClass(NULL); \ 129 | unsigned int numAttributes = pipo->getNumAttrs(); \ 130 | for(unsigned int iAttr = 0; iAttr < numAttributes; iAttr++){ \ 131 | PiPo::Attr *attr = pipo->getAttr(iAttr); \ 132 | std::string attrName = pipoName; \ 133 | attrName += "."; \ 134 | attrName += attr->getName(); \ 135 | const char * attrName_c = attrName.c_str(); \ 136 | const char * attrDescr = getAttrDescription(attrName_c); \ 137 | enum PiPo::Type type = attr->getType(); \ 138 | char attrIndexStr[256]; \ 139 | sprintf(attrIndexStr, "%d", 256 + iAttr); \ 140 | switch(type) { \ 141 | case PiPo::Undefined: \ 142 | break; \ 143 | case PiPo::Int: {\ 144 | CLASS_ATTR_LONG(c, attrName_c, 0, MaxPiPoT, dummy_attr_long); \ 145 | CLASS_ATTR_LABEL(c,attrName_c, 0, attrDescr); \ 146 | CLASS_ATTR_ACCESSORS(c, attrName_c, getPiPoAttr, setPiPoAttr); \ 147 | CLASS_ATTR_ORDER(c, attrName_c, 0, attrIndexStr); \ 148 | IRCAMMAX_CLASS_ATTR_DESCRIPTION(c, attrName_c, attrDescr); \ 149 | break; }\ 150 | case PiPo::Bool: {\ 151 | CLASS_ATTR_LONG(c, attrName_c, 0, MaxPiPoT, dummy_attr_long); \ 152 | CLASS_ATTR_STYLE_LABEL(c, attrName_c, 0, "onoff", attrDescr); \ 153 | CLASS_ATTR_ACCESSORS(c, attrName_c, getPiPoAttr, setPiPoAttr); \ 154 | CLASS_ATTR_ORDER(c, attrName_c, 0, attrIndexStr); \ 155 | IRCAMMAX_CLASS_ATTR_DESCRIPTION(c, attrName_c, attrDescr); \ 156 | break; }\ 157 | case PiPo::Enum: {\ 158 | std::vector *enumList = attr->getEnumList(); \ 159 | std::string enumStr = (*enumList)[0]; \ 160 | if(enumList != NULL && enumList->size() > 0){ \ 161 | for(unsigned int i = 1; i < enumList->size(); i++){ \ 162 | enumStr += " "; \ 163 | enumStr += (*enumList)[i]; }} \ 164 | CLASS_ATTR_LONG(c, attrName_c, 0, MaxPiPoT, dummy_attr_long); \ 165 | CLASS_ATTR_LABEL(c,attrName_c, 0, attrDescr); \ 166 | CLASS_ATTR_ACCESSORS(c, attrName_c, getPiPoAttr, setPiPoAttr); \ 167 | CLASS_ATTR_ENUMINDEX(c, attrName_c, 0, enumStr.c_str());\ 168 | CLASS_ATTR_ORDER(c, attrName_c, 0, attrIndexStr); \ 169 | IRCAMMAX_CLASS_ATTR_DESCRIPTION(c, attrName_c, attrDescr); \ 170 | break; }\ 171 | case PiPo::Float: {\ 172 | CLASS_ATTR_DOUBLE(c, attrName_c, 0, MaxPiPoT, dummy_attr); \ 173 | CLASS_ATTR_LABEL(c,attrName_c, 0, attrDescr); \ 174 | CLASS_ATTR_ACCESSORS(c, attrName_c, getPiPoAttr, setPiPoAttr); \ 175 | CLASS_ATTR_ORDER(c, attrName_c, 0, attrIndexStr); \ 176 | IRCAMMAX_CLASS_ATTR_DESCRIPTION(c, attrName_c, attrDescr); \ 177 | break; }\ 178 | case PiPo::Double: {\ 179 | CLASS_ATTR_DOUBLE(c, attrName_c, 0, MaxPiPoT, dummy_attr); \ 180 | CLASS_ATTR_LABEL(c,attrName_c, 0, attrDescr); \ 181 | CLASS_ATTR_ACCESSORS(c, attrName_c, getPiPoAttr, setPiPoAttr); \ 182 | CLASS_ATTR_ORDER(c, attrName_c, 0, attrIndexStr); \ 183 | IRCAMMAX_CLASS_ATTR_DESCRIPTION(c, attrName_c, attrDescr); \ 184 | break; }\ 185 | case PiPo::String: \ 186 | case PiPo::Dictionary: { \ 187 | CLASS_ATTR_SYM(c, attrName_c, 0, MaxPiPoT, dummy_attr); \ 188 | CLASS_ATTR_LABEL(c,attrName_c, 0, attrDescr); \ 189 | CLASS_ATTR_ACCESSORS(c, attrName_c, getPiPoAttr, setPiPoAttr); \ 190 | CLASS_ATTR_ORDER(c, attrName_c, 0, attrIndexStr); \ 191 | IRCAMMAX_CLASS_ATTR_DESCRIPTION(c, attrName_c, attrDescr); \ 192 | break; }\ 193 | default: \ 194 | break; }}}\ 195 | static void *newMaxObject(t_symbol *s, long ac, t_atom *at) { \ 196 | MaxPiPoT *self = (MaxPiPoT *)object_alloc(max ## pipoClass ## Class); \ 197 | if(self != NULL) { \ 198 | self->pipo = new pipoClass(NULL); \ 199 | } \ 200 | return self; } \ 201 | static void freeMaxObject(MaxPiPoT *self) { delete self->pipo; } \ 202 | static void helpnameMethod(MaxPiPoT *self, char *str){ sprintf(str, "pipo.%s", pipoName);} \ 203 | static void bangMethod(MaxPiPoT *self, t_symbol *s, short ac, t_atom *at){object_error((t_object *) self, "pipo works only inside a pipo host!!! see pipo, pipo~ and mubu.process");} \ 204 | static void listMethod(MaxPiPoT *self, t_symbol *s, short ac, t_atom *at){object_error((t_object *) self, "pipo works only inside a pipo host!!! see pipo, pipo~ and mubu.process");}\ 205 | static void intMethod(MaxPiPoT *self, long i){object_error((t_object *) self, "pipo works only inside a pipo host!!! see pipo, pipo~ and mubu.process");} \ 206 | static void floatMethod(MaxPiPoT *self, double f){object_error((t_object *) self, "pipo works only inside a pipo host!!! see pipo, pipo~ and mubu.process");}\ 207 | int main(void) { \ 208 | t_class *c = class_new("pipo." pipoName, (method)newMaxObject, (method)freeMaxObject, (long)sizeof(MaxPiPoT), 0L, A_GIMME, 0); \ 209 | class_initIrcamMax(c); \ 210 | IRCAMMAX_CLASS_DIGEST(c, MaxPiPoT, digest); \ 211 | IRCAMMAX_CLASS_DESCRIPTION(c, MaxPiPoT, description); \ 212 | IRCAMMAX_CLASS_SEEALSO(c, MaxPiPoT, "pipo, pipo~, mubu.process"); \ 213 | class_add_attributes_from_pipo(c); \ 214 | class_addmethod(c, (method)helpnameMethod, "helpname", A_CANT, 0);\ 215 | class_addmethod(c, (method)bangMethod, "bang", 0);\ 216 | class_addmethod(c, (method)listMethod, "list", A_GIMME, 0);\ 217 | class_addmethod(c, (method)intMethod, "int", A_LONG, 0);\ 218 | class_addmethod(c, (method)floatMethod, "float", A_FLOAT, 0);\ 219 | class_register(CLASS_BOX, c); \ 220 | max ## pipoClass ## Class = c; \ 221 | return 0; } 222 | 223 | #else // PIPO_MAX_WITH_DOC 224 | 225 | #define PIPO_MAX_CLASS(pipoName, pipoClass) \ 226 | static t_class *max ## pipoClass ## Class = NULL; \ 227 | static void *newMaxObject(t_symbol *s, long ac, t_atom *at) { \ 228 | MaxPiPoT *self = (MaxPiPoT *)object_alloc(max ## pipoClass ## Class); \ 229 | if(self != NULL) { self->pipo = new pipoClass(NULL); } \ 230 | return self; } \ 231 | static void freeMaxObject(MaxPiPoT *self) { delete self->pipo; } \ 232 | static void helpnameMethod(MaxPiPoT *self, char *str){ sprintf(str, "pipo.%s", pipoName);} \ 233 | static void bangMethod(MaxPiPoT *self, t_symbol *s, short ac, t_atom *at){object_error((t_object *) self, "pipo works only inside a pipo host!!!");} \ 234 | static void listMethod(MaxPiPoT *self, t_symbol *s, short ac, t_atom *at){object_error((t_object *) self, "pipo works only inside a pipo host!!!");}\ 235 | static void intMethod(MaxPiPoT *self, long i){object_error((t_object *) self, "pipo works only inside a pipo host!!!");} \ 236 | static void floatMethod(MaxPiPoT *self, double f){object_error((t_object *) self, "pipo works only inside a pipo host!!!");}\ 237 | int main(void) { \ 238 | t_class *c = class_new("pipo." pipoName, (method)newMaxObject, (method)freeMaxObject, (long)sizeof(MaxPiPoT), 0L, A_GIMME, 0); \ 239 | class_addmethod(c, (method)helpnameMethod, "helpname", A_CANT, 0);\ 240 | class_addmethod(c, (method)bangMethod, "bang", 0);\ 241 | class_addmethod(c, (method)listMethod, "list", A_GIMME, 0);\ 242 | class_addmethod(c, (method)intMethod, "int", A_LONG, 0);\ 243 | class_addmethod(c, (method)floatMethod, "float", A_FLOAT, 0);\ 244 | class_register(CLASS_BOX, c); \ 245 | max ## pipoClass ## Class = c; \ 246 | return 0; } 247 | 248 | #endif // PIPO_MAX_WITH_DOC 249 | 250 | #endif // _MAX_PIPO_H_ 251 | -------------------------------------------------------------------------------- /bindings/max/MaxPiPoHost.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @file MaxPiPoHost.h 4 | * @author Norbert.Schnell@ircam.fr 5 | * 6 | * @brief Max PiPo utilities 7 | * Copyright (C) 2012-2014 by IRCAM – Centre Pompidou, Paris, France. 8 | * All rights reserved. 9 | * 10 | */ 11 | 12 | #include 13 | 14 | #include "MaxPiPoHost.h" 15 | 16 | #include 17 | #include 18 | #include "ext.h" // for ext_dictionary.h and 19 | #include "ext_dictobj.h" 20 | 21 | using namespace std; 22 | 23 | /********************************************************* 24 | * 25 | * Max PiPo Host Utils 26 | * 27 | */ 28 | static const unsigned int maxWordLen = 256; 29 | 30 | static bool 31 | getPiPoInstanceAndAttrName(const char *attrName, char *instanceName, char *pipoAttrName) 32 | { 33 | const char *dot = strrchr(attrName, '.'); 34 | 35 | if(dot != NULL) 36 | { 37 | unsigned int pipoAttrNameLen = dot - attrName; 38 | 39 | strcpy(pipoAttrName, dot + 1); 40 | 41 | if(pipoAttrNameLen > maxWordLen) 42 | pipoAttrNameLen = maxWordLen; 43 | 44 | strncpy(instanceName, attrName, pipoAttrNameLen); 45 | instanceName[pipoAttrNameLen] = '\0'; 46 | 47 | return true; 48 | } 49 | 50 | return false; 51 | } 52 | 53 | static void 54 | getMaxAttributeList(PiPo *pipo, unsigned int attrId, long *pac, t_atom **pat) 55 | { 56 | PiPo::Attr *attr = pipo->getAttr(attrId); 57 | enum PiPo::Type type = attr->getType(); 58 | 59 | switch(type) 60 | { 61 | case PiPo::Undefined: 62 | break; 63 | 64 | case PiPo::Bool: 65 | case PiPo::Int: 66 | { 67 | for(unsigned int i = 0; i < attr->getSize(); i++) 68 | atom_setlong((*pat) + i, attr->getInt(i)); 69 | 70 | break; 71 | } 72 | case PiPo::Enum: 73 | { 74 | if(attr->getIsArray() || attr->getIsVarSize()) 75 | { 76 | vector *enumList = attr->getEnumList(); 77 | if(enumList != NULL && enumList->size() > 0) 78 | for(unsigned int i = 0; i < attr->getSize(); i++) 79 | { 80 | const char *enumStr = (*enumList)[attr->getInt(i)]; 81 | atom_setsym((*pat) + i, gensym(enumStr)); 82 | } 83 | else 84 | for(unsigned int i = 0; i < attr->getSize(); i++) 85 | atom_setlong((*pat) + i, attr->getInt(i)); 86 | } 87 | else 88 | { 89 | for(unsigned int i = 0; i < attr->getSize(); i++) 90 | atom_setlong((*pat) + i, attr->getInt(i)); 91 | } 92 | break; 93 | } 94 | case PiPo::Float: 95 | case PiPo::Double: 96 | { 97 | for(unsigned int i = 0; i < attr->getSize(); i++) 98 | atom_setfloat((*pat) + i, attr->getDbl(i)); 99 | 100 | break; 101 | } 102 | case PiPo::String: 103 | case PiPo::Dictionary: 104 | { 105 | for(unsigned int i = 0; i < attr->getSize(); i++) 106 | atom_setsym((*pat) + i, attr->getStr(i) ? gensym(attr->getStr(i)) : gensym("")); // why didn't this crash before the NULL check? 107 | 108 | break; 109 | } 110 | 111 | default: 112 | break; 113 | } 114 | } 115 | 116 | /********************************************************* 117 | * 118 | * Max PiPo Host Class 119 | * 120 | */ 121 | MaxPiPoHost::MaxPiPoHost(t_object *ext, const char *prefix) 122 | : moduleFactory(ext, prefix), 123 | chain(this, &this->moduleFactory), 124 | inputStreamAttrs(), outputStreamAttrs() 125 | { 126 | this->ext = ext; 127 | systhread_mutex_new(&this->mutex, SYSTHREAD_MUTEX_RECURSIVE); 128 | } 129 | 130 | MaxPiPoHost::~MaxPiPoHost(void) 131 | { 132 | systhread_mutex_free(this->mutex); 133 | } 134 | 135 | void 136 | MaxPiPoHost::lock() 137 | { 138 | systhread_mutex_lock(this->mutex); 139 | } 140 | 141 | bool 142 | MaxPiPoHost::trylock() 143 | { 144 | return (systhread_mutex_trylock(this->mutex) == 0); 145 | } 146 | 147 | void 148 | MaxPiPoHost::unlock() 149 | { 150 | systhread_mutex_unlock(this->mutex); 151 | } 152 | 153 | PiPo * 154 | MaxPiPoHost::setChainDescription(const char *str, PiPo *receiver) 155 | { 156 | this->chain.clear(); 157 | 158 | if(this->chain.parse(str) > 0 && this->chain.instantiate() && this->chain.connect(receiver)) 159 | return this->chain.getHead(); 160 | 161 | return NULL; 162 | } 163 | 164 | /** declare pipo module attributes as max attributes */ 165 | void MaxPiPoHost::copyPiPoAttributes (MaxAttrGetterT getAttrMeth, MaxAttrSetterT setAttrMeth) 166 | { 167 | for(int iPiPo = 0; iPiPo < this->chain.getSize(); iPiPo++) 168 | { 169 | PiPo *pipo = this->chain.getPiPo(iPiPo); 170 | const char *instanceName = this->chain.getInstanceName(iPiPo); 171 | unsigned int numAttrs = pipo->getNumAttrs(); 172 | 173 | for(unsigned int iAttr = 0; iAttr < numAttrs; iAttr++) 174 | { 175 | PiPo::Attr *attr = pipo->getAttr(iAttr); 176 | 177 | if(attr != NULL) 178 | { 179 | /* attribute name */ 180 | string attrName = instanceName; 181 | attrName += "."; 182 | attrName += attr->getName(); 183 | 184 | /* description */ 185 | string label = attr->getDescr(); 186 | label += " ("; 187 | label += instanceName; 188 | label += ")"; 189 | 190 | enum PiPo::Type type = attr->getType(); 191 | t_symbol *typeSym = NULL; 192 | 193 | switch(type) 194 | { 195 | case PiPo::Undefined: 196 | break; 197 | 198 | case PiPo::Bool: 199 | case PiPo::Enum: 200 | case PiPo::Int: 201 | typeSym = USESYM(long); 202 | break; 203 | 204 | case PiPo::Float: 205 | typeSym = USESYM(float32); 206 | break; 207 | 208 | case PiPo::Double: 209 | typeSym = USESYM(float64); 210 | break; 211 | 212 | case PiPo::String: 213 | case PiPo::Dictionary: 214 | typeSym = USESYM(symbol); 215 | break; 216 | 217 | default: 218 | break; 219 | } 220 | bool isArray = attr->getIsArray(); 221 | bool isVarSize = attr->getIsVarSize(); 222 | 223 | t_object *maxAttr = NULL; 224 | if(!(isArray || isVarSize)) 225 | maxAttr = attribute_new(attrName.c_str(), typeSym, 0, (method)getAttrMeth, (method)setAttrMeth); 226 | else 227 | { 228 | if(type == PiPo::Enum) typeSym = USESYM(atom); 229 | maxAttr = attr_offset_array_new(attrName.c_str(), typeSym, 1024, 0, (method)getAttrMeth, (method)setAttrMeth, 0, 0); 230 | } 231 | object_addattr(this->ext, maxAttr); 232 | 233 | if(type == PiPo::Bool) 234 | object_attr_addattr_parse(this->ext, attrName.c_str(), "style", USESYM(symbol), 0, "onoff"); 235 | else if(type == PiPo::Enum) 236 | { 237 | vector *enumList = attr->getEnumList(); 238 | 239 | if(enumList != NULL && enumList->size() > 0) 240 | { 241 | string enumStr = (*enumList)[0]; 242 | 243 | for(unsigned int i = 1; i < enumList->size(); i++) 244 | { 245 | enumStr += " "; 246 | enumStr += (*enumList)[i]; 247 | } 248 | 249 | if(!(isArray || isVarSize)) 250 | { 251 | object_attr_addattr_parse(this->ext, attrName.c_str(), "style", USESYM(symbol), 0, "enumindex"); 252 | object_attr_addattr_parse(this->ext, attrName.c_str(), "enumvals", USESYM(symbol), 0, enumStr.c_str()); 253 | } 254 | } 255 | } 256 | 257 | object_attr_addattr_format(this->ext, attrName.c_str(), "label", USESYM(symbol), 0, "s", gensym(label.c_str())); 258 | 259 | t_atom a; 260 | atom_setlong(&a, (iPiPo + 1) * 256 + iAttr); 261 | object_attr_addattr_atoms(this->ext, attrName.c_str(), "order", USESYM(long), 0, 1, &a); 262 | } 263 | } 264 | } 265 | } 266 | 267 | void 268 | MaxPiPoHost::getMaxAttr(const char *attrName, long *pac, t_atom **pat, PiPoChain *chain) 269 | { 270 | if(pac != NULL && pat != NULL) 271 | { 272 | char instanceName[maxWordLen]; 273 | char pipoAttrName[maxWordLen]; 274 | 275 | this->lock(); 276 | 277 | if(chain == NULL) 278 | chain = &this->chain; 279 | 280 | *pac = 0; 281 | 282 | if(getPiPoInstanceAndAttrName(attrName, instanceName, pipoAttrName)) 283 | { 284 | PiPo *pipo = chain->getPiPo(instanceName); 285 | 286 | if(pipo != NULL) 287 | { 288 | PiPo::Attr *attr = pipo->getAttr(pipoAttrName); 289 | 290 | if(attr != NULL) 291 | { 292 | unsigned int attrSize = attr->getSize(); 293 | char alloc; 294 | 295 | if(atom_alloc_array(attrSize, pac, pat, &alloc) == MAX_ERR_NONE) 296 | { 297 | getMaxAttributeList(pipo, attr->getIndex(), pac, pat); 298 | *pac = attrSize; 299 | } 300 | } 301 | } 302 | } 303 | 304 | this->unlock(); 305 | } 306 | } 307 | 308 | void 309 | MaxPiPoHost::setMaxAttr(const char *attrName, long ac, t_atom *at, PiPoChain *chain, bool silently) 310 | { 311 | char instanceName[maxWordLen]; 312 | char pipoAttrName[maxWordLen]; 313 | 314 | this->lock(); 315 | 316 | if(chain == NULL) 317 | chain = &this->chain; 318 | 319 | if(getPiPoInstanceAndAttrName(attrName, instanceName, pipoAttrName)) 320 | { 321 | PiPo *pipo = chain->getPiPo(instanceName); 322 | 323 | if(pipo != NULL) 324 | { 325 | PiPo::Attr *attr = pipo->getAttr(pipoAttrName); 326 | 327 | if(attr != NULL) 328 | { 329 | for(int i = 0; i < ac; i++) 330 | { 331 | if(!atom_isnum(at + i) && !atom_issym(at + i)) 332 | ac = i; 333 | } 334 | 335 | if(ac > 0) 336 | { 337 | attr->setSize(ac); 338 | 339 | if(atom_isnum(at) || atom_issym(at)) 340 | { 341 | for(int i = 0; i < ac; i++) { 342 | if(atom_issym(at + i)) { 343 | attr->set(i, (const char *)mysneg(atom_getsym(at + i)), true); 344 | } else if(atom_islong(at + i)) { 345 | attr->set(i, (int)atom_getlong(at + i), true); 346 | } else if(atom_isfloat(at + i)) { 347 | attr->set(i, (double)atom_getfloat(at + i), true); 348 | } else { 349 | attr->set(i, 0, true); 350 | } 351 | } 352 | 353 | if (attr->getType() == PiPo::Dictionary) 354 | { // check if attr value is valid max dictionary and convert into json string 355 | //assert(attr->getSize() == 1); //YAGNI: make a list of json strings 356 | PiPoDictionaryAttr *dictattr = dynamic_cast(attr); 357 | 358 | t_dictionary *dict = dictobj_findregistered_retain(atom_getsym(at)); 359 | if (dict != NULL) 360 | { 361 | t_object *jsonwriter = (t_object *) object_new(_sym_nobox, _sym_jsonwriter); 362 | t_handle json; 363 | 364 | object_method(jsonwriter, _sym_writedictionary, dict); 365 | object_method(jsonwriter, _sym_getoutput, &json); 366 | 367 | // now const char *str = *json contains our JSON serialization of the t_dictionary 368 | dictattr->setJson(*json); 369 | 370 | object_free(jsonwriter); 371 | dictobj_release(dict); 372 | } 373 | else // attr. value is not a dictionary, we assume it is json and copy it 374 | dictattr->setJson(mysneg(atom_getsym(at))); 375 | } 376 | 377 | attr->changed(silently); 378 | } 379 | else 380 | object_error(this->ext, "invalid argument for attribute %s", attrName); 381 | } 382 | else 383 | object_error(this->ext, "missing argument for attribute %s", attrName); 384 | } 385 | } 386 | } 387 | 388 | this->unlock(); 389 | } 390 | 391 | void 392 | MaxPiPoHost::propagateInputAttributes(void) 393 | { 394 | this->lock(); 395 | 396 | PiPo *head = this->chain.getHead(); 397 | 398 | if(head != NULL) 399 | { 400 | const char *colNameStr[PIPO_MAX_LABELS]; 401 | const char **labels = NULL; 402 | unsigned int numCols = this->inputStreamAttrs.dims[0]; 403 | unsigned int numLabels = this->inputStreamAttrs.numLabels; 404 | 405 | if(numLabels > PIPO_MAX_LABELS) 406 | numLabels = PIPO_MAX_LABELS; 407 | 408 | if(numLabels > numCols) 409 | numLabels = numCols; 410 | 411 | if(numLabels > 0) 412 | { 413 | for(unsigned int i = 0; i < numLabels; i++) 414 | colNameStr[i] = mysneg(this->inputStreamAttrs.labels[i]); 415 | 416 | for(unsigned int i = numLabels; i < numCols; i++) 417 | colNameStr[i] = "unnamed"; 418 | 419 | labels = colNameStr; 420 | } 421 | 422 | head->streamAttributes(this->inputStreamAttrs.hasTimeTags, 423 | this->inputStreamAttrs.rate, 424 | this->inputStreamAttrs.offset, 425 | this->inputStreamAttrs.dims[0], 426 | this->inputStreamAttrs.dims[1], 427 | labels, 428 | this->inputStreamAttrs.hasVarSize, 429 | this->inputStreamAttrs.domain, 430 | this->inputStreamAttrs.maxFrames); 431 | } 432 | 433 | this->unlock(); 434 | } 435 | 436 | void 437 | MaxPiPoHost::setOutputAttributes(bool hasTimeTags, double rate, double offset, unsigned int width, unsigned int size, const char **labels, bool hasVarSize, double domain, unsigned int maxFrames) 438 | { 439 | this->lock(); 440 | 441 | if(labels != NULL) 442 | { 443 | int numLabels = width; 444 | 445 | if(numLabels > PIPO_MAX_LABELS) 446 | numLabels = PIPO_MAX_LABELS; 447 | 448 | for(int i = 0; i < numLabels; i++) 449 | this->outputStreamAttrs.labels[i] = gensym(labels[i]); 450 | 451 | this->outputStreamAttrs.numLabels = width; 452 | } 453 | else 454 | this->outputStreamAttrs.numLabels = 0; 455 | 456 | this->outputStreamAttrs.hasTimeTags = hasTimeTags; 457 | this->outputStreamAttrs.rate = rate; 458 | this->outputStreamAttrs.offset = offset; 459 | this->outputStreamAttrs.dims[0] = width; 460 | this->outputStreamAttrs.dims[1] = size; 461 | this->outputStreamAttrs.hasVarSize = hasVarSize; 462 | this->outputStreamAttrs.domain = domain; 463 | this->outputStreamAttrs.maxFrames = maxFrames; 464 | 465 | this->unlock(); 466 | } 467 | 468 | void 469 | MaxPiPoHost::streamAttributesChanged(PiPo *pipo, PiPo::Attr *attr) 470 | { 471 | this->propagateInputAttributes(); 472 | } 473 | 474 | void 475 | MaxPiPoHost::signalError(PiPo *pipo, std::string errorMsg) 476 | { 477 | object_error(this->ext, errorMsg.c_str()); 478 | } 479 | 480 | void 481 | MaxPiPoHost::signalWarning(PiPo *pipo, std::string errorMsg) 482 | { 483 | object_warn(this->ext, errorMsg.c_str()); 484 | } 485 | 486 | void 487 | MaxPiPoHost::setInputDims(int width, int size, bool propagate) 488 | { 489 | this->lock(); 490 | 491 | this->inputStreamAttrs.dims[0] = width; 492 | this->inputStreamAttrs.dims[1] = size; 493 | 494 | if(propagate) 495 | this->propagateInputAttributes(); 496 | 497 | this->unlock(); 498 | } 499 | 500 | void 501 | MaxPiPoHost::setInputLabels(long ac, t_atom *at, bool propagate) 502 | { 503 | this->lock(); 504 | 505 | if(ac > PIPO_MAX_LABELS) 506 | ac = PIPO_MAX_LABELS; 507 | 508 | this->inputStreamAttrs.numLabels = ac; 509 | 510 | for(int i = 0; i < ac; i++) 511 | { 512 | if(atom_issym(at + i)) 513 | this->inputStreamAttrs.labels[i] = atom_getsym(at + i); 514 | else 515 | { 516 | this->inputStreamAttrs.numLabels = i; 517 | break; 518 | } 519 | } 520 | 521 | if(propagate) 522 | this->propagateInputAttributes(); 523 | 524 | this->unlock(); 525 | } 526 | 527 | void 528 | MaxPiPoHost::setInputHasTimeTags(int hasTimeTags, bool propagate) 529 | { 530 | this->lock(); 531 | 532 | this->inputStreamAttrs.hasTimeTags = hasTimeTags; 533 | 534 | if(propagate) 535 | this->propagateInputAttributes(); 536 | 537 | this->unlock(); 538 | } 539 | 540 | #define MIN_SAMPLERATE (1.0 / 31536000000.0) /* once a year */ 541 | #define MAX_SAMPLERATE (96000000000.0) 542 | 543 | void 544 | MaxPiPoHost::setInputFrameRate(double sampleRate, bool propagate) 545 | { 546 | if(sampleRate <= MIN_SAMPLERATE) 547 | this->inputStreamAttrs.rate = MIN_SAMPLERATE; 548 | else if(sampleRate >= MAX_SAMPLERATE) 549 | this->inputStreamAttrs.rate = MAX_SAMPLERATE; 550 | else 551 | this->inputStreamAttrs.rate = sampleRate; 552 | 553 | if(propagate) 554 | this->propagateInputAttributes(); 555 | } 556 | 557 | void 558 | MaxPiPoHost::setInputFrameOffset(double sampleOffset, bool propagate) 559 | { 560 | this->inputStreamAttrs.offset = sampleOffset; 561 | 562 | if(propagate) 563 | this->propagateInputAttributes(); 564 | } 565 | 566 | void 567 | MaxPiPoHost::setInputMaxFrames(int maxFrames, bool propagate) 568 | { 569 | this->inputStreamAttrs.maxFrames = maxFrames; 570 | 571 | if(propagate) 572 | this->propagateInputAttributes(); 573 | } 574 | 575 | void 576 | MaxPiPoHost::getInputDims(int &width, int &size) 577 | { 578 | width = this->inputStreamAttrs.dims[0]; 579 | size = this->inputStreamAttrs.dims[1]; 580 | } 581 | 582 | void 583 | MaxPiPoHost::getInputLabels(int &num, t_atom *array) 584 | { 585 | int numLabels = this->inputStreamAttrs.numLabels; 586 | 587 | if(num > numLabels) 588 | num = numLabels; 589 | 590 | for(int i = 0; i < num; i++) 591 | atom_setsym(array + i, this->inputStreamAttrs.labels[i]); 592 | } 593 | 594 | bool 595 | MaxPiPoHost::getInputHasTimeTags() 596 | { 597 | return this->inputStreamAttrs.hasTimeTags; 598 | } 599 | 600 | double 601 | MaxPiPoHost::getInputFrameRate(void) 602 | { 603 | return this->inputStreamAttrs.rate; 604 | } 605 | 606 | double 607 | MaxPiPoHost::getInputFrameOffset(void) 608 | { 609 | return this->inputStreamAttrs.offset; 610 | } 611 | 612 | void 613 | MaxPiPoHost::getOutputDims(int &width, int &size) 614 | { 615 | width = this->outputStreamAttrs.dims[0]; 616 | size = this->outputStreamAttrs.dims[1]; 617 | } 618 | 619 | void 620 | MaxPiPoHost::getOutputLabels(int &num, t_atom *array) 621 | { 622 | int numLabels = this->outputStreamAttrs.numLabels; 623 | 624 | if(num > numLabels) 625 | num = numLabels; 626 | 627 | for(int i = 0; i < num; i++) 628 | atom_setsym(array + i, this->outputStreamAttrs.labels[i]); 629 | } 630 | 631 | bool 632 | MaxPiPoHost::getOutputHasTimeTags() 633 | { 634 | return this->outputStreamAttrs.hasTimeTags; 635 | } 636 | 637 | double 638 | MaxPiPoHost::getOutputFrameRate(void) 639 | { 640 | return this->outputStreamAttrs.rate; 641 | } 642 | 643 | double 644 | MaxPiPoHost::getOutputFrameOffset(void) 645 | { 646 | return this->outputStreamAttrs.offset; 647 | } 648 | 649 | int 650 | MaxPiPoHost::getOutputMaxFrames() 651 | { 652 | return this->outputStreamAttrs.maxFrames; 653 | } 654 | 655 | /** EMACS ** 656 | * Local variables: 657 | * mode: c++ 658 | * c-basic-offset:2 659 | * End: 660 | */ 661 | -------------------------------------------------------------------------------- /bindings/max/MaxPiPoHost.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file MaxPiPoHost.h 3 | * @author Norbert.Schnell@ircam.fr 4 | * 5 | * @brief Max PiPo utilities 6 | * Copyright (C) 2012-2014 by IRCAM – Centre Pompidou, Paris, France. 7 | * All rights reserved. 8 | * 9 | */ 10 | #ifndef _MAX_PIPO_HOST_ 11 | #define _MAX_PIPO_HOST_ 12 | 13 | #include "PiPoChain.h" 14 | #include "MaxPiPo.h" 15 | #include "ext.h" 16 | #include "ext_obex.h" 17 | #include "ext_systhread.h" 18 | #include "z_dsp.h" 19 | #include "ext_systhread.h" 20 | #include "z_dsp.h" 21 | 22 | #include 23 | #include 24 | 25 | #define atom_isnum(a) ((a)->a_type == A_LONG || (a)->a_type == A_FLOAT) 26 | #define atom_issym(a) ((a)->a_type == A_SYM) 27 | #define atom_isobj(p) ((p)->a_type == A_OBJ) 28 | #define mysneg(s) ((s)->s_name) 29 | 30 | #define atom_islong(p) ((p)->a_type == A_LONG) 31 | #define atom_isfloat(p) ((p)->a_type == A_FLOAT) 32 | #define atom_getnum(p) (((p)->a_type == A_FLOAT)? (double)((p)->a_w.w_float): (double)((p)->a_w.w_long)) 33 | #define atom_setvoid(p) ((p)->a_type = A_NOTHING) 34 | 35 | class MaxPiPoHost : public PiPo::Parent 36 | { 37 | class MaxPiPoModuleFactory : public PiPoModuleFactory 38 | { 39 | class MaxPiPoModule : public PiPoModule 40 | { 41 | MaxPiPoT *maxPiPo; 42 | 43 | public: 44 | MaxPiPoModule(MaxPiPoT *maxPiPo) 45 | { 46 | this->maxPiPo = maxPiPo; 47 | }; 48 | 49 | MaxPiPoModule(void) 50 | { 51 | if(this->maxPiPo != NULL) 52 | object_free((t_object *)this->maxPiPo); 53 | }; 54 | }; 55 | 56 | public: 57 | MaxPiPoModuleFactory(t_object *ext, const char *prefix = "pipo") 58 | { 59 | this->ext = ext; 60 | this->prefix = std::string(prefix); 61 | }; 62 | 63 | ~MaxPiPoModuleFactory(void) { } 64 | 65 | PiPo *create(unsigned int index, const std::string &pipoName, const std::string &instanceName, PiPoModule *&module) 66 | { 67 | std::string pipoClassNameStr = this->prefix + "." + pipoName; 68 | MaxPiPoT *maxPiPo = (MaxPiPoT *)object_new_typed(CLASS_BOX, gensym(pipoClassNameStr.c_str()), 0, NULL); 69 | 70 | if (maxPiPo == NULL) 71 | { // try to find pipo decoder module embedded in mimo 72 | std::string mimo_class_name = "mimo." + pipoName; 73 | printf("%s not found, trying to load %s\n", pipoClassNameStr.c_str(), mimo_class_name.c_str()); 74 | maxPiPo = (MaxPiPoT *) object_new_typed(CLASS_BOX, gensym(mimo_class_name.c_str()), 0, NULL); 75 | } 76 | 77 | if(maxPiPo != NULL) 78 | { 79 | module = new MaxPiPoModule(maxPiPo); 80 | return maxPiPo->pipo; 81 | } 82 | 83 | object_error((t_object *)this->ext, "cannot find external module %s", pipoClassNameStr.c_str()); 84 | return NULL; 85 | } 86 | 87 | private: 88 | t_object *ext; 89 | std::string prefix; 90 | }; 91 | 92 | //#define PIPO_MAX_LABELS 64 93 | 94 | //TODO: unify with pipohost.h 95 | class PiPoStreamAttributes 96 | { 97 | public: 98 | int hasTimeTags; 99 | double rate; 100 | double offset; 101 | unsigned int dims[2]; 102 | t_symbol *labels[PIPO_MAX_LABELS]; //TODO: abstract from t_symbol 103 | unsigned int numLabels; 104 | bool hasVarSize; 105 | double domain; 106 | unsigned int maxFrames; 107 | 108 | PiPoStreamAttributes(void) : labels() 109 | { 110 | this->hasTimeTags = false; 111 | this->rate = 1000.0; 112 | this->offset = 0.0; 113 | this->dims[0] = 1; 114 | this->dims[1] = 1; 115 | this->numLabels = 0; 116 | this->hasVarSize = false; 117 | this->domain = 0.0; 118 | this->maxFrames = 1; 119 | }; 120 | }; 121 | 122 | protected: 123 | t_object *ext; 124 | MaxPiPoModuleFactory moduleFactory; 125 | PiPoChain chain; 126 | PiPoStreamAttributes inputStreamAttrs; 127 | PiPoStreamAttributes outputStreamAttrs; 128 | t_systhread_mutex mutex; 129 | 130 | public: 131 | MaxPiPoHost(t_object *ext, const char *prefix = "pipo"); 132 | ~MaxPiPoHost(void); 133 | 134 | void lock(void); 135 | bool trylock(void); 136 | void unlock(void); 137 | 138 | PiPoChain *getChain(void) { return &this->chain; }; 139 | PiPo *setChainDescription(const char *str, PiPo *receiver); 140 | 141 | typedef t_max_err (*MaxAttrGetterT)(t_object *ext, void *attr, long *pac, t_atom **pat); 142 | typedef t_max_err (*MaxAttrSetterT)(t_object *ext, void *attr, long ac, t_atom *at); 143 | void copyPiPoAttributes(MaxAttrGetterT getAttrMeth, MaxAttrSetterT setAttrMeth); 144 | 145 | void getMaxAttr(const char *attrName, long *pac, t_atom **pat, PiPoChain *chain = NULL); 146 | void setMaxAttr(const char *attrName, long ac, t_atom *at, PiPoChain *chain = NULL, bool silently = false); 147 | 148 | /** call streamAttributes on first pipo in chain --> generic host */ 149 | void propagateInputAttributes(void); 150 | void setOutputAttributes(bool hasTimeTags, double rate, double offset, unsigned int width, unsigned int size, const char **labels, bool hasVarSize, double domain, unsigned int maxFrames); 151 | 152 | void streamAttributesChanged(PiPo *pipo, PiPo::Attr *attr) override; 153 | void signalError(PiPo *pipo, std::string errorMsg) override; 154 | void signalWarning(PiPo *pipo, std::string errorMsg) override; 155 | 156 | //TODO: to pipohost 157 | void setInputDims(int width, int size, bool propagate = true); 158 | void setInputLabels(long ac, t_atom *at, bool propagate = true); 159 | void setInputHasTimeTags(int hasTimeTags, bool propagate = true); 160 | void setInputFrameRate(double sampleRate, bool propagate = true); 161 | void setInputFrameOffset(double sampleOffset, bool propagate = true); 162 | void setInputMaxFrames(int maxFrames, bool propagate = true); 163 | 164 | void getInputDims(int &width, int &size); 165 | void getInputLabels(int &num, t_atom *array); 166 | bool getInputHasTimeTags(void); 167 | double getInputFrameRate(void); 168 | double getInputFrameOffset(void); 169 | 170 | void getOutputDims(int &width, int &size); 171 | void getOutputLabels(int &num, t_atom *array); 172 | bool getOutputHasTimeTags(void); 173 | double getOutputFrameRate(void); 174 | double getOutputFrameOffset(void); 175 | int getOutputMaxFrames(); 176 | }; 177 | 178 | #endif 179 | -------------------------------------------------------------------------------- /bindings/max/maxmimo.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @file max_mimo.h 4 | * @author Diemo Schwarz 5 | * 6 | * @brief Max/MSP wrapper generator for a mimo module 7 | * 8 | * Copyright (C) 2016 by IRCAM – Centre Pompidou, Paris, France. 9 | * All rights reserved. 10 | * 11 | */ 12 | #ifndef _MAX_MIMO_ 13 | #define _MAX_MIMO_ 14 | 15 | #include "mimo.h" 16 | #include "ext.h" 17 | #include "ext_obex.h" 18 | 19 | typedef struct max_mimo_st { 20 | t_object head; 21 | Mimo *mimo; 22 | } MaxMimoT; 23 | 24 | #define MIMO_MAX_CLASS(mimo_name, mimo_class) \ 25 | static t_class *max_ ## mimo_class ## _class = NULL; \ 26 | static void *new_max_object(t_symbol *s, long ac, t_atom *at) { \ 27 | MaxMimoT *self = (MaxMimoT *) object_alloc(max_ ## mimo_class ## _class); \ 28 | if (self != NULL) { self->mimo = new mimo_class(NULL); } \ 29 | return self; } \ 30 | static void free_max_object(MaxMimoT *self) { delete self->mimo; } \ 31 | int main(void) { \ 32 | t_class *c = class_new("mimo." mimo_name, (method) new_max_object, (method) free_max_object, (long) sizeof(MaxMimoT), 0L, A_GIMME, 0); \ 33 | class_register(CLASS_BOX, c); \ 34 | max_ ## mimo_class ## _class = c; \ 35 | return 0; } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /bindings/max/maxmimohost.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "maxmimohost.h" 3 | 4 | Mimo *MaxMimoHost::set_module (const char *str, Mimo *receiver) 5 | { 6 | this->chain.clear(); 7 | 8 | if (this->chain.parse(str) > 0 && this->chain.instantiate() && this->chain.connect(receiver)) 9 | return dynamic_cast(this->chain.getHead()); 10 | else 11 | return NULL; 12 | } 13 | -------------------------------------------------------------------------------- /bindings/max/maxmimohost.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _MAX_MIMO_HOST_H_ 3 | #define _MAX_MIMO_HOST_H_ 4 | 5 | #include "mimo.h" 6 | #include "MaxPiPoHost.h" 7 | 8 | class MaxMimoHost : public MaxPiPoHost 9 | { 10 | public: 11 | MaxMimoHost (t_object *ext) 12 | : MaxPiPoHost(ext, "mimo") 13 | { 14 | } 15 | 16 | Mimo *set_module (const char* name, Mimo *receiver = NULL); 17 | }; 18 | 19 | #endif // _MAX_MIMO_HOST_H_ 20 | 21 | -------------------------------------------------------------------------------- /examples/jucepipo/PiPoGain-osc.maxpat: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 7, 6 | "minor" : 3, 7 | "revision" : 1, 8 | "architecture" : "x64", 9 | "modernui" : 1 10 | } 11 | , 12 | "rect" : [ 59.0, 104.0, 610.0, 551.0 ], 13 | "bglocked" : 0, 14 | "openinpresentation" : 0, 15 | "default_fontsize" : 12.0, 16 | "default_fontface" : 0, 17 | "default_fontname" : "Arial", 18 | "gridonopen" : 1, 19 | "gridsize" : [ 15.0, 15.0 ], 20 | "gridsnaponopen" : 1, 21 | "objectsnaponopen" : 1, 22 | "statusbarvisible" : 2, 23 | "toolbarvisible" : 1, 24 | "lefttoolbarpinned" : 0, 25 | "toptoolbarpinned" : 0, 26 | "righttoolbarpinned" : 0, 27 | "bottomtoolbarpinned" : 0, 28 | "toolbars_unpinned_last_save" : 0, 29 | "tallnewobj" : 0, 30 | "boxanimatetime" : 200, 31 | "enablehscroll" : 1, 32 | "enablevscroll" : 1, 33 | "devicewidth" : 0.0, 34 | "description" : "", 35 | "digest" : "", 36 | "tags" : "", 37 | "style" : "", 38 | "subpatcher_template" : "", 39 | "boxes" : [ { 40 | "box" : { 41 | "fontface" : 3, 42 | "fontsize" : 20.0, 43 | "id" : "obj-32", 44 | "maxclass" : "comment", 45 | "numinlets" : 1, 46 | "numoutlets" : 0, 47 | "patching_rect" : [ 90.0, 34.0, 366.0, 29.0 ], 48 | "style" : "", 49 | "text" : "PiPoGain for JucePipoOscApp tester" 50 | } 51 | 52 | } 53 | , { 54 | "box" : { 55 | "id" : "obj-30", 56 | "maxclass" : "newobj", 57 | "numinlets" : 1, 58 | "numoutlets" : 1, 59 | "outlettype" : [ "" ], 60 | "patching_rect" : [ 378.0, 110.0, 75.0, 22.0 ], 61 | "style" : "", 62 | "text" : "loadmess 1." 63 | } 64 | 65 | } 66 | , { 67 | "box" : { 68 | "id" : "obj-29", 69 | "maxclass" : "multislider", 70 | "numinlets" : 1, 71 | "numoutlets" : 2, 72 | "outlettype" : [ "", "" ], 73 | "parameter_enable" : 0, 74 | "patching_rect" : [ 90.0, 393.0, 134.0, 88.0 ], 75 | "presentation_rect" : [ 82.0, 354.0, 0.0, 0.0 ], 76 | "setstyle" : 3, 77 | "style" : "" 78 | } 79 | 80 | } 81 | , { 82 | "box" : { 83 | "id" : "obj-28", 84 | "maxclass" : "ezdac~", 85 | "numinlets" : 2, 86 | "numoutlets" : 0, 87 | "patching_rect" : [ 201.0, 137.0, 50.0, 50.0 ], 88 | "style" : "" 89 | } 90 | 91 | } 92 | , { 93 | "box" : { 94 | "id" : "obj-27", 95 | "maxclass" : "newobj", 96 | "numinlets" : 1, 97 | "numoutlets" : 2, 98 | "outlettype" : [ "float", "float" ], 99 | "patching_rect" : [ 90.0, 191.0, 161.0, 22.0 ], 100 | "style" : "", 101 | "text" : "t f f" 102 | } 103 | 104 | } 105 | , { 106 | "box" : { 107 | "id" : "obj-26", 108 | "maxclass" : "newobj", 109 | "numinlets" : 2, 110 | "numoutlets" : 1, 111 | "outlettype" : [ "float" ], 112 | "patching_rect" : [ 90.0, 164.0, 83.0, 22.0 ], 113 | "style" : "", 114 | "text" : "snapshot~ 10" 115 | } 116 | 117 | } 118 | , { 119 | "box" : { 120 | "id" : "obj-25", 121 | "maxclass" : "newobj", 122 | "numinlets" : 2, 123 | "numoutlets" : 1, 124 | "outlettype" : [ "signal" ], 125 | "patching_rect" : [ 90.0, 137.0, 65.0, 22.0 ], 126 | "style" : "", 127 | "text" : "cycle~ 0.1" 128 | } 129 | 130 | } 131 | , { 132 | "box" : { 133 | "id" : "obj-11", 134 | "maxclass" : "multislider", 135 | "numinlets" : 1, 136 | "numoutlets" : 2, 137 | "outlettype" : [ "", "" ], 138 | "parameter_enable" : 0, 139 | "patching_rect" : [ 90.0, 224.0, 134.0, 88.0 ], 140 | "setstyle" : 3, 141 | "style" : "" 142 | } 143 | 144 | } 145 | , { 146 | "box" : { 147 | "fontsize" : 36.0, 148 | "format" : 6, 149 | "id" : "obj-10", 150 | "maxclass" : "flonum", 151 | "numinlets" : 1, 152 | "numoutlets" : 2, 153 | "outlettype" : [ "", "bang" ], 154 | "parameter_enable" : 0, 155 | "patching_rect" : [ 378.0, 137.0, 106.0, 49.0 ], 156 | "style" : "" 157 | } 158 | 159 | } 160 | , { 161 | "box" : { 162 | "id" : "obj-8", 163 | "maxclass" : "message", 164 | "numinlets" : 2, 165 | "numoutlets" : 1, 166 | "outlettype" : [ "" ], 167 | "patching_rect" : [ 378.0, 191.0, 83.0, 22.0 ], 168 | "style" : "", 169 | "text" : "gain.factor $1" 170 | } 171 | 172 | } 173 | , { 174 | "box" : { 175 | "id" : "obj-35", 176 | "linecount" : 2, 177 | "maxclass" : "newobj", 178 | "numinlets" : 1, 179 | "numoutlets" : 1, 180 | "outlettype" : [ "" ], 181 | "patching_rect" : [ 378.0, 224.0, 145.0, 35.0 ], 182 | "style" : "", 183 | "text" : "prepend /OscPipoApp/PipoParam" 184 | } 185 | 186 | } 187 | , { 188 | "box" : { 189 | "id" : "obj-1", 190 | "maxclass" : "newobj", 191 | "numinlets" : 1, 192 | "numoutlets" : 1, 193 | "outlettype" : [ "" ], 194 | "patching_rect" : [ 90.0, 331.0, 99.0, 22.0 ], 195 | "style" : "", 196 | "text" : "udpreceive 7770" 197 | } 198 | 199 | } 200 | , { 201 | "box" : { 202 | "fontsize" : 12.0, 203 | "id" : "obj-5", 204 | "linecount" : 2, 205 | "maxclass" : "newobj", 206 | "numinlets" : 1, 207 | "numoutlets" : 1, 208 | "outlettype" : [ "" ], 209 | "patching_rect" : [ 232.0, 224.0, 141.0, 35.0 ], 210 | "style" : "", 211 | "text" : "prepend /OscPipoApp/InputData" 212 | } 213 | 214 | } 215 | , { 216 | "box" : { 217 | "fontname" : "Arial", 218 | "fontsize" : 12.0, 219 | "id" : "obj-24", 220 | "maxclass" : "newobj", 221 | "numinlets" : 1, 222 | "numoutlets" : 0, 223 | "patching_rect" : [ 312.0, 290.0, 141.0, 22.0 ], 224 | "style" : "", 225 | "text" : "udpsend 127.0.0.1 9001" 226 | } 227 | 228 | } 229 | , { 230 | "box" : { 231 | "fontname" : "Arial", 232 | "fontsize" : 12.0, 233 | "id" : "obj-118", 234 | "maxclass" : "newobj", 235 | "numinlets" : 2, 236 | "numoutlets" : 2, 237 | "outlettype" : [ "", "" ], 238 | "patching_rect" : [ 90.0, 359.0, 176.0, 22.0 ], 239 | "style" : "", 240 | "text" : "route /OscPipoApp/OutputData" 241 | } 242 | 243 | } 244 | ], 245 | "lines" : [ { 246 | "patchline" : { 247 | "destination" : [ "obj-118", 0 ], 248 | "disabled" : 0, 249 | "hidden" : 0, 250 | "source" : [ "obj-1", 0 ] 251 | } 252 | 253 | } 254 | , { 255 | "patchline" : { 256 | "destination" : [ "obj-8", 0 ], 257 | "disabled" : 0, 258 | "hidden" : 0, 259 | "source" : [ "obj-10", 0 ] 260 | } 261 | 262 | } 263 | , { 264 | "patchline" : { 265 | "destination" : [ "obj-29", 0 ], 266 | "disabled" : 0, 267 | "hidden" : 0, 268 | "source" : [ "obj-118", 0 ] 269 | } 270 | 271 | } 272 | , { 273 | "patchline" : { 274 | "destination" : [ "obj-26", 0 ], 275 | "disabled" : 0, 276 | "hidden" : 0, 277 | "source" : [ "obj-25", 0 ] 278 | } 279 | 280 | } 281 | , { 282 | "patchline" : { 283 | "destination" : [ "obj-27", 0 ], 284 | "disabled" : 0, 285 | "hidden" : 0, 286 | "source" : [ "obj-26", 0 ] 287 | } 288 | 289 | } 290 | , { 291 | "patchline" : { 292 | "destination" : [ "obj-11", 0 ], 293 | "disabled" : 0, 294 | "hidden" : 0, 295 | "source" : [ "obj-27", 0 ] 296 | } 297 | 298 | } 299 | , { 300 | "patchline" : { 301 | "destination" : [ "obj-5", 0 ], 302 | "disabled" : 0, 303 | "hidden" : 0, 304 | "source" : [ "obj-27", 1 ] 305 | } 306 | 307 | } 308 | , { 309 | "patchline" : { 310 | "destination" : [ "obj-10", 0 ], 311 | "disabled" : 0, 312 | "hidden" : 0, 313 | "source" : [ "obj-30", 0 ] 314 | } 315 | 316 | } 317 | , { 318 | "patchline" : { 319 | "destination" : [ "obj-24", 0 ], 320 | "disabled" : 0, 321 | "hidden" : 0, 322 | "source" : [ "obj-35", 0 ] 323 | } 324 | 325 | } 326 | , { 327 | "patchline" : { 328 | "destination" : [ "obj-24", 0 ], 329 | "disabled" : 0, 330 | "hidden" : 0, 331 | "source" : [ "obj-5", 0 ] 332 | } 333 | 334 | } 335 | , { 336 | "patchline" : { 337 | "destination" : [ "obj-35", 0 ], 338 | "disabled" : 0, 339 | "hidden" : 0, 340 | "source" : [ "obj-8", 0 ] 341 | } 342 | 343 | } 344 | ], 345 | "dependency_cache" : [ ], 346 | "autosave" : 0 347 | } 348 | 349 | } 350 | -------------------------------------------------------------------------------- /examples/jucepipo/PiPoGain-osc.pd: -------------------------------------------------------------------------------- 1 | #N canvas 573 269 704 462 10; 2 | #X obj 455 138 oscparse; 3 | #X obj 455 161 list trim; 4 | #X obj 455 115 netreceive -b -u 7770; 5 | #X obj 127 397 netsend -u -b; 6 | #X msg 207 329 connect localhost 9001; 7 | #X msg 207 357 disconnect; 8 | #X obj 127 184 snapshot~; 9 | #X obj 127 139 metro 10; 10 | #X obj 127 103 tgl 30 0 empty empty empty 17 7 0 10 -262144 -1 -1 1 11 | 1; 12 | #X obj 69 139 osc~ 0.1; 13 | #X msg 544 360 \; pd dsp 1; 14 | #X obj 544 337 loadbang; 15 | #X msg 544 396 \; pd dsp 0; 16 | #X obj 127 233 oscformat OscPipoApp InputData; 17 | #X obj 127 279 list prepend send; 18 | #X obj 127 302 list trim; 19 | #X obj 455 184 route OscPipoApp; 20 | #X obj 455 207 route OutputData; 21 | #X obj 82 235 vsl 30 128 -1 1 0 0 empty empty empty 0 -9 0 10 -262144 22 | -1 -1 105 0; 23 | #X obj 227 183 oscformat OscPipoApp PipoParam; 24 | #X obj 227 101 nbx 5 30 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 20 25 | -262144 -1 -1 1 256; 26 | #X obj 455 232 vsl 30 128 -1 1 0 0 empty empty empty 0 -9 0 10 -262144 27 | -1 -1 77 0; 28 | #X text 46 24 PiPoGain for JucePipoOscApp tester; 29 | #X obj 227 161 list; 30 | #X msg 227 138 gain.factor \$1; 31 | #X obj 227 59 loadbang; 32 | #X msg 227 80 1; 33 | #X obj 207 302 loadbang; 34 | #X connect 0 0 1 0; 35 | #X connect 1 0 16 0; 36 | #X connect 2 0 0 0; 37 | #X connect 4 0 3 0; 38 | #X connect 5 0 3 0; 39 | #X connect 6 0 13 0; 40 | #X connect 6 0 18 0; 41 | #X connect 7 0 6 0; 42 | #X connect 8 0 7 0; 43 | #X connect 9 0 6 0; 44 | #X connect 11 0 10 0; 45 | #X connect 13 0 14 0; 46 | #X connect 14 0 15 0; 47 | #X connect 15 0 3 0; 48 | #X connect 16 0 17 0; 49 | #X connect 17 0 21 0; 50 | #X connect 19 0 14 0; 51 | #X connect 20 0 24 0; 52 | #X connect 23 0 19 0; 53 | #X connect 24 0 23 0; 54 | #X connect 25 0 26 0; 55 | #X connect 26 0 20 0; 56 | #X connect 27 0 4 0; 57 | -------------------------------------------------------------------------------- /examples/jucepipo/PiPoGain.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @file PiPoGain.h 4 | * @author Norbert.Schnell@ircam.fr 5 | * 6 | * @brief PiPo gain data stream 7 | * 8 | * Copyright (C) 2012-2014 by IRCAM – Centre Pompidou, Paris, France. 9 | * All rights reserved. 10 | * 11 | */ 12 | #ifndef _PIPO_GAIN_ 13 | #define _PIPO_GAIN_ 14 | 15 | #include "PiPo.h" 16 | 17 | class PiPoGain : public PiPo 18 | { 19 | private: 20 | std::vector buffer; 21 | 22 | public: 23 | PiPoScalarAttr factor; 24 | 25 | PiPoGain (Parent *parent, PiPo *receiver = NULL) 26 | : PiPo(parent, receiver), 27 | factor(this, "factor", "Gain Factor", false, 1.0) 28 | { } 29 | 30 | ~PiPoGain (void) 31 | { } 32 | 33 | int streamAttributes (bool hasTimeTags, double rate, double offset, 34 | unsigned int width, unsigned int height, 35 | const char **labels, bool hasVarSize, 36 | double domain, unsigned int maxFrames) 37 | { 38 | // A general pipo can not work in place, we need to create an output buffer 39 | buffer.resize(width * height * maxFrames); 40 | return propagateStreamAttributes(hasTimeTags, rate, offset, width, height, 41 | labels, hasVarSize, domain, maxFrames); 42 | } 43 | 44 | int frames (double time, double weight, PiPoValue *values, 45 | unsigned int size, unsigned int num) 46 | { 47 | double f = factor.get(); // get gain factor here, as it could change while running 48 | PiPoValue *ptr = &buffer[0]; 49 | 50 | for (unsigned int i = 0; i < num; i++) 51 | { 52 | for (unsigned int j = 0; j < size; j++) 53 | ptr[j] = values[j] * f; 54 | 55 | ptr += size; 56 | values += size; 57 | } 58 | 59 | return propagateFrames(time, weight, &buffer[0], size, num); 60 | } 61 | }; 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /examples/jucepipo/PiPoGain.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 315B90381FB4AC4B0005150B /* PiPo.h in Headers */ = {isa = PBXBuildFile; fileRef = 315B90341FB4AC4B0005150B /* PiPo.h */; }; 11 | 315B90391FB4AC4B0005150B /* PiPoParallel.h in Headers */ = {isa = PBXBuildFile; fileRef = 315B90351FB4AC4B0005150B /* PiPoParallel.h */; }; 12 | 315B903A1FB4AC4B0005150B /* PiPoSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = 315B90361FB4AC4B0005150B /* PiPoSequence.h */; }; 13 | 315B903B1FB4AC4B0005150B /* RingBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 315B90371FB4AC4B0005150B /* RingBuffer.h */; }; 14 | 315B903E1FB4AC760005150B /* PiPoModuleClass.h in Headers */ = {isa = PBXBuildFile; fileRef = 315B903D1FB4AC760005150B /* PiPoModuleClass.h */; }; 15 | 31C6621A1DBE58EF00A543A8 /* PiPoGain.h in Sources */ = {isa = PBXBuildFile; fileRef = 31C662191DBE589900A543A8 /* PiPoGain.h */; }; 16 | 31C6621D1DBE5A7700A543A8 /* PipoGain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 31C6621C1DBE5A6E00A543A8 /* PipoGain.cpp */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 315B90341FB4AC4B0005150B /* PiPo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PiPo.h; path = ../../src/PiPo.h; sourceTree = ""; }; 21 | 315B90351FB4AC4B0005150B /* PiPoParallel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PiPoParallel.h; path = ../../src/PiPoParallel.h; sourceTree = ""; }; 22 | 315B90361FB4AC4B0005150B /* PiPoSequence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PiPoSequence.h; path = ../../src/PiPoSequence.h; sourceTree = ""; }; 23 | 315B90371FB4AC4B0005150B /* RingBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RingBuffer.h; path = ../../src/RingBuffer.h; sourceTree = ""; }; 24 | 315B903D1FB4AC760005150B /* PiPoModuleClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PiPoModuleClass.h; path = ../../src/host/PiPoModuleClass.h; sourceTree = ""; }; 25 | 31C662191DBE589900A543A8 /* PiPoGain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PiPoGain.h; sourceTree = ""; }; 26 | 31C6621C1DBE5A6E00A543A8 /* PipoGain.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = PipoGain.cpp; sourceTree = ""; }; 27 | 3B37A53F1DB105E9001FCA3C /* PipoGain.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = PipoGain.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | 3B37A5391DB105E9001FCA3C /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | 195DF8CFFE9D517E11CA2CBB /* Products */ = { 42 | isa = PBXGroup; 43 | children = ( 44 | 3B37A53F1DB105E9001FCA3C /* PipoGain.dylib */, 45 | ); 46 | name = Products; 47 | sourceTree = ""; 48 | }; 49 | 20286C29FDCF999611CA2CEA /* juce_application */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | 315B90331FB4AC310005150B /* src */, 53 | 31C662191DBE589900A543A8 /* PiPoGain.h */, 54 | 31C6621C1DBE5A6E00A543A8 /* PipoGain.cpp */, 55 | 195DF8CFFE9D517E11CA2CBB /* Products */, 56 | ); 57 | name = juce_application; 58 | sourceTree = ""; 59 | }; 60 | 315B90331FB4AC310005150B /* src */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 315B903C1FB4AC4F0005150B /* host */, 64 | 315B90341FB4AC4B0005150B /* PiPo.h */, 65 | 315B90351FB4AC4B0005150B /* PiPoParallel.h */, 66 | 315B90361FB4AC4B0005150B /* PiPoSequence.h */, 67 | 315B90371FB4AC4B0005150B /* RingBuffer.h */, 68 | ); 69 | name = src; 70 | sourceTree = ""; 71 | }; 72 | 315B903C1FB4AC4F0005150B /* host */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | 315B903D1FB4AC760005150B /* PiPoModuleClass.h */, 76 | ); 77 | name = host; 78 | sourceTree = ""; 79 | }; 80 | /* End PBXGroup section */ 81 | 82 | /* Begin PBXHeadersBuildPhase section */ 83 | 3B37A53A1DB105E9001FCA3C /* Headers */ = { 84 | isa = PBXHeadersBuildPhase; 85 | buildActionMask = 2147483647; 86 | files = ( 87 | 315B90381FB4AC4B0005150B /* PiPo.h in Headers */, 88 | 315B903A1FB4AC4B0005150B /* PiPoSequence.h in Headers */, 89 | 315B90391FB4AC4B0005150B /* PiPoParallel.h in Headers */, 90 | 315B903E1FB4AC760005150B /* PiPoModuleClass.h in Headers */, 91 | 315B903B1FB4AC4B0005150B /* RingBuffer.h in Headers */, 92 | ); 93 | runOnlyForDeploymentPostprocessing = 0; 94 | }; 95 | /* End PBXHeadersBuildPhase section */ 96 | 97 | /* Begin PBXNativeTarget section */ 98 | 3B37A5351DB105E9001FCA3C /* PipoGain */ = { 99 | isa = PBXNativeTarget; 100 | buildConfigurationList = 3B37A53C1DB105E9001FCA3C /* Build configuration list for PBXNativeTarget "PipoGain" */; 101 | buildPhases = ( 102 | 3B37A5361DB105E9001FCA3C /* Sources */, 103 | 3B37A5391DB105E9001FCA3C /* Frameworks */, 104 | 3B37A53A1DB105E9001FCA3C /* Headers */, 105 | 3B37A53B1DB105E9001FCA3C /* ShellScript */, 106 | ); 107 | buildRules = ( 108 | ); 109 | dependencies = ( 110 | ); 111 | name = PipoGain; 112 | productName = PipoBands.dylib; 113 | productReference = 3B37A53F1DB105E9001FCA3C /* PipoGain.dylib */; 114 | productType = "com.apple.product-type.library.dynamic"; 115 | }; 116 | /* End PBXNativeTarget section */ 117 | 118 | /* Begin PBXProject section */ 119 | 20286C28FDCF999611CA2CEA /* Project object */ = { 120 | isa = PBXProject; 121 | attributes = { 122 | }; 123 | buildConfigurationList = 84F30CC308FEAA620087E26C /* Build configuration list for PBXProject "PiPoGain" */; 124 | compatibilityVersion = "Xcode 3.2"; 125 | developmentRegion = English; 126 | hasScannedForEncodings = 1; 127 | knownRegions = ( 128 | English, 129 | Japanese, 130 | French, 131 | German, 132 | ); 133 | mainGroup = 20286C29FDCF999611CA2CEA /* juce_application */; 134 | projectDirPath = ""; 135 | projectRoot = ""; 136 | targets = ( 137 | 3B37A5351DB105E9001FCA3C /* PipoGain */, 138 | ); 139 | }; 140 | /* End PBXProject section */ 141 | 142 | /* Begin PBXShellScriptBuildPhase section */ 143 | 3B37A53B1DB105E9001FCA3C /* ShellScript */ = { 144 | isa = PBXShellScriptBuildPhase; 145 | buildActionMask = 12; 146 | files = ( 147 | ); 148 | inputPaths = ( 149 | ); 150 | outputPaths = ( 151 | ); 152 | runOnlyForDeploymentPostprocessing = 0; 153 | shellPath = /bin/sh; 154 | shellScript = "ditto $BUILT_PRODUCTS_DIR/${TARGET_NAME}.${EXECUTABLE_EXTENSION} ./"; 155 | }; 156 | /* End PBXShellScriptBuildPhase section */ 157 | 158 | /* Begin PBXSourcesBuildPhase section */ 159 | 3B37A5361DB105E9001FCA3C /* Sources */ = { 160 | isa = PBXSourcesBuildPhase; 161 | buildActionMask = 2147483647; 162 | files = ( 163 | 31C6621D1DBE5A7700A543A8 /* PipoGain.cpp in Sources */, 164 | 31C6621A1DBE58EF00A543A8 /* PiPoGain.h in Sources */, 165 | ); 166 | runOnlyForDeploymentPostprocessing = 0; 167 | }; 168 | /* End PBXSourcesBuildPhase section */ 169 | 170 | /* Begin XCBuildConfiguration section */ 171 | 3B37A53D1DB105E9001FCA3C /* Debug */ = { 172 | isa = XCBuildConfiguration; 173 | buildSettings = { 174 | ALWAYS_SEARCH_USER_PATHS = NO; 175 | CLANG_ANALYZER_NONNULL = YES; 176 | CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; 177 | CLANG_ENABLE_MODULES = YES; 178 | CLANG_ENABLE_OBJC_ARC = YES; 179 | CLANG_WARN_BOOL_CONVERSION = YES; 180 | CLANG_WARN_CONSTANT_CONVERSION = YES; 181 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 182 | CLANG_WARN_EMPTY_BODY = YES; 183 | CLANG_WARN_ENUM_CONVERSION = YES; 184 | CLANG_WARN_INT_CONVERSION = YES; 185 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 186 | CLANG_WARN_UNREACHABLE_CODE = YES; 187 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 188 | CODE_SIGN_IDENTITY = "-"; 189 | COPY_PHASE_STRIP = NO; 190 | DEBUG_INFORMATION_FORMAT = dwarf; 191 | DYLIB_COMPATIBILITY_VERSION = 1; 192 | DYLIB_CURRENT_VERSION = 1; 193 | ENABLE_STRICT_OBJC_MSGSEND = YES; 194 | ENABLE_TESTABILITY = YES; 195 | GCC_C_LANGUAGE_STANDARD = gnu99; 196 | GCC_DYNAMIC_NO_PIC = NO; 197 | GCC_INPUT_FILETYPE = sourcecode.cpp.cpp; 198 | GCC_NO_COMMON_BLOCKS = YES; 199 | GCC_OPTIMIZATION_LEVEL = 0; 200 | GCC_PREPROCESSOR_DEFINITIONS = ( 201 | "DEBUG=1", 202 | "$(inherited)", 203 | ); 204 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 205 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 206 | GCC_WARN_UNDECLARED_SELECTOR = YES; 207 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 208 | GCC_WARN_UNUSED_FUNCTION = YES; 209 | GCC_WARN_UNUSED_VARIABLE = YES; 210 | HEADER_SEARCH_PATHS = ( 211 | ../../src, 212 | ../../components/pipo/sdk/include, 213 | ../../components/pipo/sdk/host, 214 | ../../components/pipo/sdk/example, 215 | ../../components/pipo/modules, 216 | ../../components/pipo/modules/rta, 217 | ../../components/pipo/modules/rta/misc, 218 | ../../components/pipo/modules/rta/common, 219 | ../../components/pipo/modules/rta/psy, 220 | ); 221 | MTL_ENABLE_DEBUG_INFO = YES; 222 | ONLY_ACTIVE_ARCH = YES; 223 | PRODUCT_NAME = "$(TARGET_NAME)"; 224 | SDKROOT = macosx; 225 | }; 226 | name = Debug; 227 | }; 228 | 3B37A53E1DB105E9001FCA3C /* Release */ = { 229 | isa = XCBuildConfiguration; 230 | buildSettings = { 231 | ALWAYS_SEARCH_USER_PATHS = NO; 232 | CLANG_ANALYZER_NONNULL = YES; 233 | CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; 234 | CLANG_ENABLE_MODULES = YES; 235 | CLANG_ENABLE_OBJC_ARC = YES; 236 | CLANG_WARN_BOOL_CONVERSION = YES; 237 | CLANG_WARN_CONSTANT_CONVERSION = YES; 238 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 239 | CLANG_WARN_EMPTY_BODY = YES; 240 | CLANG_WARN_ENUM_CONVERSION = YES; 241 | CLANG_WARN_INT_CONVERSION = YES; 242 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 243 | CLANG_WARN_UNREACHABLE_CODE = YES; 244 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 245 | CODE_SIGN_IDENTITY = "-"; 246 | COPY_PHASE_STRIP = NO; 247 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 248 | DYLIB_COMPATIBILITY_VERSION = 1; 249 | DYLIB_CURRENT_VERSION = 1; 250 | ENABLE_NS_ASSERTIONS = NO; 251 | ENABLE_STRICT_OBJC_MSGSEND = YES; 252 | GCC_C_LANGUAGE_STANDARD = gnu99; 253 | GCC_INPUT_FILETYPE = sourcecode.cpp.cpp; 254 | GCC_NO_COMMON_BLOCKS = YES; 255 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 256 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 257 | GCC_WARN_UNDECLARED_SELECTOR = YES; 258 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 259 | GCC_WARN_UNUSED_FUNCTION = YES; 260 | GCC_WARN_UNUSED_VARIABLE = YES; 261 | HEADER_SEARCH_PATHS = ( 262 | ../../src, 263 | ../../components/pipo/sdk/include, 264 | ../../components/pipo/sdk/host, 265 | ../../components/pipo/sdk/example, 266 | ../../components/pipo/modules, 267 | ../../components/pipo/modules/rta, 268 | ../../components/pipo/modules/rta/misc, 269 | ../../components/pipo/modules/rta/common, 270 | ../../components/pipo/modules/rta/psy, 271 | ); 272 | MTL_ENABLE_DEBUG_INFO = NO; 273 | PRODUCT_NAME = "$(TARGET_NAME)"; 274 | SDKROOT = macosx; 275 | }; 276 | name = Release; 277 | }; 278 | 84F30CC408FEAA620087E26C /* Debug */ = { 279 | isa = XCBuildConfiguration; 280 | buildSettings = { 281 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 282 | CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; 283 | CLANG_CXX_LIBRARY = "libc++"; 284 | COMPONENTS_DIR = ../../components; 285 | COMPONENTS_HEADER_DIRS = "$(COMPONENTS_DIR)/pipo/src $(COMPONENTS_DIR)/pipo/modules $(COMPONENTS_DIR)/pipo/modules/rta $(COMMON_DIR)/pipo/modules/rta/common $(COMPONENTS_DIR)/pipo/modules/rta/misc /System/Library/Frameworks/Accelerate.framework/Headers"; 286 | FRAMEWORK_SEARCH_PATHS = "$(VECLIB_FRAMEWORK_DIR)"; 287 | HEADER_SEARCH_PATHS = ( 288 | ../../src, 289 | ../../components/juce, 290 | ../../components/ImtrEditor/src, 291 | ../../components/ImtrEditor/src/components, 292 | ../../components/ImtrEditor/src/editors, 293 | ../../components/ImtrEditor/src/images, 294 | ../../components/ImtrEditor/src/tools, 295 | ../../components/sdif, 296 | ../../components/pipo/src, 297 | ../../components/pipo/modules, 298 | ../../components/mubu/src, 299 | ../../components/midifile/src, 300 | ../../components/pipo/sdk/include, 301 | ../../components/pipo/sdk/host, 302 | ../../components/pipo/modules, 303 | ../../components/pipo/modules/rta, 304 | ../../components/pipo/modules/rta/misc, 305 | ../../components/pipo/modules/rta/common, 306 | ../../components/pipo/modules/rta/psy, 307 | /System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/Headers, 308 | /System/Library/Frameworks/Accelerate.framework/Headers, 309 | ); 310 | MACOSX_DEPLOYMENT_TARGET = 10.10; 311 | OTHER_CPLUSPLUSFLAGS = ( 312 | "-D__MACOSX_CORE__", 313 | "-mtune=native", 314 | ); 315 | SYS_LINKER_FLAGS = "-lstdc++ -lmx -framework Accelerate -framework Carbon"; 316 | VECLIB_FRAMEWORK_DIR = /System/Library/Frameworks/Accelerate.framework/Frameworks; 317 | }; 318 | name = Debug; 319 | }; 320 | 84F30CC508FEAA620087E26C /* Release */ = { 321 | isa = XCBuildConfiguration; 322 | buildSettings = { 323 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 324 | CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; 325 | CLANG_CXX_LIBRARY = "libc++"; 326 | COMPONENTS_DIR = ../../components; 327 | COMPONENTS_HEADER_DIRS = "$(COMPONENTS_DIR)/pipo/src $(COMPONENTS_DIR)/pipo/modules $(COMPONENTS_DIR)/pipo/modules/rta $(COMMON_DIR)/pipo/modules/rta/common $(COMPONENTS_DIR)/pipo/modules/rta/misc /System/Library/Frameworks/Accelerate.framework/Headers"; 328 | FRAMEWORK_SEARCH_PATHS = "$(VECLIB_FRAMEWORK_DIR)"; 329 | HEADER_SEARCH_PATHS = ( 330 | ../../src, 331 | ../../components/juce, 332 | ../../components/ImtrEditor/src, 333 | ../../components/ImtrEditor/src/components, 334 | ../../components/ImtrEditor/src/editors, 335 | ../../components/ImtrEditor/src/images, 336 | ../../components/ImtrEditor/src/tools, 337 | ../../components/sdif, 338 | ../../components/pipo/src, 339 | ../../components/pipo/modules, 340 | ../../components/mubu/src, 341 | ../../components/midifile/src, 342 | ../../components/pipo/sdk/include, 343 | ../../components/pipo/sdk/host, 344 | ../../components/pipo/modules, 345 | ../../components/pipo/modules/rta, 346 | ../../components/pipo/modules/rta/misc, 347 | ../../components/pipo/modules/rta/common, 348 | ../../components/pipo/modules/rta/psy, 349 | /System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/Headers, 350 | /System/Library/Frameworks/Accelerate.framework/Headers, 351 | ); 352 | MACOSX_DEPLOYMENT_TARGET = 10.10; 353 | OTHER_CPLUSPLUSFLAGS = ( 354 | "-D__MACOSX_CORE__", 355 | "-mtune=native", 356 | ); 357 | SYS_LINKER_FLAGS = "-lstdc++ -lmx -framework Accelerate -framework Carbon"; 358 | VECLIB_FRAMEWORK_DIR = /System/Library/Frameworks/Accelerate.framework/Frameworks; 359 | }; 360 | name = Release; 361 | }; 362 | /* End XCBuildConfiguration section */ 363 | 364 | /* Begin XCConfigurationList section */ 365 | 3B37A53C1DB105E9001FCA3C /* Build configuration list for PBXNativeTarget "PipoGain" */ = { 366 | isa = XCConfigurationList; 367 | buildConfigurations = ( 368 | 3B37A53D1DB105E9001FCA3C /* Debug */, 369 | 3B37A53E1DB105E9001FCA3C /* Release */, 370 | ); 371 | defaultConfigurationIsVisible = 0; 372 | defaultConfigurationName = Debug; 373 | }; 374 | 84F30CC308FEAA620087E26C /* Build configuration list for PBXProject "PiPoGain" */ = { 375 | isa = XCConfigurationList; 376 | buildConfigurations = ( 377 | 84F30CC408FEAA620087E26C /* Debug */, 378 | 84F30CC508FEAA620087E26C /* Release */, 379 | ); 380 | defaultConfigurationIsVisible = 0; 381 | defaultConfigurationName = Debug; 382 | }; 383 | /* End XCConfigurationList section */ 384 | }; 385 | rootObject = 20286C28FDCF999611CA2CEA /* Project object */; 386 | } 387 | -------------------------------------------------------------------------------- /examples/jucepipo/PipoGain.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @file PipoGain.cpp 4 | * 5 | * @brief wrapper for PiPoGain 6 | * 7 | * Copyright (C) 2012-2016 by IRCAM – Centre Pompidou, Paris, France. 8 | * All rights reserved. 9 | * 10 | */ 11 | #include "PipoGain.h" 12 | #include "PiPoModuleClass.h" 13 | 14 | PIPO_MODULE_CLASS("gain", PiPoGain); 15 | -------------------------------------------------------------------------------- /examples/jucepipo/PipoGain.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ircam-ismm/pipo-sdk/9d9605b1f017cb84f3bc4d50f4f82ecf29281a5d/examples/jucepipo/PipoGain.dylib -------------------------------------------------------------------------------- /examples/maxpipo/PiPoGain.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @file PiPoGain.h 4 | * @author Diemo.Schwarz@ircam.fr 5 | * 6 | * @brief PiPo gain data stream 7 | * 8 | * Copyright (C) 2012-2014 by IRCAM – Centre Pompidou, Paris, France. 9 | * All rights reserved. 10 | * 11 | */ 12 | #ifndef _PIPO_GAIN_ 13 | #define _PIPO_GAIN_ 14 | 15 | #include "PiPo.h" 16 | 17 | class PiPoGain : public PiPo 18 | { 19 | private: 20 | std::vector buffer_; 21 | unsigned int framesize_; // cache max frame size 22 | 23 | public: 24 | PiPoScalarAttr factor_attr_; 25 | 26 | PiPoGain (Parent *parent, PiPo *receiver = NULL) 27 | : PiPo(parent, receiver), 28 | factor_attr_(this, "factor", "Gain Factor", false, 1.0) 29 | { } 30 | 31 | ~PiPoGain (void) 32 | { } 33 | 34 | /* Configure PiPo module according to the input stream attributes and propagate output stream attributes. 35 | * Note: For audio input, one PiPo frame corresponds to one sample frame, i.e. width is the number of channels, height is 1, maxFrames is the maximum number of (sample) frames passed to the module, rate is the sample rate, and domain is 1 / sample rate. 36 | */ 37 | int streamAttributes (bool hasTimeTags, double rate, double offset, 38 | unsigned int width, unsigned int height, 39 | const char **labels, bool hasVarSize, 40 | double domain, unsigned int maxFrames) 41 | { 42 | // we need to store the max frame size in case hasVarSize is true 43 | framesize_ = width * height; 44 | 45 | // A general pipo can not work in place, we need to create an output buffer 46 | buffer_.resize(framesize_ * maxFrames); 47 | 48 | // we will produce the same stream layout as the input 49 | return propagateStreamAttributes(hasTimeTags, rate, offset, width, height, 50 | labels, hasVarSize, domain, maxFrames); 51 | } 52 | 53 | int frames (double time, double weight, PiPoValue *values, 54 | unsigned int size, unsigned int num) 55 | { 56 | double f = factor_attr_.get(); // get gain factor here, as it could change while running 57 | PiPoValue *outptr = &buffer_[0]; 58 | 59 | for (unsigned int i = 0; i < num; i++) 60 | { 61 | for (unsigned int j = 0; j < size; j++) 62 | outptr[j] = values[j] * f; 63 | 64 | outptr += framesize_; 65 | values += framesize_; 66 | } 67 | 68 | return propagateFrames(time, weight, &buffer_[0], size, num); 69 | } 70 | }; 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /examples/maxpipo/external.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleExecutable 6 | $(PRODUCT_NAME) 7 | CFBundlePackageType 8 | iLaX 9 | CFBundleShortVersionString 10 | 1.1 11 | CFBundleVersion 12 | 1.1 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/maxpipo/maxpipo-example-debug.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Project-Debug.xcconfig 3 | // 4 | // Generated by BuildSettingExtractor on 25/06/15 5 | // https://github.com/dempseyatgithub/BuildSettingExtractor 6 | // 7 | 8 | #include "maxpipo-example-shared.xcconfig" 9 | 10 | 11 | BUILD_DEFS = DEBUG=1 12 | 13 | 14 | // Optimization Level 15 | // 16 | // None: Do not optimize. [-O0] 17 | // 18 | // With this setting, the compiler's goal is to reduce the cost of compilation and to 19 | // make debugging produce the expected results. Statements are independent: if you stop 20 | // the program with a breakpoint between statements, you can then assign a new value to 21 | // any variable or change the program counter to any other statement in the function and 22 | // get exactly the results you would expect from the source code. 23 | // 24 | // Fast: Optimizing compilation takes somewhat more time, and a lot more memory for a 25 | // large function. [-O, -O1] 26 | // 27 | // With this setting, the compiler tries to reduce code size and execution time, without 28 | // performing any optimizations that take a great deal of compilation time. In Apple's 29 | // compiler, strict aliasing, block reordering, and inter-block scheduling are disabled 30 | // by default when optimizing. 31 | // 32 | // Faster: The compiler performs nearly all supported optimizations that do not involve a 33 | // space-speed tradeoff. [-O2] 34 | // 35 | // With this setting, the compiler does not perform loop unrolling or function inlining, 36 | // or register renaming. As compared to the 'Fast' setting, this setting increases both 37 | // compilation time and the performance of the generated code. 38 | // 39 | // Fastest: Turns on all optimizations specified by the 'Faster' setting and also turns 40 | // on function inlining and register renaming options. This setting may result in a 41 | // larger binary. [-O3] 42 | // 43 | // Fastest, Smallest: Optimize for size. This setting enables all 'Faster' optimizations 44 | // that do not typically increase code size. It also performs further optimizations 45 | // designed to reduce code size. [-Os] 46 | // 47 | // Fastest, Aggressive Optimizations: This setting enables 'Fastest' but also enables 48 | // aggressive optimizations that may break strict standards compliance but should work 49 | // well on well-behaved code. [-Ofast] 50 | 51 | GCC_OPTIMIZATION_LEVEL = 0 52 | 53 | 54 | // Build Active Architecture Only 55 | // 56 | // When checked, only the active architecture is built for faster debugging turnaround 57 | 58 | ONLY_ACTIVE_ARCH = NO //YES 59 | 60 | 61 | ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = $(NATIVE_ARCH_ACTUAL) -------------------------------------------------------------------------------- /examples/maxpipo/maxpipo-example-release.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Project-Release.xcconfig 3 | // 4 | // Generated by BuildSettingExtractor on 25/06/15 5 | // https://github.com/dempseyatgithub/BuildSettingExtractor 6 | // 7 | 8 | #include "maxpipo-example-shared.xcconfig" 9 | 10 | 11 | BUILD_DEFS = NDEBUG=1 12 | 13 | 14 | // Optimization Level 15 | // 16 | // None: Do not optimize. [-O0] 17 | // 18 | // With this setting, the compiler's goal is to reduce the cost of compilation and to 19 | // make debugging produce the expected results. Statements are independent: if you stop 20 | // the program with a breakpoint between statements, you can then assign a new value to 21 | // any variable or change the program counter to any other statement in the function and 22 | // get exactly the results you would expect from the source code. 23 | // 24 | // Fast: Optimizing compilation takes somewhat more time, and a lot more memory for a 25 | // large function. [-O, -O1] 26 | // 27 | // With this setting, the compiler tries to reduce code size and execution time, without 28 | // performing any optimizations that take a great deal of compilation time. In Apple's 29 | // compiler, strict aliasing, block reordering, and inter-block scheduling are disabled 30 | // by default when optimizing. 31 | // 32 | // Faster: The compiler performs nearly all supported optimizations that do not involve a 33 | // space-speed tradeoff. [-O2] 34 | // 35 | // With this setting, the compiler does not perform loop unrolling or function inlining, 36 | // or register renaming. As compared to the 'Fast' setting, this setting increases both 37 | // compilation time and the performance of the generated code. 38 | // 39 | // Fastest: Turns on all optimizations specified by the 'Faster' setting and also turns 40 | // on function inlining and register renaming options. This setting may result in a 41 | // larger binary. [-O3] 42 | // 43 | // Fastest, Smallest: Optimize for size. This setting enables all 'Faster' optimizations 44 | // that do not typically increase code size. It also performs further optimizations 45 | // designed to reduce code size. [-Os] 46 | // 47 | // Fastest, Aggressive Optimizations: This setting enables 'Fastest' but also enables 48 | // aggressive optimizations that may break strict standards compliance but should work 49 | // well on well-behaved code. [-Ofast] 50 | 51 | GCC_OPTIMIZATION_LEVEL = 3 -------------------------------------------------------------------------------- /examples/maxpipo/maxpipo-example-shared.xcconfig: -------------------------------------------------------------------------------- 1 | // base xcode config file for pipo sdk example 2 | // You need to adapt the first definition MAXAPI_DIR to where you put the Max SDK 3 | // downloaded from https://cycling74.com/downloads/sdk/ 4 | // You might want to adapt the next 3 settings, but the rest should not need changing. 5 | 6 | 7 | // where is your Max SDK? 8 | // Below example path points to a Max8 SDK placed into a folder "max-sdk" next to the pipo-sdk folder. 9 | MAXAPI_DIR = ../../../max-sdk/max-sdk-8.0.3/source/c74support/ 10 | 11 | // force built mxo to be placed in example project dir 12 | CONFIGURATION_BUILD_DIR = $(PROJECT_DIR) 13 | 14 | 15 | COMPONENTS_HEADER_DIRS = /System/Library/Frameworks/Accelerate.framework/Headers 16 | VECLIB_FRAMEWORK_DIR = /System/Library/Frameworks/Accelerate.framework/Frameworks 17 | 18 | 19 | /////////////////////////////////////////////////////////////////////////////// 20 | // Standard settings start here 21 | /////////////////////////////////////////////////////////////////////////////// 22 | 23 | // Set to building universal binary 24 | ARCHS = $(ARCHS_STANDARD_32_64_BIT) 25 | 26 | // Dead Code Stripping 27 | // 28 | // Activating this setting causes the -dead_strip flag to be passed to ld(1) via cc(1) to 29 | // turn on dead code stripping. If this option is selected, -gfull (not -gused) must be 30 | // used to generate debugging symbols in order to have them correctly stripped. 31 | // [-dead_strip] 32 | 33 | DEAD_CODE_STRIPPING = YES 34 | 35 | 36 | // Framework Search Paths 37 | // 38 | // This is a list of paths to folders containing frameworks to be searched by the 39 | // compiler for both included or imported header files when compiling C, Objective-C, 40 | // C++, or Objective-C++, and by the linker for frameworks used by the product. Paths are 41 | // delimited by whitespace, so any paths with spaces in them need to be properly quoted. 42 | // [-F] 43 | 44 | FRAMEWORK_SEARCH_PATHS = $(MAXAPI_DIR)/** $(VECLIB_FRAMEWORK_DIR) 45 | 46 | 47 | GCC_AUTO_VECTORIZATION = YES 48 | 49 | 50 | GCC_ENABLE_SSE3_EXTENSIONS = YES 51 | 52 | 53 | GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES 54 | 55 | 56 | // Inline Methods Hidden 57 | // 58 | // When enabled, out-of-line copies of inline methods are declared 'private extern'. 59 | // [-fvisibility-inlines-hidden] 60 | 61 | GCC_INLINES_ARE_PRIVATE_EXTERN = NO 62 | 63 | 64 | // Precompile Prefix Header 65 | // 66 | // Generates a precompiled header for the prefix header, which should reduce overall 67 | // build times. 68 | // 69 | // Note: Precompiling the prefix header will be most effective if the contents of the 70 | // prefix header or any file it includes change rarely. If the contents of the prefix 71 | // header or any file it includes change frequently, there may be a negative impact to 72 | // overall build time. 73 | 74 | GCC_PRECOMPILE_PREFIX_HEADER = YES 75 | 76 | 77 | // Prefix Header 78 | // 79 | // Implicitly include the named header. The path given should either be a project 80 | // relative path or an absolute path. 81 | 82 | GCC_PREFIX_HEADER = $(MAXAPI_DIR)/max-includes/macho-prefix.pch 83 | 84 | 85 | // Preprocessor Macros 86 | // 87 | // Space-separated list of preprocessor macros of the form "foo" or "foo=bar". [-D] 88 | 89 | GCC_PREPROCESSOR_DEFINITIONS = $(BUILD_DEFS) $(CONFIG_DEFS) 90 | 91 | 92 | // Treat Missing Function Prototypes as Errors 93 | // 94 | // Causes warnings about missing function prototypes to be treated as errors. Only 95 | // applies to C and Objective-C. [-Werror-implicit-function-declaration] 96 | 97 | GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = NO 98 | 99 | 100 | // Missing Newline At End Of File 101 | // 102 | // Warn when a source file does not end with a newline. [-Wnewline-eof] 103 | 104 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES 105 | 106 | 107 | // Missing Function Prototypes 108 | // 109 | // Causes warnings to be emitted about missing prototypes. [-Wmissing-prototypes] 110 | 111 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES 112 | 113 | 114 | // Mismatched Return Type 115 | // 116 | // Causes warnings to be emitted when a function with a defined return type (not void) 117 | // contains a return statement without a return-value. Also emits a warning when a 118 | // function is defined without specifying a return type. [-Wreturn-type] 119 | 120 | GCC_WARN_ABOUT_RETURN_TYPE = YES 121 | 122 | 123 | // Check Switch Statements 124 | // 125 | // Warn whenever a switch statement has an index of enumeral type and lacks a case for 126 | // one or more of the named codes of that enumeration. The presence of a default label 127 | // prevents this warning. Case labels outside the enumeration range also provoke 128 | // warnings when this option is used. [-Wswitch] 129 | 130 | GCC_WARN_CHECK_SWITCH_STATEMENTS = YES 131 | 132 | 133 | // Missing Braces and Parentheses 134 | // 135 | // Warn if parentheses are omitted in certain contexts, such as when there is an 136 | // assignment in a context where a truth value is expected, or when operators are nested 137 | // whose precedence people often get confused about. 138 | // 139 | // Also warn about constructions where there may be confusion to which if statement an 140 | // else branch belongs. Here is an example of such a case: 141 | // { 142 | // if (a) 143 | // if (b) 144 | // foo (); 145 | // else 146 | // bar (); 147 | // } 148 | // 149 | // In C, every else branch belongs to the innermost possible if statement, which in this 150 | // example is if (b) . This is often not what the programmer expected, as illustrated in 151 | // the above example by indentation the programmer chose. When there is the potential 152 | // for this confusion, GCC will issue a warning when this flag is specified. To 153 | // eliminate the warning, add explicit braces around the innermost if statement so there 154 | // is no way the else could belong to the enclosing if . The resulting code would look 155 | // like this: 156 | // { 157 | // if (a) 158 | // { 159 | // if (b) 160 | // foo (); 161 | // else 162 | // bar (); 163 | // } 164 | // } 165 | // 166 | // [-Wparentheses] 167 | 168 | GCC_WARN_MISSING_PARENTHESES = YES 169 | 170 | 171 | // Hidden Local Variables 172 | // 173 | // Warn whenever a local variable shadows another local variable, parameter or global 174 | // variable or whenever a built-in function is shadowed. [-Wshadow] 175 | 176 | GCC_WARN_SHADOW = NO 177 | 178 | 179 | // Sign Comparison 180 | // 181 | // Warn when a comparison between signed and unsigned values could produce an incorrect 182 | // result when the signed value is converted to unsigned. [-Wsign-compare] 183 | 184 | GCC_WARN_SIGN_COMPARE = YES 185 | 186 | 187 | // Typecheck Calls to printf/scanf 188 | // 189 | // Check calls to printf and scanf, etc., to make sure that the arguments supplied have 190 | // types appropriate to the format string specified, and that the conversions specified 191 | // in the format string make sense. [-Wno-format] 192 | 193 | GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES 194 | 195 | 196 | // Uninitialized Variables 197 | // 198 | // Warn if a variable might be clobbered by a setjmp call or if an automatic variable is 199 | // used without prior initialization. 200 | // 201 | // Note that the compiler may not detect all cases where an automatic variable is 202 | // initialized or all usage patterns that may lead to use prior to initialization. You 203 | // can toggle between the normal uninitialized value checking or the more aggressive 204 | // (conservative) checking which finds more issues but the checking is much stricter. 205 | // [-Wuninitialized,-Wconditional-uninitialized] 206 | 207 | GCC_WARN_UNINITIALIZED_AUTOS = NO 208 | 209 | 210 | // Unused Functions 211 | // 212 | // Warn whenever a static function is declared but not defined or a non-inline static 213 | // function is unused. [-Wunused-function] 214 | 215 | GCC_WARN_UNUSED_FUNCTION = YES 216 | 217 | 218 | // Unused Labels 219 | // 220 | // Warn whenever a label is declared but not used. [-Wunused-label] 221 | 222 | GCC_WARN_UNUSED_LABEL = YES 223 | 224 | 225 | // Unused Parameters 226 | // 227 | // Warn whenever a function parameter is unused aside from its declaration. 228 | // [-Wunused-parameter] 229 | 230 | GCC_WARN_UNUSED_PARAMETER = NO 231 | 232 | 233 | // Unused Values 234 | // 235 | // Warn whenever a statement computes a result that is explicitly not used. 236 | // [-Wunused-value] 237 | 238 | GCC_WARN_UNUSED_VALUE = YES 239 | 240 | 241 | // Unused Variables 242 | // 243 | // Warn whenever a local variable or non-constant static variable is unused aside from 244 | // its declaration. [-Wunused-variable] 245 | 246 | GCC_WARN_UNUSED_VARIABLE = YES 247 | 248 | 249 | // Force Package Info Generation 250 | // 251 | // Forces the PkgInfo file to be written to wrapped products even if this file is not 252 | // expected. 253 | 254 | GENERATE_PKGINFO_FILE = YES 255 | 256 | 257 | // Header Search Paths 258 | // 259 | // This is a list of paths to folders to be searched by the compiler for included or 260 | // imported header files when compiling C, Objective-C, C++, or Objective-C++. Paths are 261 | // delimited by whitespace, so any paths with spaces in them need to be properly quoted. 262 | // [-I] 263 | 264 | HEADER_SEARCH_PATHS = $(MAXAPI_DIR)/** $(COMPONENTS_HEADER_DIRS) $(COMMON_HEADER_DIRS) $(VECLIB_FRAMEWORK_DIR)/vecLib.framework/Headers 265 | 266 | 267 | // Info.plist File 268 | // 269 | // This is the project-relative path to the plist file that contains the Info.plist 270 | // information used by bundles. 271 | 272 | INFOPLIST_FILE = external.plist 273 | 274 | 275 | // Library Search Paths 276 | // 277 | // This is a list of paths to folders to be searched by the linker for libraries used by 278 | // the product. Paths are delimited by whitespace, so any paths with spaces in them need 279 | // to be properly quoted. [-L] 280 | 281 | LIBRARY_SEARCH_PATHS = 282 | 283 | 284 | // OS X Deployment Target 285 | // 286 | // Code will load on this and later versions of OS X. Framework APIs that are 287 | // unavailable in earlier versions will be weak-linked; your code should check for null 288 | // function pointers or specific system versions before calling newer APIs. 289 | // 290 | // Compiler Default - Code will load on any Mac OS system that supports the APIs that are 291 | // used. 292 | // OS X 10.4 - Code will not load on systems earlier than 10.4. [10.4] 293 | // OS X 10.5 - Code will not load on systems earlier than 10.5. [10.5] 294 | // OS X 10.6 - Code will not load on systems earlier than 10.6. [10.6] 295 | // OS X 10.7 - Code will not load on systems earlier than 10.7. [10.7] 296 | // OS X 10.8 - Code will not load on systems earlier than 10.8. [10.8] 297 | // OS X 10.9 - Code will not load on systems earlier than 10.9. [10.9] 298 | 299 | MACOSX_DEPLOYMENT_TARGET = 10.6 300 | 301 | 302 | MAX_LINKER_FLAGS = -framework MaxAPI -framework MaxAudioAPI -Wl,-U,_object_new_imp,-U,_object_method_imp 303 | 304 | 305 | // Other Linker Flags 306 | // 307 | // Options defined in this setting are passed to invocations of the linker. 308 | 309 | OTHER_LDFLAGS = $(SYS_LINKER_FLAGS) $(MAX_LINKER_FLAGS) 310 | 311 | 312 | // Base SDK 313 | // 314 | // The name or path of the base SDK being used during the build. The product will be 315 | // built against the headers and libraries located inside the indicated SDK. This path 316 | // will be prepended to all search paths, and will be passed through the environment to 317 | // the compiler and linker. Additional SDKs can be specified in the ADDITIONAL_SDKS 318 | // setting. 319 | 320 | SDKROOT = macosx 321 | 322 | 323 | // Use Separate Strip 324 | // 325 | // Activating this setting when the linked product is to be stripped will cause stripping 326 | // to occur via a separate invocation of strip(1). Otherwise stripping will occur during 327 | // linking, if possible. 328 | 329 | SEPARATE_STRIP = YES 330 | 331 | 332 | SYS_LINKER_FLAGS = -lstdc++ -lmx -framework Accelerate -framework Carbon 333 | 334 | 335 | 336 | // Wrapper Extension 337 | // 338 | // This is the extension used for product wrappers, which has a default value based on 339 | // the product type. 340 | 341 | WRAPPER_EXTENSION = mxo 342 | -------------------------------------------------------------------------------- /examples/maxpipo/maxpipo-example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 21A040491B3C041A008E9540 /* pipo.gain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A040481B3C041A008E9540 /* pipo.gain.cpp */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXFileReference section */ 14 | 21A040371B3C01BA008E9540 /* pipo.gain.mxo */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = pipo.gain.mxo; sourceTree = BUILT_PRODUCTS_DIR; }; 15 | 21A0403B1B3C01BA008E9540 /* external.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = external.plist; sourceTree = ""; }; 16 | 21A040411B3C03B4008E9540 /* maxpipo-example-debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "maxpipo-example-debug.xcconfig"; sourceTree = ""; }; 17 | 21A040421B3C03B4008E9540 /* maxpipo-example-release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "maxpipo-example-release.xcconfig"; sourceTree = ""; }; 18 | 21A040431B3C03B4008E9540 /* maxpipo-example-shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "maxpipo-example-shared.xcconfig"; sourceTree = ""; }; 19 | 21A040471B3C0413008E9540 /* PiPoGain.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PiPoGain.h; sourceTree = SOURCE_ROOT; tabWidth = 8; }; 20 | 21A040481B3C041A008E9540 /* pipo.gain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pipo.gain.cpp; sourceTree = SOURCE_ROOT; }; 21 | 315B90411FB4ACEE0005150B /* PiPo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PiPo.h; path = ../../src/PiPo.h; sourceTree = ""; }; 22 | 315B90421FB4ACEE0005150B /* PiPoParallel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PiPoParallel.h; path = ../../src/PiPoParallel.h; sourceTree = ""; }; 23 | 315B90431FB4ACEE0005150B /* PiPoSequence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PiPoSequence.h; path = ../../src/PiPoSequence.h; sourceTree = ""; }; 24 | 315B90441FB4ACEE0005150B /* RingBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RingBuffer.h; path = ../../src/RingBuffer.h; sourceTree = ""; }; 25 | 315B90451FB4ACFF0005150B /* MaxPiPo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MaxPiPo.h; path = ../../bindings/max/MaxPiPo.h; sourceTree = ""; }; 26 | /* End PBXFileReference section */ 27 | 28 | /* Begin PBXFrameworksBuildPhase section */ 29 | 21A040341B3C01BA008E9540 /* Frameworks */ = { 30 | isa = PBXFrameworksBuildPhase; 31 | buildActionMask = 2147483647; 32 | files = ( 33 | ); 34 | runOnlyForDeploymentPostprocessing = 0; 35 | }; 36 | /* End PBXFrameworksBuildPhase section */ 37 | 38 | /* Begin PBXGroup section */ 39 | 21A0402E1B3C01BA008E9540 = { 40 | isa = PBXGroup; 41 | children = ( 42 | 315B903F1FB4ACA50005150B /* src */, 43 | 21A040411B3C03B4008E9540 /* maxpipo-example-debug.xcconfig */, 44 | 21A040421B3C03B4008E9540 /* maxpipo-example-release.xcconfig */, 45 | 21A040431B3C03B4008E9540 /* maxpipo-example-shared.xcconfig */, 46 | 21EDE88A1CCFDE4700F26EDC /* maxpipo */, 47 | 21A040391B3C01BA008E9540 /* pipo.gain */, 48 | 21A040381B3C01BA008E9540 /* Products */, 49 | ); 50 | sourceTree = ""; 51 | }; 52 | 21A040381B3C01BA008E9540 /* Products */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 21A040371B3C01BA008E9540 /* pipo.gain.mxo */, 56 | ); 57 | name = Products; 58 | sourceTree = ""; 59 | }; 60 | 21A040391B3C01BA008E9540 /* pipo.gain */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 21A040471B3C0413008E9540 /* PiPoGain.h */, 64 | 21A040481B3C041A008E9540 /* pipo.gain.cpp */, 65 | 21A0403B1B3C01BA008E9540 /* external.plist */, 66 | ); 67 | path = pipo.gain; 68 | sourceTree = ""; 69 | }; 70 | 21EDE88A1CCFDE4700F26EDC /* maxpipo */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 315B90451FB4ACFF0005150B /* MaxPiPo.h */, 74 | ); 75 | name = maxpipo; 76 | path = ../maxpipo; 77 | sourceTree = ""; 78 | }; 79 | 315B903F1FB4ACA50005150B /* src */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 315B90411FB4ACEE0005150B /* PiPo.h */, 83 | 315B90421FB4ACEE0005150B /* PiPoParallel.h */, 84 | 315B90431FB4ACEE0005150B /* PiPoSequence.h */, 85 | 315B90441FB4ACEE0005150B /* RingBuffer.h */, 86 | ); 87 | name = src; 88 | sourceTree = ""; 89 | }; 90 | /* End PBXGroup section */ 91 | 92 | /* Begin PBXNativeTarget section */ 93 | 21A040361B3C01BA008E9540 /* pipo.gain */ = { 94 | isa = PBXNativeTarget; 95 | buildConfigurationList = 21A0403E1B3C01BA008E9540 /* Build configuration list for PBXNativeTarget "pipo.gain" */; 96 | buildPhases = ( 97 | 21A040331B3C01BA008E9540 /* Sources */, 98 | 21A040341B3C01BA008E9540 /* Frameworks */, 99 | 21A040351B3C01BA008E9540 /* Resources */, 100 | ); 101 | buildRules = ( 102 | ); 103 | dependencies = ( 104 | ); 105 | name = pipo.gain; 106 | productName = pipo.gain; 107 | productReference = 21A040371B3C01BA008E9540 /* pipo.gain.mxo */; 108 | productType = "com.apple.product-type.bundle"; 109 | }; 110 | /* End PBXNativeTarget section */ 111 | 112 | /* Begin PBXProject section */ 113 | 21A0402F1B3C01BA008E9540 /* Project object */ = { 114 | isa = PBXProject; 115 | attributes = { 116 | LastUpgradeCheck = 0630; 117 | ORGANIZATIONNAME = ircam; 118 | TargetAttributes = { 119 | 21A040361B3C01BA008E9540 = { 120 | CreatedOnToolsVersion = 6.3.2; 121 | }; 122 | }; 123 | }; 124 | buildConfigurationList = 21A040321B3C01BA008E9540 /* Build configuration list for PBXProject "maxpipo-example" */; 125 | compatibilityVersion = "Xcode 3.2"; 126 | developmentRegion = English; 127 | hasScannedForEncodings = 0; 128 | knownRegions = ( 129 | en, 130 | ); 131 | mainGroup = 21A0402E1B3C01BA008E9540; 132 | productRefGroup = 21A040381B3C01BA008E9540 /* Products */; 133 | projectDirPath = ""; 134 | projectRoot = ""; 135 | targets = ( 136 | 21A040361B3C01BA008E9540 /* pipo.gain */, 137 | ); 138 | }; 139 | /* End PBXProject section */ 140 | 141 | /* Begin PBXResourcesBuildPhase section */ 142 | 21A040351B3C01BA008E9540 /* Resources */ = { 143 | isa = PBXResourcesBuildPhase; 144 | buildActionMask = 2147483647; 145 | files = ( 146 | ); 147 | runOnlyForDeploymentPostprocessing = 0; 148 | }; 149 | /* End PBXResourcesBuildPhase section */ 150 | 151 | /* Begin PBXSourcesBuildPhase section */ 152 | 21A040331B3C01BA008E9540 /* Sources */ = { 153 | isa = PBXSourcesBuildPhase; 154 | buildActionMask = 2147483647; 155 | files = ( 156 | 21A040491B3C041A008E9540 /* pipo.gain.cpp in Sources */, 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXSourcesBuildPhase section */ 161 | 162 | /* Begin XCBuildConfiguration section */ 163 | 21A0403C1B3C01BA008E9540 /* Debug */ = { 164 | isa = XCBuildConfiguration; 165 | baseConfigurationReference = 21A040411B3C03B4008E9540 /* maxpipo-example-debug.xcconfig */; 166 | buildSettings = { 167 | ALWAYS_SEARCH_USER_PATHS = NO; 168 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 169 | CLANG_CXX_LIBRARY = "libc++"; 170 | CLANG_ENABLE_MODULES = YES; 171 | CLANG_ENABLE_OBJC_ARC = YES; 172 | CLANG_WARN_BOOL_CONVERSION = YES; 173 | CLANG_WARN_CONSTANT_CONVERSION = YES; 174 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 175 | CLANG_WARN_EMPTY_BODY = YES; 176 | CLANG_WARN_ENUM_CONVERSION = YES; 177 | CLANG_WARN_INT_CONVERSION = YES; 178 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 179 | CLANG_WARN_UNREACHABLE_CODE = YES; 180 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 181 | COPY_PHASE_STRIP = NO; 182 | DEBUG_INFORMATION_FORMAT = dwarf; 183 | ENABLE_STRICT_OBJC_MSGSEND = YES; 184 | GCC_C_LANGUAGE_STANDARD = gnu99; 185 | GCC_DYNAMIC_NO_PIC = NO; 186 | GCC_NO_COMMON_BLOCKS = YES; 187 | GCC_OPTIMIZATION_LEVEL = 0; 188 | GCC_PREPROCESSOR_DEFINITIONS = ( 189 | "DEBUG=1", 190 | "$(inherited)", 191 | ); 192 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 193 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 194 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 195 | GCC_WARN_UNDECLARED_SELECTOR = YES; 196 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 197 | GCC_WARN_UNUSED_FUNCTION = YES; 198 | GCC_WARN_UNUSED_VARIABLE = YES; 199 | MACOSX_DEPLOYMENT_TARGET = 10.10; 200 | MTL_ENABLE_DEBUG_INFO = YES; 201 | ONLY_ACTIVE_ARCH = NO; 202 | }; 203 | name = Debug; 204 | }; 205 | 21A0403D1B3C01BA008E9540 /* Release */ = { 206 | isa = XCBuildConfiguration; 207 | baseConfigurationReference = 21A040421B3C03B4008E9540 /* maxpipo-example-release.xcconfig */; 208 | buildSettings = { 209 | ALWAYS_SEARCH_USER_PATHS = NO; 210 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 211 | CLANG_CXX_LIBRARY = "libc++"; 212 | CLANG_ENABLE_MODULES = YES; 213 | CLANG_ENABLE_OBJC_ARC = YES; 214 | CLANG_WARN_BOOL_CONVERSION = YES; 215 | CLANG_WARN_CONSTANT_CONVERSION = YES; 216 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 217 | CLANG_WARN_EMPTY_BODY = YES; 218 | CLANG_WARN_ENUM_CONVERSION = YES; 219 | CLANG_WARN_INT_CONVERSION = YES; 220 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 221 | CLANG_WARN_UNREACHABLE_CODE = YES; 222 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 223 | COPY_PHASE_STRIP = NO; 224 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 225 | ENABLE_NS_ASSERTIONS = NO; 226 | ENABLE_STRICT_OBJC_MSGSEND = YES; 227 | GCC_C_LANGUAGE_STANDARD = gnu99; 228 | GCC_NO_COMMON_BLOCKS = YES; 229 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 230 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 231 | GCC_WARN_UNDECLARED_SELECTOR = YES; 232 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 233 | GCC_WARN_UNUSED_FUNCTION = YES; 234 | GCC_WARN_UNUSED_VARIABLE = YES; 235 | MACOSX_DEPLOYMENT_TARGET = 10.10; 236 | MTL_ENABLE_DEBUG_INFO = NO; 237 | }; 238 | name = Release; 239 | }; 240 | 21A0403F1B3C01BA008E9540 /* Debug */ = { 241 | isa = XCBuildConfiguration; 242 | buildSettings = { 243 | INFOPLIST_FILE = external.plist; 244 | PRODUCT_NAME = "$(TARGET_NAME)"; 245 | }; 246 | name = Debug; 247 | }; 248 | 21A040401B3C01BA008E9540 /* Release */ = { 249 | isa = XCBuildConfiguration; 250 | buildSettings = { 251 | INFOPLIST_FILE = external.plist; 252 | PRODUCT_NAME = "$(TARGET_NAME)"; 253 | }; 254 | name = Release; 255 | }; 256 | /* End XCBuildConfiguration section */ 257 | 258 | /* Begin XCConfigurationList section */ 259 | 21A040321B3C01BA008E9540 /* Build configuration list for PBXProject "maxpipo-example" */ = { 260 | isa = XCConfigurationList; 261 | buildConfigurations = ( 262 | 21A0403C1B3C01BA008E9540 /* Debug */, 263 | 21A0403D1B3C01BA008E9540 /* Release */, 264 | ); 265 | defaultConfigurationIsVisible = 0; 266 | defaultConfigurationName = Release; 267 | }; 268 | 21A0403E1B3C01BA008E9540 /* Build configuration list for PBXNativeTarget "pipo.gain" */ = { 269 | isa = XCConfigurationList; 270 | buildConfigurations = ( 271 | 21A0403F1B3C01BA008E9540 /* Debug */, 272 | 21A040401B3C01BA008E9540 /* Release */, 273 | ); 274 | defaultConfigurationIsVisible = 0; 275 | defaultConfigurationName = Release; 276 | }; 277 | /* End XCConfigurationList section */ 278 | }; 279 | rootObject = 21A0402F1B3C01BA008E9540 /* Project object */; 280 | } 281 | -------------------------------------------------------------------------------- /examples/maxpipo/pipo.gain.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @file pipo.gain.cpp 4 | * @author Norbert.Schnell@ircam.fr 5 | * 6 | * @brief scaling PiPo 7 | * 8 | * Copyright (C) 2012-2014 by IRCAM – Centre Pompidou, Paris, France. 9 | * All rights reserved. 10 | * 11 | */ 12 | #include "PiPoGain.h" 13 | #include "MaxPiPo.h" 14 | 15 | PIPO_MAX_CLASS("gain", PiPoGain); 16 | -------------------------------------------------------------------------------- /examples/maxpipo/pipo.gain.maxhelp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "appversion" : { 5 | "major" : 7, 6 | "minor" : 0, 7 | "revision" : 2, 8 | "architecture" : "x86", 9 | "modernui" : 1 10 | } 11 | , 12 | "rect" : [ 34.0, 79.0, 640.0, 480.0 ], 13 | "bglocked" : 0, 14 | "openinpresentation" : 0, 15 | "default_fontsize" : 12.0, 16 | "default_fontface" : 0, 17 | "default_fontname" : "Arial", 18 | "gridonopen" : 1, 19 | "gridsize" : [ 15.0, 15.0 ], 20 | "gridsnaponopen" : 1, 21 | "objectsnaponopen" : 1, 22 | "statusbarvisible" : 2, 23 | "toolbarvisible" : 1, 24 | "lefttoolbarpinned" : 0, 25 | "toptoolbarpinned" : 0, 26 | "righttoolbarpinned" : 0, 27 | "bottomtoolbarpinned" : 0, 28 | "toolbars_unpinned_last_save" : 0, 29 | "tallnewobj" : 0, 30 | "boxanimatetime" : 200, 31 | "enablehscroll" : 1, 32 | "enablevscroll" : 1, 33 | "devicewidth" : 0.0, 34 | "description" : "", 35 | "digest" : "", 36 | "tags" : "", 37 | "style" : "", 38 | "subpatcher_template" : "", 39 | "boxes" : [ { 40 | "box" : { 41 | "id" : "obj-15", 42 | "maxclass" : "message", 43 | "numinlets" : 2, 44 | "numoutlets" : 1, 45 | "outlettype" : [ "" ], 46 | "patching_rect" : [ 139.0, 306.0, 49.0, 22.0 ], 47 | "style" : "", 48 | "text" : "clearall" 49 | } 50 | 51 | } 52 | , { 53 | "box" : { 54 | "id" : "obj-14", 55 | "maxclass" : "button", 56 | "numinlets" : 1, 57 | "numoutlets" : 1, 58 | "outlettype" : [ "bang" ], 59 | "patching_rect" : [ 34.0, 344.0, 24.0, 24.0 ], 60 | "style" : "" 61 | } 62 | 63 | } 64 | , { 65 | "box" : { 66 | "id" : "obj-12", 67 | "maxclass" : "message", 68 | "numinlets" : 2, 69 | "numoutlets" : 1, 70 | "outlettype" : [ "" ], 71 | "patching_rect" : [ 33.0, 266.0, 203.0, 22.0 ], 72 | "style" : "", 73 | "text" : "readappend jongly.aif @name audio" 74 | } 75 | 76 | } 77 | , { 78 | "box" : { 79 | "fontface" : 0, 80 | "fontname" : "Arial", 81 | "fontsize" : 12.0, 82 | "id" : "obj-9", 83 | "maxclass" : "newobj", 84 | "numinlets" : 1, 85 | "numoutlets" : 1, 86 | "outlettype" : [ "" ], 87 | "patching_rect" : [ 33.0, 306.0, 83.0, 22.0 ], 88 | "saved_object_attributes" : { 89 | "embed" : 0, 90 | "externalfiles" : 1 91 | } 92 | , 93 | "style" : "", 94 | "text" : "mubu mydata" 95 | } 96 | 97 | } 98 | , { 99 | "box" : { 100 | "fontface" : 0, 101 | "fontname" : "Arial", 102 | "fontsize" : 12.0, 103 | "id" : "obj-7", 104 | "maxclass" : "newobj", 105 | "numinlets" : 2, 106 | "numoutlets" : 4, 107 | "outlettype" : [ "", "", "int", "" ], 108 | "patching_rect" : [ 33.0, 381.0, 489.0, 22.0 ], 109 | "style" : "", 110 | "text" : "mubu.process mydata audio gain @gain.factor 0.5 @name output @info gui \"fgcolor blue\"" 111 | } 112 | 113 | } 114 | , { 115 | "box" : { 116 | "format" : 6, 117 | "id" : "obj-10", 118 | "maxclass" : "flonum", 119 | "numinlets" : 1, 120 | "numoutlets" : 2, 121 | "outlettype" : [ "", "bang" ], 122 | "parameter_enable" : 0, 123 | "patching_rect" : [ 250.0, 52.0, 50.0, 22.0 ], 124 | "style" : "" 125 | } 126 | 127 | } 128 | , { 129 | "box" : { 130 | "id" : "obj-8", 131 | "maxclass" : "message", 132 | "numinlets" : 2, 133 | "numoutlets" : 1, 134 | "outlettype" : [ "" ], 135 | "patching_rect" : [ 104.0, 187.0, 135.0, 22.0 ], 136 | "style" : "", 137 | "text" : "88. 88. 6." 138 | } 139 | 140 | } 141 | , { 142 | "box" : { 143 | "fontname" : "Arial", 144 | "fontsize" : 12.0, 145 | "format" : 6, 146 | "id" : "obj-6", 147 | "maxclass" : "flonum", 148 | "numinlets" : 1, 149 | "numoutlets" : 2, 150 | "outlettype" : [ "", "bang" ], 151 | "parameter_enable" : 0, 152 | "patching_rect" : [ 118.0, 33.0, 50.0, 22.0 ], 153 | "style" : "" 154 | } 155 | 156 | } 157 | , { 158 | "box" : { 159 | "fontname" : "Arial", 160 | "fontsize" : 12.0, 161 | "id" : "obj-2", 162 | "maxclass" : "message", 163 | "numinlets" : 2, 164 | "numoutlets" : 1, 165 | "outlettype" : [ "" ], 166 | "patching_rect" : [ 118.0, 83.0, 51.0, 22.0 ], 167 | "style" : "", 168 | "text" : "$1 $1 3" 169 | } 170 | 171 | } 172 | , { 173 | "box" : { 174 | "fontname" : "Arial", 175 | "fontsize" : 12.0, 176 | "id" : "obj-5", 177 | "maxclass" : "message", 178 | "numinlets" : 2, 179 | "numoutlets" : 1, 180 | "outlettype" : [ "" ], 181 | "patching_rect" : [ 250.0, 83.0, 83.0, 22.0 ], 182 | "style" : "", 183 | "text" : "gain.factor $1" 184 | } 185 | 186 | } 187 | , { 188 | "box" : { 189 | "fontname" : "Arial", 190 | "fontsize" : 12.0, 191 | "format" : 6, 192 | "id" : "obj-4", 193 | "maxclass" : "flonum", 194 | "numinlets" : 1, 195 | "numoutlets" : 2, 196 | "outlettype" : [ "", "bang" ], 197 | "parameter_enable" : 0, 198 | "patching_rect" : [ 33.0, 187.0, 50.0, 22.0 ], 199 | "style" : "" 200 | } 201 | 202 | } 203 | , { 204 | "box" : { 205 | "fontname" : "Arial", 206 | "fontsize" : 12.0, 207 | "format" : 6, 208 | "id" : "obj-3", 209 | "maxclass" : "flonum", 210 | "numinlets" : 1, 211 | "numoutlets" : 2, 212 | "outlettype" : [ "", "bang" ], 213 | "parameter_enable" : 0, 214 | "patching_rect" : [ 33.0, 83.0, 50.0, 22.0 ], 215 | "style" : "" 216 | } 217 | 218 | } 219 | , { 220 | "box" : { 221 | "fontface" : 0, 222 | "fontname" : "Arial", 223 | "fontsize" : 12.0, 224 | "id" : "obj-1", 225 | "maxclass" : "newobj", 226 | "numinlets" : 2, 227 | "numoutlets" : 3, 228 | "outlettype" : [ "", "float", "" ], 229 | "patching_rect" : [ 33.0, 139.0, 141.0, 22.0 ], 230 | "style" : "", 231 | "text" : "pipo gain @gain.factor 2" 232 | } 233 | 234 | } 235 | ], 236 | "lines" : [ { 237 | "patchline" : { 238 | "destination" : [ "obj-4", 0 ], 239 | "disabled" : 0, 240 | "hidden" : 0, 241 | "source" : [ "obj-1", 0 ] 242 | } 243 | 244 | } 245 | , { 246 | "patchline" : { 247 | "destination" : [ "obj-8", 1 ], 248 | "disabled" : 0, 249 | "hidden" : 0, 250 | "source" : [ "obj-1", 0 ] 251 | } 252 | 253 | } 254 | , { 255 | "patchline" : { 256 | "destination" : [ "obj-5", 0 ], 257 | "disabled" : 0, 258 | "hidden" : 0, 259 | "source" : [ "obj-10", 0 ] 260 | } 261 | 262 | } 263 | , { 264 | "patchline" : { 265 | "destination" : [ "obj-9", 0 ], 266 | "disabled" : 0, 267 | "hidden" : 0, 268 | "source" : [ "obj-12", 0 ] 269 | } 270 | 271 | } 272 | , { 273 | "patchline" : { 274 | "destination" : [ "obj-7", 0 ], 275 | "disabled" : 0, 276 | "hidden" : 0, 277 | "source" : [ "obj-14", 0 ] 278 | } 279 | 280 | } 281 | , { 282 | "patchline" : { 283 | "destination" : [ "obj-9", 0 ], 284 | "disabled" : 0, 285 | "hidden" : 0, 286 | "source" : [ "obj-15", 0 ] 287 | } 288 | 289 | } 290 | , { 291 | "patchline" : { 292 | "destination" : [ "obj-1", 0 ], 293 | "disabled" : 0, 294 | "hidden" : 0, 295 | "source" : [ "obj-2", 0 ] 296 | } 297 | 298 | } 299 | , { 300 | "patchline" : { 301 | "destination" : [ "obj-1", 0 ], 302 | "disabled" : 0, 303 | "hidden" : 0, 304 | "source" : [ "obj-3", 0 ] 305 | } 306 | 307 | } 308 | , { 309 | "patchline" : { 310 | "destination" : [ "obj-1", 0 ], 311 | "disabled" : 0, 312 | "hidden" : 0, 313 | "source" : [ "obj-5", 0 ] 314 | } 315 | 316 | } 317 | , { 318 | "patchline" : { 319 | "destination" : [ "obj-2", 0 ], 320 | "disabled" : 0, 321 | "hidden" : 0, 322 | "source" : [ "obj-6", 0 ] 323 | } 324 | 325 | } 326 | ], 327 | "dependency_cache" : [ { 328 | "name" : "pipo.mxo", 329 | "type" : "iLaX" 330 | } 331 | , { 332 | "name" : "mubu.mxo", 333 | "type" : "iLaX" 334 | } 335 | , { 336 | "name" : "mubu.mxo", 337 | "type" : "iLaX" 338 | } 339 | ], 340 | "embedsnapshot" : 0 341 | } 342 | 343 | } 344 | -------------------------------------------------------------------------------- /examples/maxpipo/pipo.gain.mxo/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 15G22010 7 | CFBundleExecutable 8 | pipo.gain 9 | CFBundlePackageType 10 | iLaX 11 | CFBundleShortVersionString 12 | 1.1 13 | CFBundleSupportedPlatforms 14 | 15 | MacOSX 16 | 17 | CFBundleVersion 18 | 1.1 19 | DTCompiler 20 | com.apple.compilers.llvm.clang.1_0 21 | DTPlatformBuild 22 | 8C38 23 | DTPlatformVersion 24 | GM 25 | DTSDKBuild 26 | 14D125 27 | DTSDKName 28 | macosx10.10 29 | DTXcode 30 | 0820 31 | DTXcodeBuild 32 | 8C38 33 | 34 | 35 | -------------------------------------------------------------------------------- /examples/maxpipo/pipo.gain.mxo/Contents/MacOS/pipo.gain: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ircam-ismm/pipo-sdk/9d9605b1f017cb84f3bc4d50f4f82ecf29281a5d/examples/maxpipo/pipo.gain.mxo/Contents/MacOS/pipo.gain -------------------------------------------------------------------------------- /examples/maxpipo/pipo.gain.mxo/Contents/PkgInfo: -------------------------------------------------------------------------------- 1 | iLaX???? -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | 2 | doc/html/index.html: include/PiPo.h include/PiPoParallel.h include/PiPoSequence.h doc/pipo.doxygen makefile 3 | cd doc && doxygen pipo.doxygen 4 | 5 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 2 | # PiPo — Plugin Interface for Processing Objects # 3 | 4 | PiPo is an extremely simple plugin API for modules processing streams of multi-dimensional data such as audio, audio descriptors, or gesture and motion data. The current version of the interface is limited to unary operations. Each PiPo module receives and produces a single stream. The elements of a stream are time-tagged or regularly sampled scalars, vectors, or two-dimensional matrices. 5 | 6 | 7 | ### More Information 8 | 9 | http://ismm.ircam.fr/pipo/ 10 | 11 | ### Authors 12 | 13 | This code has been initially authored by Norbert Schnell in the Sound Music Movement Interaction team of the STMS Lab - IRCAM - CNRS - UPMC. 14 | 15 | ### Copyright 16 | 17 | Copyright (c) 2012–2016 by IRCAM – Centre Pompidou, Paris, France. 18 | All rights reserved. 19 | 20 | ### Licence: BSD 3-clause 21 | 22 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 23 | 24 | - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 25 | 26 | - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 27 | 28 | - Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 29 | 30 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | 32 | ### Features 33 | 34 | PiPo has been developed to be make things simple for users and developers. 35 | 36 | #### User Level Features 37 | 38 | - Easy integration and customization of stream processing modules 39 | - Suited for filtering, transformation, extraction, and segmentation algorithms 40 | - Real-time and offline processing 41 | - Applying to audio and control streams (for whom this distinction still makes sense) 42 | 43 | #### Developer Level Features 44 | 45 | - Fast and easy implementation of modules and reuse of code for different contexts 46 | - C/C++ API defined by a single header file without additional dependencies 47 | - Core API as single abstract class defining a small set of virtual methods 48 | 49 | #### PiPo Stream Attributes 50 | 51 | PiPo streams are a sequences of frames characterized by a set of attributes. A PiPo module defines the attributes of its output stream when receiving the attributes of the input stream. 52 | 53 | Each module can configure its internal state depending on the attributes of the input stream (e.g. memory allocation and pre-calculated state variables) before propagating its output stream attributes to the next module. 54 | 55 | This way, the attributes of the input stream are propagated through a series of PiPo modules before starting the actual stream processing. 56 | 57 | In summary, a PiPo stream is described by the following attributes: 58 | 59 | - a boolean representing whether the elements of the stream are time-tagged 60 | - frame rate (highest average rate for time-tagged streams) 61 | - lag of the output stream relative to the input 62 | - frame width (also number of channels or matrix columns) 63 | - frame size (or number of matrix rows) 64 | - labels (for the frame channels or columns) 65 | - a boolean representing whether the frames have a variable size (respecting the given frame size as maximum) 66 | - extent of a frame in the given domain (e.g. duration or frequency range) 67 | - maximum number of frames in a block exchanged between two modules 68 | 69 | #### PiPo Module Parameters 70 | 71 | The PiPo SDK comes with a template class [PiPo::Attr](http://recherche.ircam.fr/equipes/temps-reel/mubu/pipo/sdk-doc-v0.1/class_pi_po_1_1_attr.html) permits to define scalar, enum, or variable or fixed size vector attributes of a pipo module that are exposed to the host environment. 72 | 73 | Since certain parameter changes may also change the attributes of a module’s output stream, PiPo provides a mechanism for signaling these changes through the following modules to the processing environment (i.e. the PiPo host). 74 | 75 | For MAX/MSP PiPo includes a binding to extend a PiPo class to a Max/MSP external that then declares the module's parameters as Max/MSP attributes and implement the required setters and getters. 76 | 77 | ## PiPo API 78 | 79 | ### Module API 80 | 81 | The PiPo Module API consists of the abstract class [PiPo](http://recherche.ircam.fr/equipes/temps-reel/mubu/pipo/sdk-doc-v0.1/class_pi_po.html) in [PiPo.h](include/PiPo.h) of a few virtual methods for propagating stream attributes (see above), frames, and additional processing control through a series of modules: 82 | 83 | - Propagating stream attributes 84 | - Propagating frames 85 | - Reset stream processing 86 | - Finalize stream processing 87 | - Propagate the change of a parameter requiring redefining the output stream attributes 88 | 89 | See the doc extraced from [PiPo.h](include/PiPo.h) at: http://recherche.ircam.fr/equipes/temps-reel/mubu/pipo/sdk-doc-v0.1/ 90 | 91 | ### Host API 92 | 93 | Classes supporting implementation of PiPo hosts are found in directory [host](host). 94 | -------------------------------------------------------------------------------- /src/PiPoParallel.h: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | @file PiPoParallel.h 4 | @author Diemo.Schwarz@ircam.fr 5 | 6 | @brief PiPo dataflow graph class that encapsulates a parallel section of pipo modules. 7 | 8 | @copyright 9 | 10 | Copyright (c) 2012–2016 by IRCAM – Centre Pompidou, Paris, France. 11 | All rights reserved. 12 | 13 | @par License (BSD 3-clause) 14 | 15 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 16 | 17 | - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 18 | 19 | - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 20 | 21 | - Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | */ 26 | 27 | #ifndef _PIPO_PARALLEL_H_ 28 | #define _PIPO_PARALLEL_H_ 29 | 30 | #include //db 31 | #include //db 32 | #include "PiPo.h" 33 | 34 | #define PIPO_DEBUG DEBUG*1 35 | 36 | class PiPoParallel : public PiPo 37 | { 38 | private: 39 | /** class to merge several parallel pipo data streams, combining columns 40 | */ 41 | class PiPoMerge : public PiPo 42 | { 43 | private: 44 | # define MAX_PAR 64 45 | int count_; 46 | int numpar_; 47 | PiPoStreamAttributes sa_; // combined stream attributes 48 | int paroffset_[MAX_PAR]; // cumulative column offsets in output array 49 | int parwidth_[MAX_PAR]; // column widths of parallel pipos 50 | int framesize_; // output frame size = width * maxheight 51 | 52 | // working variables for merging of frames 53 | PiPoValue *values_; 54 | int time_; 55 | unsigned int numrows_; 56 | unsigned int numframes_; 57 | 58 | public: 59 | PiPoMerge (PiPo::Parent *parent) 60 | : PiPo(parent), count_(0), numpar_(0), sa_(1024), framesize_(0), values_(NULL) 61 | { 62 | #ifdef DEBUG // clean memory to make possible memory errors more consistent at least 63 | memset(paroffset_, 0, sizeof(*paroffset_) * MAX_PAR); 64 | memset(parwidth_, 0, sizeof(*parwidth_) * MAX_PAR); 65 | #endif 66 | } 67 | 68 | // copy constructor 69 | PiPoMerge (const PiPoMerge &other) 70 | : PiPo(other.parent), count_(other.count_), numpar_(other.numpar_), sa_(other.sa_), framesize_(other.framesize_) 71 | { 72 | #if defined(__GNUC__) && PIPO_DEBUG >= 2 73 | printf("\n•••••• %s: COPY CONSTRUCTOR\n", __PRETTY_FUNCTION__); //db 74 | #endif 75 | 76 | #ifdef DEBUG // clean memory to make possible memory errors more consistent at least 77 | memset(paroffset_, 0, sizeof(*paroffset_) * MAX_PAR); 78 | memset(parwidth_, 0, sizeof(*parwidth_) * MAX_PAR); 79 | #endif 80 | 81 | memcpy(paroffset_, other.paroffset_, numpar_ * sizeof(int)); 82 | memcpy(parwidth_, other.parwidth_, numpar_ * sizeof(int)); 83 | values_ = (PiPoValue *) malloc(sa_.maxFrames * framesize_ * sizeof(PiPoValue)); 84 | memcpy(values_, other.values_, sa_.maxFrames * framesize_ * sizeof(PiPoValue)); 85 | } 86 | 87 | // assignment operator 88 | PiPoMerge &operator= (const PiPoMerge &other) 89 | { 90 | #if defined(__GNUC__) && PIPO_DEBUG >= 2 91 | printf("\n•••••• %s: ASSIGNMENT OPERATOR\n", __PRETTY_FUNCTION__); //db 92 | #endif 93 | 94 | #ifdef DEBUG // clean memory to make possible memory errors more consistent at least 95 | memset(paroffset_, 0, sizeof(*paroffset_) * MAX_PAR); 96 | memset(parwidth_, 0, sizeof(*parwidth_) * MAX_PAR); 97 | #endif 98 | 99 | count_ = other.count_; 100 | numpar_ = other.numpar_; 101 | sa_ = other.sa_; 102 | framesize_ = other.framesize_; 103 | 104 | memcpy(paroffset_, other.paroffset_, numpar_ * sizeof(int)); 105 | memcpy(parwidth_, other.parwidth_, numpar_ * sizeof(int)); 106 | values_ = (PiPoValue *) malloc(sa_.maxFrames * framesize_ * sizeof(PiPoValue)); 107 | memcpy(values_, other.values_, sa_.maxFrames * framesize_ * sizeof(PiPoValue)); 108 | 109 | return *this; 110 | } 111 | 112 | // destructor 113 | ~PiPoMerge () 114 | { 115 | free(values_); 116 | } 117 | 118 | public: 119 | void start (size_t numpar) 120 | { // on start, record number of calls to expect from parallel pipos, each received stream call increments count_, when numpar_ is reached, merging has to be performed 121 | numpar_ = (int) numpar; 122 | count_ = 0; 123 | } 124 | 125 | // TODO: signal end of parallel pipos, accomodates for possibly missing calls down the chain 126 | void finish () 127 | { 128 | } 129 | 130 | public: 131 | int streamAttributes (bool hasTimeTags, double rate, double offset, unsigned int width, unsigned int height, const char **labels, bool hasVarSize, double domain, unsigned int maxFrames) 132 | { // collect stream attributes declarations from parallel pipos 133 | #if PIPO_DEBUG >= 1 134 | printf("PiPoParallel streamAttributes timetags %d rate %f offset %f width %d height %d labels %s varsize %d domain %f maxframes %d\n", 135 | hasTimeTags, rate, offset, width, height, labels ? labels[0] : "n/a", hasVarSize, domain, maxFrames); 136 | #endif 137 | 138 | if (count_ == 0) 139 | { // first parallel pipo defines most stream attributes, we store then here 140 | sa_.hasTimeTags = hasTimeTags; 141 | sa_.rate = rate; 142 | sa_.offset = offset; 143 | sa_.dims[0] = width; 144 | sa_.dims[1] = height; 145 | sa_.numLabels = 0; 146 | sa_.hasVarSize = hasVarSize; 147 | sa_.domain = domain; 148 | sa_.maxFrames = maxFrames; 149 | sa_.concat_labels(labels, width); 150 | 151 | paroffset_[0] = 0; 152 | parwidth_[0] = width; 153 | } 154 | else 155 | { // apply merge rules with following pipos 156 | // columns are concatenated 157 | sa_.concat_labels(labels, width); 158 | sa_.dims[0] += width; 159 | paroffset_[count_] = paroffset_[count_ - 1] + parwidth_[count_ - 1]; 160 | parwidth_[count_] = width; 161 | 162 | //TODO: check maxframes, height, should not differ 163 | //TODO: option to transpose column vectors 164 | } 165 | 166 | if (++count_ == numpar_) 167 | { // last parallel pipo, now reserve memory and pass merged stream attributes onwards 168 | framesize_ = sa_.dims[0] * sa_.dims[1]; 169 | values_ = (PiPoValue *) realloc(values_, sa_.maxFrames * framesize_ * sizeof(PiPoValue)); // alloc space for maxmal block size 170 | 171 | return propagateStreamAttributes(sa_.hasTimeTags, sa_.rate, sa_.offset, sa_.dims[0], sa_.dims[1], sa_.labels, sa_.hasVarSize, sa_.domain, sa_.maxFrames); 172 | } 173 | else 174 | return 0; // continue receiving stream attributes 175 | } 176 | 177 | 178 | int reset () 179 | { 180 | if (++count_ == numpar_) 181 | return this->propagateReset(); 182 | else 183 | return 0; // continue receiving reset 184 | } 185 | 186 | 187 | int frames (double time, double weight, PiPoValue *values, unsigned int size, unsigned int num) 188 | { // collect data from parallel pipos 189 | if (count_ >= numpar_) // bug is still there 190 | { 191 | #ifdef WIN32 192 | printf("%s: ARGH! count_ %d >= numpar_ %d\n", __FUNCSIG__, count_, numpar_); 193 | #else 194 | printf("%s: ARGH! count_ %d >= numpar_ %d\n", __PRETTY_FUNCTION__, count_, numpar_); 195 | #endif 196 | count_ = numpar_ - 1; 197 | } 198 | //assert(size / parwidth_[count_] == 1); 199 | 200 | int width = parwidth_[count_]; 201 | unsigned int height = size / width; // number of input rows 202 | 203 | if (count_ == 0) 204 | { // first parallel pipo determines time tag, num. rows and frames 205 | time_ = time; 206 | numrows_ = height; 207 | numframes_ = num; 208 | 209 | // clear memory just in case one pipo doesn't output data (FIXME: handle this correctly) 210 | memset(values_, 0, num * framesize_ * sizeof(PiPoValue)); 211 | } 212 | 213 | // copy input data to be kept from parallel pipo to merged values_ 214 | if (num > numframes_) num = numframes_; 215 | if (height > numrows_) height = numrows_; 216 | 217 | for (unsigned int i = 0; i < num; i++) // for all frames present 218 | for (unsigned int k = 0; k < height; k++) // for all rows to be kept 219 | { 220 | //printf("merge::frames %p\n values_ %p + %d + %d + %d,\n values %p + %d,\n size %d\n", 221 | // this, values_, i * framesize_, k * sa_.dims[0], paroffset_[count_], values, i * size, parwidth_[count_] * sizeof(PiPoValue)); 222 | //TODO: zero pad if num rows here: size / parwidth_[count_] < numrows_ 223 | memcpy(values_ + i * framesize_ + k * sa_.dims[0] + paroffset_[count_], 224 | values + i * size + k * width, width * sizeof(PiPoValue)); 225 | } 226 | 227 | if (++count_ == numpar_) // last parallel pipo: pass on to receiver(s) 228 | return propagateFrames(time_, 0 /*weight to disappear*/, values_, numrows_ * sa_.dims[0], numframes_); 229 | else 230 | return 0; // continue receiving frames 231 | } 232 | 233 | 234 | int finalize (double inputEnd) 235 | { 236 | if (count_ == 0) 237 | time_ = inputEnd; 238 | 239 | if (++count_ == numpar_) 240 | return this->propagateFinalize(time_); 241 | else 242 | return 0; // continue receiving finalize 243 | } 244 | }; // end class PiPoMerge 245 | 246 | PiPoMerge merge; 247 | 248 | public: 249 | // constructor 250 | PiPoParallel (PiPo::Parent *parent) 251 | : PiPo(parent), merge(parent) 252 | { } 253 | 254 | //TODO: varargs constructor PiPoParallel (PiPo::Parent *parent, PiPo *pipos ...) 255 | 256 | private: 257 | // copy constructor 258 | PiPoParallel (const PiPoParallel &other) 259 | : PiPo(other), merge(other.merge) 260 | { } 261 | 262 | // assignment operator 263 | const PiPoParallel& operator= (const PiPoParallel &other) 264 | { 265 | parent = other.parent; 266 | merge = other.merge; 267 | 268 | return *this; 269 | } 270 | 271 | public: 272 | // destructor 273 | ~PiPoParallel (void) { } 274 | 275 | 276 | /** @name PiPoParallel setup methods */ 277 | /** @{ */ 278 | 279 | /** Add module @p{pipo} to the data flow graph in parallel. 280 | */ 281 | void add (PiPo *pipo) 282 | { // add to list of receivers of this parallel module, to branch out on input 283 | PiPo::setReceiver(pipo, true); 284 | // then connect module to internal merge module 285 | pipo->setReceiver(&merge); 286 | } 287 | 288 | void add (PiPo &pipo) 289 | { 290 | add(&pipo); 291 | } 292 | 293 | /** @} PiPoParallel setup methods */ 294 | 295 | /** @name overloaded PiPo methods */ 296 | /** @{ */ 297 | 298 | void setParent (PiPo::Parent *parent) 299 | { 300 | this->parent = parent; 301 | 302 | for (unsigned int i = 0; i < receivers.size(); i++) 303 | receivers[i]->setParent(parent); 304 | } 305 | 306 | void setReceiver (PiPo *receiver, bool add = false) 307 | { 308 | merge.setReceiver(receiver, add); 309 | } 310 | 311 | /** @name preparation and processing methods: just notify merge, and let propagate* do the branching */ 312 | /** @{ */ 313 | 314 | /** start stream preparation */ 315 | int streamAttributes (bool hasTimeTags, double rate, double offset, unsigned int width, unsigned int height, const char **labels, bool hasVarSize, double domain, unsigned int maxFrames) 316 | { 317 | merge.start(receivers.size()); 318 | return PiPo::propagateStreamAttributes(hasTimeTags, rate, offset, width, height, labels, hasVarSize, domain, maxFrames); 319 | } 320 | 321 | int reset () 322 | { 323 | merge.start(receivers.size()); 324 | return PiPo::propagateReset(); 325 | } 326 | 327 | /** @} end of preparation of processing methods */ 328 | 329 | /** @name processing */ 330 | /** @{ */ 331 | 332 | int frames (double time, double weight, PiPoValue *values, unsigned int size, unsigned int num) 333 | { 334 | merge.start(receivers.size()); 335 | return PiPo::propagateFrames(time, weight, values, size, num); 336 | } 337 | 338 | int finalize (double inputEnd) 339 | { 340 | merge.start(receivers.size()); 341 | return PiPo::propagateFinalize(inputEnd); 342 | } 343 | 344 | /** @} end of processing methods */ 345 | /** @} end of overloaded PiPo methods */ 346 | }; 347 | 348 | #endif /* _PIPO_PARALLEL_H_ */ 349 | 350 | 351 | /** EMACS ** 352 | * Local variables: 353 | * mode: c++ 354 | * c-basic-offset:2 355 | * End: 356 | */ 357 | -------------------------------------------------------------------------------- /src/PiPoSequence.h: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | @file PiPoSequence.h 4 | @author Diemo.Schwarz@ircam.fr 5 | 6 | @brief PiPo dataflow graph class that encapsulates a sequence of pipo modules. 7 | 8 | @copyright 9 | 10 | Copyright (c) 2012–2016 by IRCAM – Centre Pompidou, Paris, France. 11 | All rights reserved. 12 | 13 | @par License (BSD 3-clause) 14 | 15 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 16 | 17 | - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 18 | 19 | - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 20 | 21 | - Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | */ 26 | 27 | #ifndef _PIPO_SEQUENCE_ 28 | #define _PIPO_SEQUENCE_ 29 | 30 | #include "PiPo.h" 31 | 32 | class PiPoSequence : public PiPo 33 | { 34 | private: 35 | std::vector seq_; 36 | 37 | public: 38 | // constructor 39 | PiPoSequence (PiPo::Parent *parent) 40 | : PiPo(parent), seq_() 41 | { } 42 | 43 | #if __cplusplus > 199711L // check for C++11 44 | /** varargs constructor with a list of pipos that will be connected: 45 | 46 | PiPoSequence (PiPo::Parent *parent, PiPo &pipos ...) 47 | seq(parent, pipo1, pipo2, ...); 48 | 49 | (using C++11 variadic templates) 50 | */ 51 | template 52 | PiPoSequence (PiPo::Parent *parent, Args&... pipos) 53 | : PiPo(parent), seq_{&pipos ...} // use C++11 initilizer_list syntax and variadic templates 54 | { 55 | // set parents of all pipos? 56 | connect(NULL); 57 | } 58 | #endif 59 | 60 | // copy constructor 61 | PiPoSequence (const PiPoSequence &other) 62 | : PiPo(other), seq_(other.seq_) 63 | { 64 | connect(NULL); 65 | } 66 | 67 | // assignment operator 68 | const PiPoSequence& operator=(const PiPoSequence &other) 69 | { 70 | parent = other.parent; 71 | seq_ = other.seq_; 72 | connect(NULL); 73 | 74 | return *this; 75 | } 76 | 77 | ~PiPoSequence (void) { } 78 | 79 | 80 | /** @name PiPoSequence setup methods */ 81 | /** @{ */ 82 | 83 | /** append module \p pipo to sequential data flow graph 84 | */ 85 | void add (PiPo *pipo, bool autoconnect = true) 86 | { 87 | seq_.push_back(pipo); 88 | 89 | if (autoconnect && seq_.size() > 1) 90 | seq_[seq_.size() - 2]->setReceiver(pipo); // connect previous to just added pipo 91 | } 92 | 93 | void add (PiPo &pipo, bool autoconnect = true) 94 | { 95 | add(&pipo, autoconnect); 96 | } 97 | 98 | 99 | void clear () 100 | { 101 | for (unsigned int i = 0; i < seq_.size(); i++) 102 | seq_[i] = NULL; 103 | 104 | seq_.clear(); 105 | } 106 | 107 | 108 | /** connect each PiPo in PiPoSequence (from end to start) 109 | 110 | @param receiver is terminating PiPo of the host that finally receives data 111 | */ 112 | bool connect (PiPo *receiver) 113 | { 114 | PiPo *next = getTail(); 115 | 116 | if (next != NULL) 117 | { 118 | next->setReceiver(receiver); 119 | 120 | for (long i = seq_.size() - 2; i >= 0; i--) 121 | { 122 | PiPo *pipo = seq_[i]; 123 | pipo->setReceiver(next); 124 | next = pipo; 125 | } 126 | 127 | return true; 128 | } 129 | 130 | return false; 131 | } 132 | 133 | /** @} PiPoSequence setup methods */ 134 | 135 | /** @name PiPoChain query methods */ 136 | /** @{ */ 137 | 138 | size_t getSize() const 139 | { 140 | return seq_.size(); 141 | } 142 | 143 | PiPo *getHead () const 144 | { 145 | if (seq_.size() > 0) 146 | return seq_[0]; 147 | 148 | return NULL; 149 | } 150 | 151 | PiPo *getTail () const 152 | { 153 | if (seq_.size() > 0) 154 | return seq_[seq_.size() - 1]; 155 | 156 | return NULL; 157 | } 158 | 159 | PiPo *getPiPo (unsigned int index) const 160 | { 161 | //printf("%s(%d) -> %p\n", __PRETTY_FUNCTION__, index, seq_[index]); 162 | 163 | if (index < seq_.size()) 164 | return seq_[index]; 165 | 166 | return NULL; 167 | } 168 | 169 | /** @} PiPoSequence query methods */ 170 | 171 | /** @name overloaded PiPo methods */ 172 | /** @{ */ 173 | 174 | void setParent (PiPo::Parent *parent) 175 | { 176 | this->parent = parent; 177 | 178 | for (unsigned int i = 0; i < seq_.size(); i++) 179 | seq_[i]->setParent(parent); 180 | } 181 | 182 | void setReceiver (PiPo *receiver, bool add = false) 183 | { 184 | PiPo *tail = getTail(); 185 | 186 | if (tail != NULL) 187 | tail->setReceiver(receiver, add); 188 | } 189 | 190 | /** @name preparation of processing */ 191 | /** @{ */ 192 | 193 | /** start stream preparation */ 194 | int streamAttributes (bool hasTimeTags, double rate, double offset, unsigned int width, unsigned int height, const char **labels, bool hasVarSize, double domain, unsigned int maxFrames) 195 | { 196 | PiPo *head = getHead(); 197 | 198 | if (head != NULL) 199 | return head->streamAttributes(hasTimeTags, rate, offset, width, height, labels, hasVarSize, domain, maxFrames); 200 | 201 | return -1; 202 | } 203 | 204 | int reset () 205 | { 206 | PiPo *head = getHead(); 207 | 208 | if (head != NULL) 209 | return head->reset(); 210 | 211 | return -1; 212 | } 213 | 214 | /** @} end of preparation of processing methods */ 215 | 216 | /** @name processing */ 217 | /** @{ */ 218 | 219 | int frames (double time, double weight, PiPoValue *values, unsigned int size, unsigned int num) 220 | { 221 | PiPo *head = getHead(); 222 | 223 | if (head != NULL) 224 | return head->frames(time, weight, values, size, num); 225 | 226 | return -1; 227 | } 228 | 229 | int finalize (double inputEnd) 230 | { 231 | PiPo *head = getHead(); 232 | 233 | if (head != NULL) 234 | return head->finalize(inputEnd); 235 | 236 | return -1; 237 | } 238 | 239 | /** @} end of processing methods */ 240 | /** @} end of overloaded PiPo methods */ 241 | }; 242 | 243 | /** EMACS ** 244 | * Local variables: 245 | * mode: c++ 246 | * c-basic-offset:2 247 | * End: 248 | */ 249 | 250 | #endif /* _PIPO_SEQUENCE_ */ 251 | -------------------------------------------------------------------------------- /src/RingBuffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | @file RingBuffer.h 4 | @author Norbert.Schnell, Diemo Schwarz 5 | 6 | @brief ringbuffer class 7 | 8 | @copyright 9 | 10 | Copyright (c) 2012–2016 by IRCAM – Centre Pompidou, Paris, France. 11 | All rights reserved. 12 | 13 | @par License (BSD 3-clause) 14 | 15 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 16 | 17 | - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 18 | 19 | - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 20 | 21 | - Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | */ 26 | 27 | #ifndef _RINGBUFFER_ 28 | #define _RINGBUFFER_ 29 | 30 | template 31 | class RingBuffer 32 | { 33 | public: 34 | std::vector vector; 35 | unsigned int width; 36 | unsigned int size; 37 | unsigned int index; 38 | bool filled; 39 | 40 | public: 41 | RingBuffer (void) 42 | : vector() 43 | { 44 | this->width = 1; 45 | this->size = 0; 46 | this->index = 0; 47 | this->filled = false; 48 | }; 49 | 50 | void resize (int width, int size) 51 | { 52 | this->vector.resize(width * size); 53 | this->width = width; 54 | this->size = size; 55 | this->index = 0; 56 | this->filled = false; 57 | }; 58 | 59 | void reset (void) 60 | { 61 | this->index = 0; 62 | this->filled = false; 63 | }; 64 | 65 | int input (T *values, unsigned int num, PiPoValue scale = 1.0) 66 | { 67 | T *ringValues = &this->vector[this->index * this->width]; 68 | 69 | if (num > this->width) 70 | num = this->width; 71 | 72 | /* copy frame */ 73 | if (scale == 1.0) /*TODO: some polymorphism and template magic to avoid this if clause */ 74 | memcpy(ringValues, values, num * sizeof(T)); 75 | else 76 | { 77 | for (unsigned int j = 0; j < num; j++) 78 | ringValues[j] = values[j] * scale; 79 | } 80 | 81 | /* zero pad this values */ 82 | if (num < this->width) 83 | memset(ringValues + num, 0, (this->width - num) * sizeof(T)); 84 | 85 | this->index++; 86 | 87 | if (this->index >= this->size) 88 | { 89 | filled = true; 90 | this->index = 0; 91 | } 92 | 93 | if (this->filled) 94 | return this->size; 95 | else 96 | return this->index; 97 | }; 98 | }; 99 | 100 | /** EMACS ** 101 | * Local variables: 102 | * mode: c++ 103 | * c-basic-offset:2 104 | * End: 105 | */ 106 | 107 | #endif /* _RINGBUFFER_ */ 108 | -------------------------------------------------------------------------------- /src/host/PiPoChain.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file PiPoHost.h 3 | * @author Norbert.Schnell@ircam.fr 4 | * 5 | * @brief Sequence of PiPo modules piping data into each other. 6 | * 7 | * A PiPo host is built around the class PiPoChain that represents a sequence of 8 | * PiPo modules piping data into each other. 9 | * 10 | * A PiPoChain is setup with the following steps: 11 | * 12 | * 1. parse chain definition string by calling parse() 13 | * 2. instantiate each PiPoModule in the chain by calling instantiate(), using a PiPoModuleFactory 14 | * 3. connect PiPos by calling PiPoSequence::connect() 15 | * 16 | * A PiPoChain is itself also a PiPo module, i.e. data processing works the same as for a simple module: 17 | * - the PiPoChain is prepared for processing by calling streamAttributes() on it. 18 | * - data is piped into the PiPoChain with the frames() method. 19 | * 20 | * The host registers as the receiver for the last PiPo module in the PiPoChain. 21 | * 22 | * @copyright 23 | * Copyright (c) 2012–2016 by IRCAM – Centre Pompidou, Paris, France. 24 | * All rights reserved. 25 | * 26 | * License (BSD 3-clause) 27 | * 28 | * Redistribution and use in source and binary forms, with or without 29 | * modification, are permitted provided that the following conditions are met: 30 | * 31 | * 1. Redistributions of source code must retain the above copyright notice, 32 | * this list of conditions and the following disclaimer. 33 | * 2. Redistributions in binary form must reproduce the above copyright 34 | * notice, this list of conditions and the following disclaimer in the 35 | * documentation and/or other materials provided with the distribution. 36 | * 3. Neither the name of the copyright holder nor the names of its 37 | * contributors may be used to endorse or promote products derived from 38 | * this software without specific prior written permission. 39 | * 40 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 41 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 44 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 45 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 46 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 47 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 48 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 50 | * POSSIBILITY OF SUCH DAMAGE. 51 | */ 52 | 53 | #ifndef _PIPO_CHAIN_ 54 | #define _PIPO_CHAIN_ 55 | 56 | #include "PiPoOp.h" 57 | #include "PiPoSequence.h" 58 | 59 | #include 60 | #include 61 | 62 | //TODO: shouldn't PiPoChain just contain a member seq_ for the sequence to build, instead of inheriting? 63 | class PiPoChain : public PiPoSequence 64 | { 65 | std::vector ops; 66 | // these vectors of pointers seem necessary in copyPiPoAttributes 67 | std::vector attrNames; 68 | std::vector attrDescrs; 69 | //PiPo::Parent *parent; //FIXME: remove? pipo has a parent member already! 70 | PiPoModuleFactory *moduleFactory; 71 | 72 | public: 73 | // constructor 74 | PiPoChain(PiPo::Parent *parent, PiPoModuleFactory *moduleFactory = NULL) 75 | : PiPoSequence(parent), ops() 76 | { 77 | this->parent = parent; 78 | this->moduleFactory = moduleFactory; 79 | } 80 | 81 | // copy constructor: invoking assignment operator 82 | PiPoChain(const PiPoChain &other) 83 | : PiPoSequence(NULL), ops() 84 | { 85 | *this = other; 86 | } 87 | 88 | // assignment operator 89 | const PiPoChain& operator=(const PiPoChain &other) 90 | { 91 | this->parent = other.parent; 92 | this->moduleFactory = other.moduleFactory; 93 | 94 | unsigned long numOps = other.ops.size(); 95 | this->ops.clear(); 96 | this->ops.resize(numOps); 97 | 98 | for (unsigned int i = 0; i < numOps; i++) 99 | { 100 | this->ops[i].set(i, this->parent, this->moduleFactory, other.ops[i]); // clone pipos by re-instantiating them 101 | this->add(this->ops[i].getPiPo(), false); // rebuild PiPoSequence to point to cloned pipos 102 | } 103 | 104 | this->connect(NULL); 105 | this->moduleFactory = NULL; 106 | 107 | return *this; 108 | } 109 | 110 | ~PiPoChain(void) 111 | { 112 | for(unsigned int i = 0; i < attrNames.size(); i++) { 113 | delete attrNames[i]; 114 | } 115 | for(unsigned int i = 0; i < attrDescrs.size(); i++) { 116 | delete attrDescrs[i]; 117 | } 118 | this->clear(); 119 | } 120 | 121 | 122 | /** @name PiPoChain setup methods */ 123 | /** @{ */ 124 | 125 | void clear() 126 | { 127 | PiPoSequence::clear(); 128 | for(unsigned int i = 0; i < this->ops.size(); i++) 129 | this->ops[i].clear(); 130 | 131 | this->ops.clear(); 132 | } 133 | 134 | 135 | /** parse pipo chain specification from string 136 | 137 | creates list of PiPoOp in member ops 138 | */ 139 | size_t parse(const char *str) 140 | { 141 | std::string pipoChainStr = str; 142 | size_t pos = 0; 143 | 144 | this->clear(); 145 | 146 | for(unsigned int i = 0; pos < std::string::npos; i++) 147 | { 148 | this->ops.resize(i + 1, i); 149 | this->ops[i].parse(pipoChainStr, pos); 150 | } 151 | 152 | return this->ops.size(); 153 | } 154 | 155 | /** go through list of PiPoOp in ops and instantiate PiPoModule using PiPoModuleFactory 156 | */ 157 | bool instantiate(void) 158 | { 159 | if(this->ops.size() > 0) 160 | { 161 | for(unsigned int i = 0; i < this->ops.size(); i++) 162 | { 163 | if(this->ops[i].instantiate(this->parent, this->moduleFactory)) 164 | { // build sequence by appending modules 165 | this->add(this->ops[i].getPiPo()); 166 | } 167 | else 168 | { 169 | this->clear(); 170 | return false; 171 | } 172 | } 173 | return true; 174 | } 175 | 176 | return false; 177 | } 178 | 179 | void copyPiPoAttributes() 180 | { 181 | for(int iPiPo = 0; iPiPo < this->getSize(); iPiPo++) 182 | { 183 | PiPo *pipo = this->getPiPo(iPiPo); 184 | 185 | const char *instanceName = this->getInstanceName(iPiPo); 186 | unsigned int numAttrs = pipo->getNumAttrs(); 187 | 188 | for(unsigned int iAttr = 0; iAttr < numAttrs; iAttr++) 189 | { 190 | PiPo::Attr *attr = pipo->getAttr(iAttr); 191 | 192 | std::string *attrName = new std::string(instanceName); 193 | *attrName += "."; 194 | *attrName += attr->getName(); 195 | 196 | std::string *attrDescr = new std::string(attr->getDescr()); 197 | *attrDescr += " ("; 198 | *attrDescr += instanceName; 199 | *attrDescr += ")"; 200 | 201 | attrNames.push_back(attrName); 202 | attrDescrs.push_back(attrDescr); 203 | 204 | this->addAttr(this, attrNames[attrNames.size() - 1]->c_str(), attrDescrs[attrDescrs.size() - 1]->c_str(), attr); 205 | } 206 | } 207 | } 208 | 209 | /** @} PiPoChain setup methods */ 210 | 211 | /** @name PiPoChain query methods */ 212 | /** @{ */ 213 | 214 | size_t getSize() 215 | { 216 | return this->ops.size(); 217 | }; 218 | 219 | int getIndex(const char *instanceName) 220 | { 221 | for(unsigned int i = 0; i < this->ops.size(); i++) 222 | { 223 | if(this->ops[i].isInstanceName(instanceName)) 224 | return i; 225 | } 226 | 227 | return -1; 228 | } 229 | 230 | // make getPiPo(unsigned int index) visible for this class PiPoChain : 231 | 232 | using PiPoSequence::getPiPo; 233 | 234 | PiPo *getPiPo(const char *instanceName) 235 | { 236 | int index = getIndex(instanceName); 237 | 238 | if(index >= 0) 239 | return getPiPo(index); 240 | 241 | return NULL; 242 | } 243 | 244 | const char *getInstanceName(unsigned int index) 245 | { 246 | if(index < this->ops.size()) 247 | return this->ops[index].getInstanceName(); 248 | 249 | return NULL; 250 | } 251 | 252 | /** @} PiPoChain query methods */ 253 | 254 | /** @name overloaded PiPo methods */ 255 | /** @{ */ 256 | /** @name all preparation and processing methods are inherited from PiPoSequence: 257 | streamAttributes(), reset(), frames(), finalize() */ 258 | /** @} end of overloaded PiPo methods */ 259 | }; 260 | 261 | /** EMACS ** 262 | * Local variables: 263 | * mode: c 264 | * c-basic-offset:2 265 | * End: 266 | */ 267 | 268 | #endif /* _PIPO_CHAIN_ */ 269 | -------------------------------------------------------------------------------- /src/host/PiPoCollection.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file PiPoCollection.h 3 | * @author Norbert.Schnell@ircam.fr 4 | * @author joseph.larralde@ircam.fr 5 | * 6 | * @brief PiPo Module Collection 7 | * 8 | * @copyright 9 | * Copyright (C) 2013 - 2015 by IMTR IRCAM – Centre Pompidou, Paris, France. 10 | * All rights reserved. 11 | * 12 | * License (BSD 3-clause) 13 | * 14 | * Redistribution and use in source and binary forms, with or without 15 | * modification, are permitted provided that the following conditions are met: 16 | * 17 | * 1. Redistributions of source code must retain the above copyright notice, 18 | * this list of conditions and the following disclaimer. 19 | * 2. Redistributions in binary form must reproduce the above copyright 20 | * notice, this list of conditions and the following disclaimer in the 21 | * documentation and/or other materials provided with the distribution. 22 | * 3. Neither the name of the copyright holder nor the names of its 23 | * contributors may be used to endorse or promote products derived from 24 | * this software without specific prior written permission. 25 | * 26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 30 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | * POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | #ifndef _PIPO_COLLECTION_ 40 | #define _PIPO_COLLECTION_ 41 | 42 | #include 43 | #include "PiPo.h" 44 | 45 | //============================================================================// 46 | //============================== PiPo factory ================================// 47 | //============================================================================// 48 | 49 | //------------------------------ PiPoCreatorBase 50 | class PiPoCreatorBase 51 | { 52 | public: 53 | //PiPoCreatorBase() {} 54 | virtual ~PiPoCreatorBase() {} 55 | virtual PiPo *create() = 0; 56 | }; 57 | 58 | //------------------------------ PiPoCreator 59 | template 60 | class PiPoCreator : public PiPoCreatorBase 61 | { 62 | public: 63 | PiPoCreator() {} 64 | virtual ~PiPoCreator() {} 65 | virtual PiPo *create() 66 | { 67 | return new T(NULL); 68 | } 69 | }; 70 | 71 | //============================================================================// 72 | //============================== PiPo collection =============================// 73 | //============================================================================// 74 | 75 | // interface with the outside world (uses the factory internally) 76 | 77 | /** 78 | * @brief PiPoCollection class : contains all base PiPo classes 79 | * (with ability to hide them from the outside world) 80 | * and methods to register new PiPos and get PiPo chains 81 | * 82 | * \code 83 | * 84 | * #include "PiPoCollection.h" 85 | * 86 | * // example : register a new non native PiPo : 87 | * PiPoCollection::init(); 88 | * PiPoCollection::addToCollection("mypipo", new PiPoCreator); 89 | * PiPo *mychain = PiPoCollection::create("slice:mypipo"); 90 | * 91 | * \endcode 92 | * 93 | */ 94 | 95 | class PiPoCollection 96 | { 97 | public: 98 | static void deinit(); 99 | static void init(bool defaultPipos = true); 100 | static void addToCollection(std::string name, PiPoCreatorBase *creator); 101 | // static void addAlias(std::string alias, std::string name); ----> TODO 102 | static PiPo *create(std::string name, PiPo::Parent *parent = NULL); 103 | private: 104 | }; 105 | 106 | #endif /* _PIPO_COLLECTION_ */ 107 | -------------------------------------------------------------------------------- /src/host/PiPoGraph.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file PiPoGraph.h 3 | * @author Joseph Larralde 4 | * 5 | * @brief PiPo dataflow graph class that parses a graph description string and instantiates 6 | * the corresponding graph of PiPos (made of PiPoSequence and PiPoParallel instances) 7 | * 8 | * PiPoGraph is built around the classes PiPoSequence, PiPoParallel and PiPoOp. 9 | * 10 | * A PiPoGraph is itself also a PiPo module, i.e. data processing works the same 11 | * as for a simple operator : 12 | * - the PiPoGraph is prepared for processing by calling streamAttributes() on it. 13 | * - data is piped into the PiPoGraph with the frames() method. 14 | * 15 | * @ingroup pipoapi 16 | * 17 | * @copyright 18 | * Copyright (C) 2017 by ISMM IRCAM - Centre Pompidou, Paris, France. 19 | * All rights reserved. 20 | * 21 | * License (BSD 3-clause) 22 | * 23 | * Redistribution and use in source and binary forms, with or without 24 | * modification, are permitted provided that the following conditions are met: 25 | * 26 | * 1. Redistributions of source code must retain the above copyright notice, 27 | * this list of conditions and the following disclaimer. 28 | * 2. Redistributions in binary form must reproduce the above copyright 29 | * notice, this list of conditions and the following disclaimer in the 30 | * documentation and/or other materials provided with the distribution. 31 | * 3. Neither the name of the copyright holder nor the names of its 32 | * contributors may be used to endorse or promote products derived from 33 | * this software without specific prior written permission. 34 | * 35 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 36 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 38 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 39 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 40 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 41 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 42 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 43 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 44 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 45 | * POSSIBILITY OF SUCH DAMAGE. 46 | */ 47 | 48 | #ifndef _PIPO_GRAPH_ 49 | #define _PIPO_GRAPH_ 50 | 51 | #include // for right definition of std::remove 52 | #include 53 | #include 54 | #include 55 | 56 | #include "PiPoOp.h" 57 | #include "PiPoSequence.h" 58 | #include "PiPoParallel.h" 59 | 60 | // NB : this is a work in progress 61 | // TODO: define error return codes for parsing 62 | 63 | class PiPoGraph : public PiPo 64 | { 65 | typedef enum PiPoGraphTypeE 66 | { 67 | undefined = -1, leaf = 0, sequence, parallel 68 | } PiPoGraphType; 69 | 70 | private: 71 | bool topLevel; 72 | std::string representation; 73 | PiPoGraphType graphType; 74 | 75 | // parallel graphs if graphType is parallel 76 | // sequence of graphs if graphType is sequence (not sequence of PiPos) 77 | // empty if graphType is leaf 78 | std::vector subGraphs; 79 | 80 | // use op if we are a leaf to parse instanceName and to hold attributes 81 | PiPoOp op; 82 | 83 | PiPo *pipo; 84 | std::vector attrNames; 85 | std::vector attrDescrs; 86 | PiPoModuleFactory *moduleFactory; 87 | 88 | public: 89 | PiPoGraph(PiPo::Parent *parent, PiPoModuleFactory *moduleFactory, bool topLevel = true) : 90 | PiPo(parent) 91 | { 92 | this->pipo = nullptr; 93 | this->parent = parent; 94 | this->moduleFactory = moduleFactory; 95 | this->topLevel = topLevel; 96 | } 97 | 98 | ~PiPoGraph() 99 | { 100 | if (this->topLevel) 101 | { 102 | for (unsigned int i = 0; i < attrNames.size(); ++i) 103 | delete attrNames[i]; 104 | 105 | for (unsigned int i = 0; i < attrDescrs.size(); ++i) 106 | delete attrDescrs[i]; 107 | } 108 | 109 | this->clear(); 110 | } 111 | 112 | void clear() 113 | { 114 | for (unsigned int i = 0; i < this->subGraphs.size(); ++i) 115 | this->subGraphs[i].clear(); 116 | 117 | if (this->graphType != leaf && this->pipo != nullptr) 118 | { 119 | // delete parallels and sequences instantiated with new 120 | delete this->pipo; 121 | this->pipo = nullptr; 122 | } 123 | else 124 | { 125 | // let op clear itself 126 | this->op.clear(); 127 | } 128 | } 129 | 130 | bool create(std::string graphStr) { 131 | if (parse(graphStr) && instantiate() && wire()) { 132 | copyPiPoAttributes(); 133 | return true; 134 | } 135 | 136 | this->clear(); 137 | return false; 138 | } 139 | 140 | private: 141 | //======================== PARSE GRAPH EXPRESSION ==========================// 142 | 143 | bool parse(std::string graphStr) { 144 | 145 | //=================== BASIC SYNTAX RULES CHECKING ========================// 146 | 147 | //========== check if we have the right number of '<' and '>' ============// 148 | 149 | int cnt = 0; 150 | 151 | for (unsigned int i = 0; i < graphStr.length(); ++i) 152 | if (graphStr[i] == '<') 153 | cnt++; 154 | else if (graphStr[i] == '>') 155 | cnt--; 156 | 157 | if (cnt != 0) 158 | return false; 159 | 160 | // TODO : add more syntax checking here ? 161 | 162 | //======= determine the type of graph (leaf, sequence or parallel) =======// 163 | 164 | unsigned int trims = 0; 165 | while (graphStr[0] == '<' && graphStr[graphStr.length() - 1] == '>') 166 | { 167 | graphStr = graphStr.substr(1, graphStr.length() - 2); 168 | trims++; 169 | } 170 | 171 | this->representation = graphStr; 172 | 173 | // by default we are a sequence 174 | this->graphType = sequence; 175 | 176 | // if we have surrounding "<...>" and first-level commas, we are a parallel 177 | if (trims > 0) 178 | { 179 | int subLevelsCnt = 0; 180 | 181 | for (unsigned int i = 0; i < graphStr.length(); ++i) 182 | if (graphStr[i] == '<') 183 | { 184 | subLevelsCnt++; 185 | } 186 | else if (graphStr[i] == '>') 187 | { 188 | subLevelsCnt--; 189 | } 190 | else if (subLevelsCnt == 0 && graphStr[i] == ',') 191 | { 192 | this->graphType = parallel; 193 | break; 194 | } 195 | } 196 | 197 | // if we don't have any sequential / parallelism symbol, 198 | // and we are not a single top-level pipo 199 | // (because we need to be inside a PiPoGraph at the top-level), 200 | // then we are a leaf : 201 | if (graphStr.find("<") >= std::string::npos && 202 | graphStr.find(">") >= std::string::npos && 203 | graphStr.find(",") >= std::string::npos && 204 | graphStr.find(":") >= std::string::npos && 205 | !this->topLevel) 206 | this->graphType = leaf; 207 | 208 | //====== now fill (or not) subGraphs vector according to graph type ======// 209 | 210 | switch (this->graphType) 211 | { 212 | 213 | //========================== leaf graph, we are a single PiPo, trim spaces 214 | case leaf: 215 | { 216 | // trim spaces - TODO: trim tabs and other spaces ? 217 | this->representation.erase( 218 | std::remove(this->representation.begin(), this->representation.end(), ' '), 219 | this->representation.end() 220 | ); 221 | 222 | size_t pos = 0; 223 | this->op.parse(this->representation.c_str(), pos); 224 | 225 | // leaf string representation cannot be empty 226 | return (graphStr.length() > 0); 227 | } 228 | break; 229 | 230 | //================= sequence of graphs, parse according to ':', <' and '>' 231 | case sequence: 232 | { 233 | int subLevelsCnt = 0; 234 | unsigned int lastStartIndex = 0; 235 | std::vector< std::pair > subStrings; 236 | 237 | if (graphStr[0] == '<') 238 | subLevelsCnt++; 239 | 240 | for (unsigned int i = 1; i < graphStr.length(); ++i) 241 | { 242 | if (graphStr[i] == ':' && subLevelsCnt == 0) 243 | { 244 | subStrings.push_back(std::pair( 245 | lastStartIndex, i - lastStartIndex 246 | )); 247 | lastStartIndex = i + 1; 248 | } 249 | else if (graphStr[i] == '<') 250 | { 251 | if (subLevelsCnt == 0) 252 | { 253 | subStrings.push_back(std::pair( 254 | lastStartIndex, i - lastStartIndex 255 | )); 256 | lastStartIndex = i; 257 | } 258 | subLevelsCnt++; 259 | } 260 | else if (graphStr[i] == '>') 261 | { 262 | subLevelsCnt--; 263 | if (subLevelsCnt == 0) 264 | { 265 | subStrings.push_back(std::pair( 266 | lastStartIndex, i - lastStartIndex + 1 267 | )); 268 | lastStartIndex = i + 1; 269 | } 270 | } 271 | else if (graphStr[i] == ',' && subLevelsCnt == 0) 272 | // cannot have first-level commas in a sequence 273 | return false; 274 | } 275 | 276 | if (graphStr[graphStr.length() - 1] != '>') 277 | { 278 | subStrings.push_back(std::pair( 279 | lastStartIndex, (unsigned int) graphStr.length() - lastStartIndex 280 | )); 281 | } 282 | 283 | for (unsigned int i = 0; i < subStrings.size(); ++i) 284 | { 285 | this->subGraphs.push_back(PiPoGraph(this->parent, this->moduleFactory, false)); 286 | PiPoGraph &g = this->subGraphs[this->subGraphs.size() - 1]; 287 | 288 | if (!g.parse(graphStr.substr(subStrings[i].first, subStrings[i].second))) 289 | return false; 290 | } 291 | 292 | return (subLevelsCnt == 0); 293 | } 294 | break; 295 | 296 | //============================= parallel graphs, parse according to commas 297 | case parallel: 298 | { 299 | int subLevelsCnt = 0; 300 | std::vector commaIndices; 301 | 302 | commaIndices.push_back(0); 303 | 304 | for (unsigned int i = 0; i < graphStr.length(); ++i) 305 | if (graphStr[i] == '<') 306 | subLevelsCnt++; 307 | else if (graphStr[i] == '>') 308 | subLevelsCnt--; 309 | else if (graphStr[i] == ',' && i < graphStr.length() - 1 && subLevelsCnt == 0) 310 | commaIndices.push_back(i + 1); 311 | 312 | commaIndices.push_back(static_cast(graphStr.length()) + 1); 313 | 314 | for (unsigned int i = 0; i < commaIndices.size() - 1; ++i) 315 | { 316 | this->subGraphs.push_back(PiPoGraph(this->parent, this->moduleFactory, false)); 317 | PiPoGraph &g = this->subGraphs[this->subGraphs.size() - 1]; 318 | unsigned int blockStart = commaIndices[i]; 319 | unsigned int blockLength = commaIndices[i + 1] - blockStart - 1; 320 | 321 | if (!g.parse(graphStr.substr(blockStart, blockLength))) 322 | return false; 323 | } 324 | 325 | return (subLevelsCnt == 0); 326 | } 327 | break; 328 | 329 | //===================================================== this never happens 330 | default: 331 | break; 332 | } 333 | 334 | return false; 335 | } 336 | 337 | //================ ONCE EXPRESSION PARSED, INSTANTIATE OPs =================// 338 | 339 | bool instantiate() 340 | { 341 | if (this->graphType == leaf) 342 | { 343 | if (!this->op.instantiate(this->parent, this->moduleFactory)) 344 | return false; 345 | else 346 | this->pipo = this->op.getPiPo(); 347 | } 348 | else if (this->graphType == sequence) 349 | { 350 | for (unsigned int i = 0; i < this->subGraphs.size(); ++i) 351 | if (!this->subGraphs[i].instantiate()) 352 | return false; 353 | 354 | this->pipo = new PiPoSequence(this->parent); 355 | } 356 | else if (this->graphType == parallel) 357 | { 358 | for (unsigned int i = 0; i < this->subGraphs.size(); ++i) 359 | if (!this->subGraphs[i].instantiate()) 360 | return false; 361 | 362 | this->pipo = new PiPoParallel(this->parent); 363 | } 364 | 365 | return true; 366 | } 367 | 368 | bool wire() 369 | { 370 | 371 | for (unsigned int i = 0; i < this->subGraphs.size(); ++i) 372 | this->subGraphs[i].wire(); 373 | 374 | if (this->graphType == sequence) 375 | for (unsigned int i = 0; i < this->subGraphs.size(); ++i) 376 | static_cast(this->pipo)->add(this->subGraphs[i].getPiPo()); 377 | 378 | else if (this->graphType == parallel) 379 | for (unsigned int i = 0; i < this->subGraphs.size(); ++i) 380 | static_cast(this->pipo)->add(this->subGraphs[i].getPiPo()); 381 | 382 | return true; 383 | } 384 | 385 | // TODO: add an option to get PiPoAttributes only from named modules ? 386 | void copyPiPoAttributes() 387 | { 388 | for (unsigned int i = 0; i < this->subGraphs.size(); ++i) 389 | { 390 | PiPoGraph &subGraph = this->subGraphs[i]; 391 | 392 | subGraph.copyPiPoAttributes(); 393 | PiPo *pipo = subGraph.getPiPo(); 394 | unsigned int numAttrs = pipo->getNumAttrs(); 395 | 396 | if (subGraph.getGraphType() == leaf) 397 | { 398 | std::string instanceName = subGraph.getInstanceName(); 399 | 400 | for (unsigned int iAttr = 0; iAttr < numAttrs; ++iAttr) 401 | { 402 | PiPo::Attr *attr = pipo->getAttr(iAttr); 403 | 404 | std::string *attrName = new std::string(instanceName); 405 | *attrName += "."; 406 | *attrName += attr->getName(); 407 | 408 | std::string *attrDescr = new std::string(attr->getDescr()); 409 | *attrDescr += " ("; 410 | *attrDescr += instanceName; 411 | *attrDescr += ")"; 412 | 413 | attrNames.push_back(attrName); 414 | attrDescrs.push_back(attrDescr); 415 | 416 | PiPo *p = this->topLevel ? this : this->pipo; 417 | p->addAttr(p, attrNames[attrNames.size() - 1]->c_str(), attrDescrs[attrDescrs.size() - 1]->c_str(), attr); 418 | } 419 | } 420 | 421 | if (subGraph.getGraphType() == sequence || subGraph.getGraphType() == parallel) 422 | { 423 | attrNames.insert(attrNames.end(), subGraph.attrNames.begin(), subGraph.attrNames.end()); 424 | attrDescrs.insert(attrDescrs.end(), subGraph.attrDescrs.begin(), subGraph.attrDescrs.end()); 425 | 426 | for (unsigned int iAttr = 0; iAttr < numAttrs; ++iAttr) 427 | { 428 | PiPo::Attr *attr = pipo->getAttr(iAttr); 429 | PiPo *p = this->topLevel ? this : this->pipo; 430 | p->addAttr(p, subGraph.attrNames[iAttr]->c_str(), subGraph.attrDescrs[iAttr]->c_str(), attr); 431 | } 432 | } 433 | } 434 | } 435 | 436 | std::string getInstanceName() 437 | { 438 | return (this->graphType == leaf) ? std::string(this->op.getInstanceName()) : ""; 439 | } 440 | 441 | PiPoGraphType getGraphType() 442 | { 443 | return this->graphType; 444 | } 445 | 446 | public: 447 | PiPo *getPiPo() 448 | { 449 | return this->pipo; 450 | } 451 | 452 | //=============== OVERRIDING ALL METHODS FROM THE BASE CLASS ===============// 453 | 454 | void setParent(PiPo::Parent *parent) override 455 | { 456 | this->pipo->setParent(parent); 457 | 458 | for (unsigned int i = 0; i < this->subGraphs.size(); ++i) 459 | this->subGraphs[i].setParent(parent); 460 | } 461 | 462 | PiPo *getReceiver(unsigned int index = 0) override 463 | { 464 | return this->pipo->getReceiver(index); 465 | } 466 | 467 | void setReceiver(PiPo *receiver, bool add = false) override 468 | { 469 | this->pipo->setReceiver(receiver); 470 | } 471 | 472 | int reset() override 473 | { 474 | return this->pipo->reset(); 475 | } 476 | 477 | int segment(double time, bool start) override 478 | { 479 | return this->pipo->segment(time, start); 480 | } 481 | 482 | int finalize(double inputEnd) override 483 | { 484 | return this->pipo->finalize(inputEnd); 485 | } 486 | 487 | int streamAttributes(bool hasTimeTags, double rate, double offset, 488 | unsigned int width, unsigned int height, 489 | const char **labels, bool hasVarSize, 490 | double domain, unsigned int maxFrames) override 491 | { 492 | return this->pipo->streamAttributes(hasTimeTags, rate, offset, 493 | width, height, labels, hasVarSize, 494 | domain, maxFrames); 495 | } 496 | 497 | int frames (double time, double weight, PiPoValue *values, 498 | unsigned int size, unsigned int num) override 499 | { 500 | return this->pipo->frames(time, weight, values, size, num); 501 | } 502 | 503 | // void print() { 504 | // std::cout << this->representation << " " << this->graphType << std::endl; 505 | // for (unsigned int i = 0; i < this->subGraphs.size(); ++i) { 506 | // std::cout << " "; 507 | // this->subGraphs[i].print(); 508 | // } 509 | // } 510 | }; 511 | 512 | #endif /* _PIPO_GRAPH_ */ 513 | -------------------------------------------------------------------------------- /src/host/PiPoHost.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file PiPoHost.cpp 3 | * @author Norbert.Schnell@ircam.fr 4 | * 5 | * @brief Plugin Interface for Processing Objects host classes. 6 | * 7 | * A PiPo host is built around the class PiPoChain that represents a sequence of 8 | * PiPo modules piping data into each other. See details of the steps there. 9 | * 10 | * @copyright 11 | * Copyright (c) 2012–2016 by IRCAM – Centre Pompidou, Paris, France. 12 | * All rights reserved. 13 | * 14 | * License (BSD 3-clause) 15 | * 16 | * Redistribution and use in source and binary forms, with or without 17 | * modification, are permitted provided that the following conditions are met: 18 | * 19 | * 1. Redistributions of source code must retain the above copyright notice, 20 | * this list of conditions and the following disclaimer. 21 | * 2. Redistributions in binary form must reproduce the above copyright 22 | * notice, this list of conditions and the following disclaimer in the 23 | * documentation and/or other materials provided with the distribution. 24 | * 3. Neither the name of the copyright holder nor the names of its 25 | * contributors may be used to endorse or promote products derived from 26 | * this software without specific prior written permission. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 32 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 | * POSSIBILITY OF SUCH DAMAGE. 39 | */ 40 | 41 | #define PIPO_OUT_RING_SIZE 2 42 | 43 | #include 44 | 45 | #include "PiPoHost.h" 46 | #include "PiPoCollection.h" 47 | 48 | //================================= PiPoHost =================================// 49 | 50 | // this class is meant to be a base class, child classes should override the 51 | // "onNewFrame" method 52 | 53 | PiPoHost::PiPoHost() : 54 | inputStreamAttrs(PIPO_MAX_LABELS), 55 | outputStreamAttrs(PIPO_MAX_LABELS) 56 | { 57 | PiPoCollection::init(); 58 | this->out = new PiPoOut(this); 59 | this->graph = nullptr; 60 | } 61 | 62 | PiPoHost::~PiPoHost() 63 | { 64 | this->clearGraph(); 65 | delete this->out; 66 | } 67 | 68 | // implementation of PiPo::Parent methods 69 | void 70 | PiPoHost::streamAttributesChanged(PiPo *pipo, PiPo::Attr *attr) 71 | { 72 | this->propagateInputStreamAttributes(); 73 | } 74 | 75 | void 76 | PiPoHost::signalError(PiPo *pipo, std::string errorMsg) 77 | { 78 | std::cout << "Error : " << errorMsg << std::endl; 79 | } 80 | 81 | void 82 | PiPoHost::signalWarning(PiPo *pipo, std::string errorMsg) 83 | { 84 | std::cout << "Warning : " << errorMsg << std::endl; 85 | } 86 | 87 | // own methods 88 | bool 89 | PiPoHost::setGraph(std::string name) 90 | { 91 | if (this->graph != nullptr) 92 | { 93 | delete this->graph; 94 | } 95 | 96 | this->graph = PiPoCollection::create(name, static_cast(this)); 97 | 98 | if (this->graph != nullptr) 99 | { 100 | this->graphName = name; 101 | this->graph->setReceiver((PiPo *)this->out); 102 | return true; 103 | } 104 | 105 | this->graph = nullptr; 106 | this->graphName = "undefined"; 107 | return false; 108 | } 109 | 110 | void 111 | PiPoHost::clearGraph() 112 | { 113 | if (this->graph != nullptr) 114 | { 115 | delete this->graph; 116 | this->graph = nullptr; 117 | } 118 | } 119 | 120 | // override this method when inheriting !!! 121 | // void 122 | // PiPoHost::onNewFrame(std::function f) 123 | // { 124 | // this->frameCallback = f; 125 | // } 126 | 127 | // override this method when inheriting !!! 128 | void 129 | PiPoHost::onNewFrame(double time, double weight, PiPoValue *values, unsigned int size) 130 | { 131 | std::cout << time << std::endl; 132 | std::cout << "please override this method" << std::endl; 133 | } 134 | 135 | std::vector 136 | PiPoHost::getLastFrame() 137 | { 138 | return this->out->getLastFrame(); 139 | } 140 | 141 | int 142 | PiPoHost::setInputStreamAttributes(const PiPoStreamAttributes &sa, bool propagate) 143 | { 144 | this->inputStreamAttrs = sa; 145 | 146 | if (propagate) 147 | { 148 | return this->propagateInputStreamAttributes(); 149 | } 150 | 151 | return 0; 152 | } 153 | 154 | PiPoStreamAttributes& 155 | PiPoHost::getOutputStreamAttributes() 156 | { 157 | return this->outputStreamAttrs; 158 | } 159 | 160 | int 161 | PiPoHost::frames(double time, double weight, PiPoValue *values, unsigned int size, 162 | unsigned int num) 163 | { 164 | return this->graph->frames(time, weight, values, size, num); 165 | } 166 | 167 | std::vector 168 | PiPoHost::getAttrNames() 169 | { 170 | std::vector res; 171 | 172 | for (unsigned int i = 0; i < this->graph->getNumAttrs(); ++i) 173 | { 174 | res.push_back(this->graph->getAttr(i)->getName()); 175 | } 176 | 177 | return res; 178 | } 179 | 180 | bool 181 | PiPoHost::setAttr(const std::string &attrName, bool value) 182 | { 183 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 184 | 185 | if (attr != NULL) 186 | { 187 | int iAttr = attr->getIndex(); 188 | return this->graph->setAttr(iAttr, value ? 1 : 0); 189 | } 190 | 191 | return false; 192 | } 193 | 194 | bool 195 | PiPoHost::setAttr(const std::string &attrName, const std::string &value) // for enums 196 | { 197 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 198 | 199 | if (attr != NULL) 200 | { 201 | PiPo::Type type = attr->getType(); 202 | 203 | if (type == PiPo::Type::Enum) 204 | { 205 | std::vector *list = attr->getEnumList(); 206 | 207 | for (int i = 0; i < list->size(); i++) 208 | { 209 | if (strcmp(list->at(i), value.c_str()) == 0) 210 | { 211 | attr->set(0, i); 212 | return true; 213 | } 214 | } 215 | } 216 | else if (type == PiPo::Type::String) 217 | { 218 | attr->set(0, value.c_str()); 219 | } 220 | } 221 | 222 | return false; 223 | } 224 | 225 | bool 226 | PiPoHost::setAttr(const std::string &attrName, int value) 227 | { 228 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 229 | 230 | if (attr != NULL) 231 | { 232 | int iAttr = attr->getIndex(); 233 | return this->graph->setAttr(iAttr, value); 234 | } 235 | 236 | return false; 237 | } 238 | 239 | bool 240 | PiPoHost::setAttr(const std::string &attrName, double value) 241 | { 242 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 243 | 244 | if (attr != NULL) 245 | { 246 | int iAttr = attr->getIndex(); 247 | return this->graph->setAttr(iAttr, value); 248 | } 249 | 250 | return false; 251 | } 252 | 253 | bool 254 | PiPoHost::setAttr(const std::string &attrName, const std::vector &values) 255 | { 256 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 257 | 258 | if (attr != NULL) 259 | { 260 | PiPo::Type type = attr->getType(); 261 | 262 | int iAttr = attr->getIndex(); 263 | int vals[values.size()]; 264 | 265 | for (unsigned int i = 0; i < values.size(); ++i) 266 | { 267 | vals[i] = values[i]; 268 | } 269 | 270 | return this->graph->setAttr(iAttr, &vals[0], static_cast(values.size())); 271 | } 272 | 273 | return false; 274 | } 275 | 276 | bool 277 | PiPoHost::setAttr(const std::string &attrName, const std::vector &values) 278 | { 279 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 280 | 281 | if (attr != NULL) 282 | { 283 | PiPo::Type type = attr->getType(); 284 | 285 | int iAttr = attr->getIndex(); 286 | double vals[values.size()]; 287 | 288 | for (unsigned int i = 0; i < values.size(); ++i) 289 | { 290 | vals[i] = values[i]; 291 | } 292 | 293 | return this->graph->setAttr(iAttr, &vals[0], static_cast(values.size())); 294 | } 295 | 296 | return false; 297 | } 298 | 299 | //--------------------------- TYPE INTROSPECTION -----------------------------// 300 | 301 | bool 302 | PiPoHost::isBoolAttr(const std::string &attrName) 303 | { 304 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 305 | 306 | if (attr != NULL) 307 | { 308 | return (attr->getType() == PiPo::Type::Bool); 309 | } 310 | 311 | return false; 312 | } 313 | 314 | bool 315 | PiPoHost::isEnumAttr(const std::string &attrName) 316 | { 317 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 318 | 319 | if (attr != NULL) 320 | { 321 | return (attr->getType() == PiPo::Type::Enum); 322 | } 323 | 324 | return false; 325 | } 326 | 327 | std::vector 328 | PiPoHost::getAttrEnumList(const std::string &attrName) 329 | { 330 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 331 | 332 | if (attr != NULL) 333 | { 334 | PiPo::Type type = attr->getType(); 335 | 336 | if (type == PiPo::Type::Enum) 337 | { 338 | std::vector *list = attr->getEnumList(); 339 | std::vector res(list->size()); 340 | 341 | for (int i = 0; i < list->size(); i++) 342 | { 343 | res[i] = std::string(list->at(i)); 344 | } 345 | 346 | return res; 347 | } 348 | } 349 | 350 | #if (__STDC_VERSION__ >= 201103L) /* C++11 */ 351 | return { "" }; 352 | #else /* fallback for C++98 */ 353 | std::vector empty; 354 | empty.push_back(""); 355 | return empty; 356 | #endif 357 | } 358 | 359 | bool 360 | PiPoHost::isStringAttr(const std::string &attrName) 361 | { 362 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 363 | 364 | if (attr != NULL) 365 | { 366 | return (attr->getType() == PiPo::Type::String); 367 | } 368 | 369 | return false; 370 | } 371 | 372 | bool 373 | PiPoHost::isIntAttr(const std::string &attrName) 374 | { 375 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 376 | 377 | if (attr != NULL) 378 | { 379 | return (attr->getType() == PiPo::Type::Int); 380 | } 381 | 382 | return false; 383 | } 384 | 385 | bool 386 | PiPoHost::isDoubleAttr(const std::string &attrName) 387 | { 388 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 389 | 390 | if (attr != NULL) 391 | { 392 | return (attr->getType() == PiPo::Type::Double); 393 | } 394 | 395 | return false; 396 | } 397 | 398 | //------------------------------ VALUE GETTERS -------------------------------// 399 | 400 | bool 401 | PiPoHost::getBoolAttr(const std::string &attrName) 402 | { 403 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 404 | 405 | if (attr != NULL) 406 | { 407 | PiPo::Type type = attr->getType(); 408 | 409 | if (type == PiPo::Type::Bool) 410 | { 411 | return attr->getInt(0) != 0; 412 | } 413 | } 414 | 415 | return false; 416 | } 417 | 418 | std::string 419 | PiPoHost::getEnumAttr(const std::string &attrName) 420 | { 421 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 422 | 423 | if (attr != NULL) 424 | { 425 | PiPo::Type type = attr->getType(); 426 | 427 | if (type == PiPo::Type::Enum) 428 | { 429 | return std::string(attr->getStr(0)); 430 | } 431 | } 432 | 433 | return ""; 434 | } 435 | 436 | std::string 437 | PiPoHost::getStringAttr(const std::string &attrName) 438 | { 439 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 440 | 441 | if (attr != NULL) 442 | { 443 | PiPo::Type type = attr->getType(); 444 | 445 | if (type == PiPo::Type::String) 446 | { 447 | return std::string(attr->getStr(0)); 448 | } 449 | } 450 | 451 | return ""; 452 | } 453 | 454 | int 455 | PiPoHost::getIntAttr(const std::string &attrName) 456 | { 457 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 458 | 459 | if (attr != NULL) 460 | { 461 | PiPo::Type type = attr->getType(); 462 | 463 | if (type == PiPo::Type::Int) 464 | { 465 | return attr->getInt(0); 466 | } 467 | } 468 | 469 | return 0; 470 | } 471 | 472 | double 473 | PiPoHost::getDoubleAttr(const std::string &attrName) 474 | { 475 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 476 | 477 | if (attr != NULL) 478 | { 479 | PiPo::Type type = attr->getType(); 480 | 481 | if (type == PiPo::Type::Double) 482 | { 483 | return attr->getDbl(0); 484 | } 485 | } 486 | 487 | return 0; 488 | } 489 | 490 | std::vector 491 | PiPoHost::getIntArrayAttr(const std::string &attrName) 492 | { 493 | std::vector res; 494 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 495 | 496 | if (attr != NULL) { 497 | PiPo::Type type = attr->getType(); 498 | 499 | if (type == PiPo::Type::Int) 500 | { 501 | res.resize(attr->getSize()); 502 | for (int i = 0; i < attr->getSize(); ++i) 503 | { 504 | res[i] = attr->getInt(i); 505 | } 506 | } 507 | } 508 | 509 | return res; 510 | } 511 | 512 | std::vector 513 | PiPoHost::getDoubleArrayAttr(const std::string &attrName) 514 | { 515 | std::vector res; 516 | PiPo::Attr *attr = this->graph->getAttr(attrName.c_str()); 517 | 518 | if (attr != NULL) { 519 | PiPo::Type type = attr->getType(); 520 | 521 | if (type == PiPo::Type::Double) 522 | { 523 | res.resize(attr->getSize()); 524 | for (int i = 0; i < attr->getSize(); ++i) 525 | { 526 | res[i] = attr->getDbl(i); 527 | } 528 | } 529 | } 530 | 531 | return res; 532 | } 533 | 534 | 535 | int 536 | PiPoHost::propagateInputStreamAttributes() 537 | { 538 | if (this->graph != nullptr) 539 | { 540 | return this->graph->streamAttributes(this->inputStreamAttrs.hasTimeTags, 541 | this->inputStreamAttrs.rate, 542 | this->inputStreamAttrs.offset, 543 | this->inputStreamAttrs.dims[0], 544 | this->inputStreamAttrs.dims[1], 545 | this->inputStreamAttrs.labels, 546 | this->inputStreamAttrs.hasVarSize, 547 | this->inputStreamAttrs.domain, 548 | this->inputStreamAttrs.maxFrames); 549 | } 550 | 551 | return 0; 552 | } 553 | 554 | void 555 | PiPoHost::setOutputStreamAttributes(bool hasTimeTags, double rate, double offset, 556 | unsigned int width, unsigned int height, 557 | const char **labels, bool hasVarSize, 558 | double domain, unsigned int maxFrames) 559 | { 560 | if (labels != NULL) 561 | { 562 | int numLabels = width; 563 | 564 | if (numLabels > PIPO_MAX_LABELS) 565 | { 566 | numLabels = PIPO_MAX_LABELS; 567 | } 568 | 569 | for (unsigned int i = 0; i < this->outputStreamAttrs.numLabels; ++i) 570 | { 571 | // free previously allocated memory 572 | delete[] this->outputStreamAttrs.labels[i]; 573 | } 574 | 575 | for (unsigned int i = 0; i < numLabels; i++) 576 | { 577 | this->outputStreamAttrs.labels[i] = new char[PIPO_MAX_LABELS]; 578 | const char * label = labels[i] != NULL ? labels[i] : ""; 579 | std::strcpy(const_cast(this->outputStreamAttrs.labels[i]), label); 580 | } 581 | 582 | this->outputStreamAttrs.numLabels = numLabels; 583 | } 584 | else 585 | { 586 | this->outputStreamAttrs.numLabels = 0; 587 | } 588 | 589 | this->outputStreamAttrs.hasTimeTags = hasTimeTags; 590 | this->outputStreamAttrs.rate = rate; 591 | this->outputStreamAttrs.offset = offset; 592 | this->outputStreamAttrs.dims[0] = width; 593 | this->outputStreamAttrs.dims[1] = height; 594 | this->outputStreamAttrs.hasVarSize = hasVarSize; 595 | this->outputStreamAttrs.domain = domain; 596 | this->outputStreamAttrs.maxFrames = maxFrames; 597 | } 598 | 599 | //================================= PiPoOut ==================================// 600 | 601 | PiPoOut::PiPoOut(PiPoHost *host) : 602 | PiPoOut::PiPo((PiPo::Parent *)host) 603 | { 604 | this->host = host; 605 | writeIndex = 0; 606 | readIndex = 0; 607 | ringBuffer.resize(PIPO_OUT_RING_SIZE); 608 | } 609 | 610 | PiPoOut::~PiPoOut() {} 611 | 612 | int 613 | PiPoOut::streamAttributes(bool hasTimeTags, 614 | double rate, double offset, 615 | unsigned int width, unsigned int height, 616 | const char **labels, bool hasVarSize, 617 | double domain, unsigned int maxFrames) 618 | { 619 | this->host->setOutputStreamAttributes(hasTimeTags, rate, offset, width, height, 620 | labels, hasVarSize, domain, maxFrames); 621 | 622 | for (int i = 0; i < PIPO_OUT_RING_SIZE; ++i) 623 | { 624 | ringBuffer[i].resize(width * height); 625 | } 626 | 627 | return 0; 628 | } 629 | 630 | int 631 | PiPoOut::frames(double time, double weight, PiPoValue *values, 632 | unsigned int size, unsigned int num) 633 | { 634 | if (num > 0) 635 | { 636 | for (int i = 0; i < num; ++i) 637 | { 638 | this->host->onNewFrame(time, weight, values, size); 639 | // this->host->frameCallback(time, weight, values, size); 640 | 641 | /* 642 | ////////// TODO : write a real lock-free queue using atomic_swap 643 | ////////// for pipo graphs fed by audio frames 644 | 645 | for (int j = 0; j < size; ++j) 646 | { 647 | ringBuffer[writeIndex][j] = values[i * size + j]; 648 | } 649 | 650 | // atomic swap ? 651 | writeIndex = 1 - writeIndex; 652 | readIndex = 1 - writeIndex; 653 | this->host->onNewFrame(time, ringBuffer[readIndex]); 654 | 655 | if (writeIndex + 1 == PIPO_OUT_RING_SIZE) 656 | { 657 | writeIndex = 0; 658 | } 659 | else 660 | { 661 | writeIndex++; 662 | } 663 | //*/ 664 | } 665 | } 666 | 667 | return 0; 668 | } 669 | 670 | std::vector 671 | PiPoOut::getLastFrame() 672 | { 673 | std::vector f; 674 | 675 | if (readIndex > -1) 676 | { 677 | f = ringBuffer[readIndex]; 678 | } 679 | 680 | return f; 681 | } 682 | -------------------------------------------------------------------------------- /src/host/PiPoHost.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file PiPoHost.h 3 | * @author Norbert.Schnell@ircam.fr 4 | * 5 | * @brief Plugin Interface for Processing Objects host classes. 6 | * 7 | * A PiPo host is built around the class PiPoChain that represents a sequence of 8 | * PiPo modules piping data into each other. See details of the steps there. 9 | * 10 | * @copyright 11 | * Copyright (c) 2012–2016 by IRCAM – Centre Pompidou, Paris, France. 12 | * All rights reserved. 13 | * 14 | * License (BSD 3-clause) 15 | * 16 | * Redistribution and use in source and binary forms, with or without 17 | * modification, are permitted provided that the following conditions are met: 18 | * 19 | * 1. Redistributions of source code must retain the above copyright notice, 20 | * this list of conditions and the following disclaimer. 21 | * 2. Redistributions in binary form must reproduce the above copyright 22 | * notice, this list of conditions and the following disclaimer in the 23 | * documentation and/or other materials provided with the distribution. 24 | * 3. Neither the name of the copyright holder nor the names of its 25 | * contributors may be used to endorse or promote products derived from 26 | * this software without specific prior written permission. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 32 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 | * POSSIBILITY OF SUCH DAMAGE. 39 | */ 40 | 41 | #ifndef _PIPO_HOST_ 42 | #define _PIPO_HOST_ 43 | 44 | #define PIPO_OUT_RING_SIZE 2 45 | 46 | #include 47 | 48 | #include "PiPo.h" 49 | 50 | class PiPoOut; 51 | 52 | //================================= PiPoHost =================================// 53 | 54 | // this class is meant to be a base class, child classes should override the 55 | // "onNewFrame" method 56 | 57 | class PiPoHost : public PiPo::Parent { 58 | friend class PiPoOut; 59 | 60 | protected: 61 | std::string graphName; 62 | PiPo *graph; 63 | PiPoOut *out; 64 | 65 | PiPoStreamAttributes inputStreamAttrs; 66 | PiPoStreamAttributes outputStreamAttrs; 67 | 68 | // std::function frameCallback; 69 | 70 | public: 71 | PiPoHost(); 72 | ~PiPoHost(); 73 | 74 | virtual bool setGraph(std::string name); 75 | virtual void clearGraph(); 76 | 77 | // methods from PiPo::Parent 78 | virtual void streamAttributesChanged(PiPo *pipo, PiPo::Attr *attr); 79 | virtual void signalError(PiPo *pipo, std::string errorMsg); 80 | virtual void signalWarning(PiPo *pipo, std::string errorMsg); 81 | 82 | // override this method when inheriting !!! 83 | // virtual void onNewFrame(std::function f); 84 | virtual void onNewFrame(double time, double weight, PiPoValue *values, unsigned int size); 85 | 86 | virtual std::vector getLastFrame(); 87 | 88 | virtual int setInputStreamAttributes(const PiPoStreamAttributes &sa, bool propagate = true); 89 | 90 | virtual PiPoStreamAttributes &getOutputStreamAttributes(); 91 | 92 | virtual int frames(double time, double weight, PiPoValue *values, unsigned int size, 93 | unsigned int num); 94 | 95 | virtual std::vector getAttrNames(); 96 | 97 | virtual bool setAttr(const std::string &attrName, bool value); 98 | virtual bool setAttr(const std::string &attrName, const std::string &value); // for enums and strings 99 | virtual bool setAttr(const std::string &attrName, int value); 100 | virtual bool setAttr(const std::string &attrName, double value); 101 | virtual bool setAttr(const std::string &attrName, const std::vector &values); 102 | virtual bool setAttr(const std::string &attrName, const std::vector &values); 103 | 104 | virtual bool isBoolAttr(const std::string &attrName); 105 | virtual bool isEnumAttr(const std::string &attrName); 106 | virtual std::vector getAttrEnumList(const std::string &attrName); 107 | virtual bool isStringAttr(const std::string &attrName); 108 | virtual bool isIntAttr(const std::string &attrName); // works for single ints and int arrays 109 | virtual bool isDoubleAttr(const std::string &attrName); // works for single doubles and double arrays 110 | 111 | virtual bool getBoolAttr(const std::string &attrName); 112 | virtual std::string getEnumAttr(const std::string &attrName); 113 | virtual std::string getStringAttr(const std::string &attrName); 114 | virtual int getIntAttr(const std::string &attrName); // will get only the 1st element if attr is array 115 | virtual double getDoubleAttr(const std::string &attrName); // will get only the 1st element if attr is array 116 | virtual std::vector getIntArrayAttr(const std::string &attrName); 117 | virtual std::vector getDoubleArrayAttr(const std::string &attrName); 118 | 119 | private: 120 | int propagateInputStreamAttributes(); 121 | 122 | void setOutputStreamAttributes(bool hasTimeTags, double rate, double offset, 123 | unsigned int width, unsigned int height, 124 | const char **labels, bool hasVarSize, 125 | double domain, unsigned int maxFrames); 126 | }; 127 | 128 | //============================================================================// 129 | 130 | class PiPoOut : public PiPo { 131 | private: 132 | PiPoHost *host; 133 | // fix all dependencies to compile with the c++11 flag before (Pm2, ircam_descriptor, ...) 134 | // std::atomic writeIndex, readIndex; 135 | int writeIndex, readIndex; 136 | std::vector > ringBuffer; 137 | 138 | public: 139 | PiPoOut(PiPoHost *host); 140 | ~PiPoOut(); 141 | 142 | int streamAttributes(bool hasTimeTags, 143 | double rate, double offset, 144 | unsigned int width, unsigned int height, 145 | const char **labels, bool hasVarSize, 146 | double domain, unsigned int maxFrames); 147 | 148 | int frames(double time, double weight, PiPoValue *values, 149 | unsigned int size, unsigned int num); 150 | 151 | std::vector getLastFrame(); 152 | }; 153 | 154 | #endif /* _PIPO_HOST_*/ 155 | -------------------------------------------------------------------------------- /src/host/PiPoModule.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file PiPoModule.h 3 | * @author Norbert.Schnell@ircam.fr 4 | * 5 | * @brief Definition of base PiPoModule and PiPoModuleFactory classes. 6 | * 7 | * @copyright 8 | * Copyright (c) 2012–2016 by IRCAM – Centre Pompidou, Paris, France. 9 | * All rights reserved. 10 | * 11 | * License (BSD 3-clause) 12 | * 13 | * Redistribution and use in source and binary forms, with or without 14 | * modification, are permitted provided that the following conditions are met: 15 | * 16 | * 1. Redistributions of source code must retain the above copyright notice, 17 | * this list of conditions and the following disclaimer. 18 | * 2. Redistributions in binary form must reproduce the above copyright 19 | * notice, this list of conditions and the following disclaimer in the 20 | * documentation and/or other materials provided with the distribution. 21 | * 3. Neither the name of the copyright holder nor the names of its 22 | * contributors may be used to endorse or promote products derived from 23 | * this software without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 29 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 | * POSSIBILITY OF SUCH DAMAGE. 36 | */ 37 | 38 | #ifndef _PIPO_MODULE_ 39 | #define _PIPO_MODULE_ 40 | 41 | #include "PiPo.h" 42 | 43 | /** 44 | * abstract base class for a container of a pipo module for PiPoModuleFactory 45 | */ 46 | class PiPoModule 47 | { 48 | public: 49 | PiPoModule(void) { }; 50 | ~PiPoModule(void) { }; 51 | }; 52 | 53 | class PiPoModuleFactory 54 | { 55 | public: 56 | PiPoModuleFactory(void) { }; 57 | ~PiPoModuleFactory(void) { }; 58 | 59 | virtual PiPo *create(unsigned int index, const std::string &pipoName, const std::string &instanceName, PiPoModule *&module) = 0; 60 | }; 61 | 62 | #endif /* _PIPO_MODULE */ 63 | -------------------------------------------------------------------------------- /src/host/PiPoModuleClass.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @file PiPoModuleClass.h 4 | * 5 | * @brief extension of PiPo for use in host apps 6 | * 7 | * Copyright (C) 2012-2016 by IRCAM – Centre Pompidou, Paris, France. 8 | * All rights reserved. 9 | * 10 | */ 11 | 12 | #ifndef _PIPO_MODULE_CLASS_ 13 | #define _PIPO_MODULE_CLASS_ 14 | 15 | #include "PiPo.h" 16 | #include "PiPoCollection.h" 17 | 18 | // this allows to load and use modules compiled as dynammic libraries : 19 | 20 | #define PIPO_MODULE_CLASS(pipoName, pipoClass) \ 21 | extern "C" const char *getPiPoName(void); \ 22 | extern "C" PiPoCreatorBase *getPiPoCreator(); \ 23 | const char *getPiPoName() { return pipoName; }\ 24 | PiPoCreatorBase *getPiPoCreator() { return new PiPoCreator; } 25 | 26 | #endif /* _PIPO_MODULE_CLASS_ */ 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/host/PiPoOp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file PiPoOp.h 3 | * @author Norbert.Schnell@ircam.fr 4 | * 5 | * @brief Wrapper class providing a level of abstraction for the instanciation 6 | * of PiPo operators. 7 | * 8 | * @copyright 9 | * Copyright (c) 2012–2016 by IRCAM – Centre Pompidou, Paris, France. 10 | * All rights reserved. 11 | * 12 | * License (BSD 3-clause) 13 | * 14 | * Redistribution and use in source and binary forms, with or without 15 | * modification, are permitted provided that the following conditions are met: 16 | * 17 | * 1. Redistributions of source code must retain the above copyright notice, 18 | * this list of conditions and the following disclaimer. 19 | * 2. Redistributions in binary form must reproduce the above copyright 20 | * notice, this list of conditions and the following disclaimer in the 21 | * documentation and/or other materials provided with the distribution. 22 | * 3. Neither the name of the copyright holder nor the names of its 23 | * contributors may be used to endorse or promote products derived from 24 | * this software without specific prior written permission. 25 | * 26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 30 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 | * POSSIBILITY OF SUCH DAMAGE. 37 | */ 38 | 39 | #ifndef _PIPO_OP_ 40 | #define _PIPO_OP_ 41 | 42 | #include "PiPo.h" 43 | #include "PiPoModule.h" 44 | 45 | #include 46 | #include 47 | 48 | const float PIPO_MIN_SDK_VERSION_REQUIRED = 0.2; 49 | 50 | /** 51 | * element of pipo chain, points to pipo pipo 52 | */ 53 | class PiPoOp 54 | { 55 | unsigned int index; 56 | std::string pipoName; /// pipo class name 57 | std::string instanceName; 58 | PiPo *pipo; 59 | PiPoModule *module; 60 | 61 | public: 62 | PiPoOp(unsigned int index = 0) : pipoName(), instanceName() 63 | { 64 | this->index = index; 65 | this->pipo = NULL; 66 | this->module = NULL; 67 | } 68 | 69 | // PiPoOp(const PiPoOp &other) : pipoName(), instanceName() 70 | // { 71 | // this->index = other.index; 72 | // this->pipoName = other.pipoName; 73 | // this->instanceName = other.instanceName; 74 | // this->pipo = other.pipo; 75 | // this->module = other.module; 76 | // }; 77 | 78 | ~PiPoOp(void) { }; 79 | 80 | void setParent(PiPo::Parent *parent) 81 | { 82 | if(this->pipo != NULL) 83 | this->pipo->setParent(parent); 84 | } 85 | 86 | void clear(void) 87 | { 88 | if(this->module != NULL) 89 | delete this->module; 90 | 91 | this->module = NULL; 92 | 93 | if(this->pipo != NULL) 94 | delete pipo; 95 | 96 | this->pipo = NULL; 97 | } 98 | 99 | /** 100 | * parse one pipo name, and optional instance name in '(' ')' 101 | */ 102 | void parse(std::string str, size_t &pos) 103 | { 104 | this->clear(); 105 | 106 | size_t end = str.find_first_of(':', pos); 107 | size_t open = str.find_first_of('(', pos); 108 | size_t closed = str.find_first_of(')', pos); 109 | 110 | if(open < std::string::npos && closed < std::string::npos) 111 | { 112 | this->pipoName = str.substr(pos, open - pos); 113 | this->instanceName = str.substr(open + 1, closed - open - 1); 114 | } 115 | else 116 | { 117 | this->pipoName = str.substr(pos, end - pos); 118 | this->instanceName = this->pipoName; 119 | } 120 | 121 | if(end < std::string::npos) 122 | pos = end + 1; 123 | else 124 | pos = std::string::npos; 125 | } 126 | 127 | bool instantiate(PiPo::Parent *parent, PiPoModuleFactory *moduleFactory) 128 | { 129 | this->pipo = NULL; 130 | this->module = NULL; 131 | 132 | if(moduleFactory != NULL) 133 | this->pipo = moduleFactory->create(index, this->pipoName, this->instanceName, this->module); 134 | 135 | if(this->pipo != NULL) 136 | { // check if version of created pipo is compatible with host 137 | if (this->pipo->getVersion() < PIPO_MIN_SDK_VERSION_REQUIRED) 138 | { 139 | printf("PiPo Host ERROR: created PiPo %s version %f is smaller than minimum required version %f\n", 140 | this->pipoName.c_str(), this->pipo->getVersion(), PIPO_MIN_SDK_VERSION_REQUIRED); 141 | //TODO: clean up: destroy unusable pipo 142 | return false; 143 | } 144 | 145 | this->pipo->setParent(parent); 146 | return true; 147 | } 148 | 149 | return false; 150 | } 151 | 152 | void set(unsigned int index, PiPo::Parent *parent, PiPoModuleFactory *moduleFactory, const PiPoOp &other) 153 | { 154 | this->index = index; 155 | this->pipoName = other.pipoName; 156 | this->instanceName = other.instanceName; 157 | 158 | this->instantiate(parent, moduleFactory); 159 | 160 | if(this->pipo != NULL) 161 | this->pipo->cloneAttrs(other.pipo); 162 | } 163 | 164 | PiPo *getPiPo() { return this->pipo; }; 165 | const char *getInstanceName() { return this->instanceName.c_str(); }; 166 | bool isInstanceName(const char *str) { return (this->instanceName.compare(str) == 0); }; 167 | }; 168 | 169 | /** EMACS ** 170 | * Local variables: 171 | * mode: c++ 172 | * c-basic-offset:2 173 | * End: 174 | */ 175 | 176 | #endif /* _PIPO_OP_ */ 177 | -------------------------------------------------------------------------------- /src/host/mimo_host.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file mimo_host.h 3 | * @author Diemo.Schwarz@ircam.fr 4 | * 5 | * @brief Modular Interface for Multi-modal Objects. Extends PiPo possibilities. 6 | * 7 | * Every mimo module inherits the basic stream description and data 8 | * passing methods (streamAttributes() and frames()) from PiPo, but 9 | * ignores real-time oriented methods (segment()), and adds iteration 10 | * for training. 11 | * 12 | * @copyright 13 | * Copyright (c) 2016-2017 by IRCAM – Centre Pompidou, Paris, France. 14 | * All rights reserved. 15 | * 16 | * License (BSD 3-clause) 17 | * 18 | * Redistribution and use in source and binary forms, with or without 19 | * modification, are permitted provided that the following conditions are met: 20 | * 21 | * 1. Redistributions of source code must retain the above copyright notice, 22 | * this list of conditions and the following disclaimer. 23 | * 2. Redistributions in binary form must reproduce the above copyright 24 | * notice, this list of conditions and the following disclaimer in the 25 | * documentation and/or other materials provided with the distribution. 26 | * 3. Neither the name of the copyright holder nor the names of its 27 | * contributors may be used to endorse or promote products derived from 28 | * this software without specific prior written permission. 29 | * 30 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 31 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 34 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 37 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 38 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40 | * POSSIBILITY OF SUCH DAMAGE. 41 | */ 42 | 43 | #include "PiPoChain.h" 44 | 45 | class mimo_host : public PiPoChain 46 | { 47 | /* for mimo, the streamAttributes() method should give the size of the input data as maxframes */ 48 | 49 | /* push data through mimo modules 50 | */ 51 | int run_training (PiPoValue *indata, int numframes) 52 | { 53 | int itercount = 0; 54 | size = width_ * height_; 55 | 56 | // first iteration on imput data, modules output passed to our mimo_receiver 57 | int status = iterate(0, indata, numframes); 58 | 59 | while ((this->maxiter() == 0 || itercount < this->maxiter()) && status == 0) 60 | { 61 | itercount++; 62 | status = iterate(itercount, indata, numframes); 63 | } 64 | } 65 | 66 | int iterate (int itercount, PiPoValue *data, numframes) 67 | { 68 | int status = 0; 69 | 70 | for (int buf = 0; buf < numbuffers; buf++) 71 | for (int track = 0; track < numtracks; track++) 72 | if ((status = getHead()->train(itercount, buf, track, numframes, data, timetags, varsize)) != 0) 73 | return status; 74 | 75 | return status; 76 | } 77 | } 78 | 79 | 80 | /* 81 | reveives data iterated upon by training mimo modules 82 | */ 83 | class mimo_receiver : mimo 84 | { 85 | PiPoValue *outputdata_; 86 | 87 | int frames (PiPoValue *values) 88 | { 89 | outputdata_ = values; 90 | } 91 | 92 | // store or merge input data transformed by one iteration of training 93 | int train () 94 | { 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/mimo.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _MIMO_H_INCLUDED_ 3 | #define _MIMO_H_INCLUDED_ 4 | 5 | #include "PiPo.h" 6 | #include 7 | 8 | 9 | 10 | /** interface for a class that holds the mimo module-specific model parameters resulting from training 11 | */ 12 | class mimo_model_data 13 | { 14 | public: 15 | /** query size of json encoding of model (including terminating 0). 16 | will be followed by a call to to_json() */ 17 | virtual int json_size () = 0; 18 | 19 | /** output as json string into out 20 | Is preceeded by a call to json_size(). 21 | Throws an exception if string would exceed size. 22 | 23 | @param out string buffer of length \p{size} 24 | @param size size of string buffer 25 | @return returns the out pointer for convenience 26 | 27 | N.B.: the mimo module might be loaded from a dynamic library, so 28 | we can't return a complex object such as std::string that 29 | internatlly uses heap allocations, since the dylib's heap is a 30 | separate one from the main app. We can't even work on a 31 | std::stringstream passed by reference, since probably the 32 | reallocations also use the heap. */ 33 | virtual char *to_json (char *out, int size) throw() = 0; 34 | 35 | /** get model from json string */ 36 | virtual int from_json (const char *json_string) = 0; 37 | 38 | // virtual const int foo() = 0; 39 | }; 40 | 41 | 42 | /** structure holding a buffer full of data 43 | */ 44 | struct mimo_buffer 45 | { 46 | int numframes; //< number of elements in data, varsize, timetags 47 | PiPoValue *data; //< pointer to numframes matrices of height * width 48 | const int *varsize; //< pointer to numframes row counts if track is varsize 49 | bool has_timetags; //< if true, use timetags, otherwise track is sampled and starttime is given 50 | union 51 | { 52 | const double *timetags; //< pointer to numframes time tags 53 | double starttime; //< start time for sampled data 54 | } time; 55 | 56 | 57 | mimo_buffer () 58 | { 59 | numframes = 0; 60 | data = NULL; 61 | varsize = NULL; 62 | has_timetags = false; 63 | time.timetags = NULL; 64 | time.starttime = 0; 65 | } 66 | 67 | mimo_buffer (int _numframes, PiPoValue *_data, const int *_varsize, bool _has_timetags, const double *_timetags, double _starttime) 68 | { 69 | numframes = _numframes; 70 | data = _data; 71 | varsize = _varsize; 72 | has_timetags = _has_timetags; 73 | if (has_timetags) 74 | time.timetags = _timetags; 75 | else 76 | time.starttime = _starttime; 77 | } 78 | }; 79 | 80 | 81 | 82 | /** base class for a Mimo module (modular interface for modeling objects) 83 | 84 | every mimo module inherits the basic stream description and data 85 | passing methods (streamAttributes() and frames()) from PiPo, but 86 | ignores real-time oriented methods (segment()), and adds iteration 87 | for training. 88 | */ 89 | 90 | class Mimo : public PiPo 91 | { 92 | public: 93 | // constructor 94 | Mimo (PiPo::Parent *parent, Mimo *receiver = NULL) 95 | : PiPo(parent, receiver) 96 | { } 97 | 98 | Mimo (const Mimo &other) 99 | : PiPo(other) 100 | { } 101 | 102 | /** the PiPo::frames() method performs decoding */ 103 | //virtual int frames (...); 104 | 105 | /** prepare for training 106 | 107 | @param numbuffers number of buffers with training data 108 | @param numtracks number of tracks per input buffer with training data 109 | @param bufsizes array[numbuffers * numtracks] of numbers of frames for each input buffer and track 110 | @param streamattr array[numtracks] attributes of input data for each input track 111 | @return 0 for ok or a negative error code (to be specified), -1 for an unspecified error 112 | */ 113 | virtual int setup (int numbuffers, int numtracks, const int bufsizes[], const PiPoStreamAttributes *streamattr[]) = 0; 114 | 115 | /** the train method performs one iteration of training. 116 | 117 | It is called for each input track with a list of buffer data, receiving the training data sets. 118 | The first iteration receives the original data, further iterations the training output data of previous iterations, 119 | that each iteration can output by calling propagateTrain(). 120 | For multi-modal training (with more than one input track), only the call for the last track may call propagateTrain(). 121 | 122 | @param itercount number of current iteration (starts at zero) 123 | @param trackindex index of current input track (up to numtracks - 1) 124 | @param numbuffers number of buffers 125 | @param buffers array[numbuffers] of buffer data 126 | @return status flag: continue training (> 0), stop training (== 0), error (< 0) 127 | */ 128 | virtual int train (int itercount, int trackindex, int numbuffers, const mimo_buffer buffers[]) = 0; 129 | 130 | 131 | /** return recommended max number of iterations, or 0 for no limit. 132 | This can be overridden by the user via an attribute 133 | N.B.: The host should ask for maxiter at every iteration, so that a training algorithm can adapt its recommendation to the training progress */ 134 | virtual int maxiter() { return 0; /* default: unlimited */ } 135 | 136 | /** after train, host checks if model converged and iterations should stop 137 | @param metric return error, distance or loss metric from training. 138 | */ 139 | virtual bool converged (double *metric) { return true; /* default: one shot */ }; 140 | 141 | /** return trained model parameters */ 142 | virtual mimo_model_data *getmodel () = 0; 143 | 144 | int propagateSetup (int numbuffers, int numtracks, const int bufsize[], const PiPoStreamAttributes *streamattr[]) 145 | { 146 | int ret = 0; 147 | 148 | for (unsigned int i = 0; i < this->receivers.size(); i++) 149 | { 150 | ret = dynamic_cast(this->receivers[i])->setup(numbuffers, 1, bufsize, &streamattr[0]); 151 | 152 | if (ret < 0) 153 | break; 154 | } 155 | 156 | return ret; 157 | } 158 | 159 | int propagateTrain (int itercount, int trackindex, int numbuffers, const mimo_buffer buffers[]) 160 | { 161 | int ret = 0; 162 | 163 | for (unsigned int i = 0; i < this->receivers.size(); i++) 164 | { 165 | ret = dynamic_cast(this->receivers[i])->train(itercount, trackindex, numbuffers, buffers); 166 | 167 | if (ret < 0) 168 | break; 169 | } 170 | 171 | return ret; 172 | } 173 | }; // end class Mimo 174 | 175 | 176 | /** special attribute class for decoder pipo of a mimo module: gets model from json string (or max dictionary handled by the host) 177 | 178 | class MimoModelAttr : public PiPoScalarAttr 179 | { 180 | }; 181 | */ 182 | 183 | /** EMACS ** 184 | * Local variables: 185 | * mode: c++ 186 | * c-basic-offset:2 187 | * End: 188 | */ 189 | 190 | #endif // defined _MIMO_H_INCLUDED_ 191 | --------------------------------------------------------------------------------