flext

C++ layer for & Max/MSP externals

Thomas Grill Vienna, Austria

http://www.parasitaere-kapazitaeten.net Pure Data & Max/MSP • Modular real-time frameworks for audio (and video) • Pure Data for , IRIX, Mac OSX and Windows • Max/MSP for Mac OS9/X and Windows

• Asynchronous (messages) and synchronous (DSP) processing • Functionality made up of loadable modules (“externals”)

• Both systems originally developed by have a lot in common

2 flext • with ++-interface to the PD or Max API • External objects represented as classes • Wrappers for various other functions

• Covers nearly all features of the respective real-time framework • Cross-platform (PD & Max, OS independence) • All major compilers supported

3 Simple message object – PD

#include typedef struct { t_object x_obj; t_float x_f1,x_f2; } t_plus; static t_class *plus_class; static void *plus_new(t_floatarg f) { t_plus *x = (t_plus *)pd_new(plus_class); outlet_new(&x->x_obj, &s_float); floatinlet_new(&x->x_obj, &x->x_f2); x->x_f1 = 0; x->x_f2 = f; return (x); } static void plus_bang(t_plus *x) { outlet_float(x->x_obj.ob_outlet, x->x_f1 + x->x_f2); } static void plus_float(t_plus *x, t_float f) { outlet_float(x->x_obj.ob_outlet, (x->x_f1 = f) + x->x_f2); } void plus_setup(void) { plus_class = class_new(gensym("plus"), (t_newmethod)plus_new, 0, sizeof(t_plus), 0, A_DEFFLOAT, 0); class_addbang(plus_class, plus_bang); class_addfloat(plus_class, (t_method)plus_float); } 4 Simple message object – flext

#include class plus: public flext_base { FLEXT_HEADER(plus,flext_base) float f1,f2; plus(float f): f1(0),f2(f) // constructor { AddInAnything("Bang or Number"); AddInFloat("Argument"); AddOutFloat("Result"); FLEXT_ADDBANG(0,m_bang); // add methods FLEXT_ADDMETHOD(0,m_float); FLEXT_ADDMETHOD(1,m_arg); } inline void m_bang() { ToOutFloat(0,f1+f2); } inline void m_float(float f) { ToOutFloat(0,(f1 = f)+f2); } inline void m_arg(float f) { f2 = f; } FLEXT_CALLBACK(m_bang) // callback wrappers FLEXT_CALLBACK_F(m_float) FLEXT_CALLBACK_F(m_arg) }; FLEXT_NEW_1("plus",plus,float0) // set up class

5 Pros and Cons • Easy to read, easy to write • Hardly any system-dependent code necessary • Use advantages of C++ (esp. polymorphism) • Convenience functions • Extensions (attributes, multi-threading etc.)

• Processing overhead • Memory consumption • File size of statically linked binaries • Building problems

6 Building parts • Detection of platform and compiler • Two base classes o flext_base for pure message objects o flext_dsp for DSP objects • Static flext class for general system functionality o Buffer class (access to sampled audio) o Atom list classes o Threading classes o Timer class and functions o Some SIMD functions o Messaging functions

7 Attributes • Consistent way to initialize, set and query state • Originally conceived by J.K.Clayton for Max/Jitter class plus: public flext_base { FLEXT_HEADER(plus,flext_base) float f1,f2; plus(float f): f1(0),f2(f) { AddInAnything("Bang or Number"); AddInFloat("Argument"); AddOutFloat("Result"); FLEXT_ADDBANG(0,m_bang); FLEXT_ADDMETHOD(0,m_float); FLEXT_ADDMETHOD(1,m_arg);

FLEXT_ADDATTR_VAR1("arg",f2); // add attribute } FLEXT_ATTRVAR_F(f2) // wrapper for attribute variable // … more methods and wrappers };

FLEXT_NEW_1("plus",plus,float0) // set up class 8 DSP objects • Virtual methods for DSP processing

class gain: public flext_dsp { FLEXT_HEADER(gain,flext_dsp) float factor; gain(): factor(0) { AddInSignal("In"); // add signal inlet AddInFloat("Gain"); AddOutSignal("Out"); // add signal outlet FLEXT_ADDMETHOD(1,m_gain); } virtual void m_signal(int n,t_sample *const *insigs,t_sample *const *outsigs) { const t_sample *in = insigs[0]; t_sample *out = outsigs[0]; while(n--) *(out++) = *(in++)*factor; // or: MulSamples(out,in,factor,n); } void m_gain(float db) { factor = pow(10.f,db*0.05f); } FLEXT_CALLBACK_F(m_gain); }; FLEXT_NEW_DSP("gain~",gain) // set up DSP class

9 Threading • Transparent threading in real-time environment • Threads are running at lower priority • Several threading models supported (pthreads as default) class writer: public flext_base { FLEXT_HEADER(writer,flext_base) writer() { AddInAnything("Bang to start"); AddOutBang("Bang on finish"); FLEXT_ADDMETHOD_I(0,"start",m_start); // register method } void m_start(int loops) { // slowly write some megabytes to disk std::ofstream file("/temp/bigfile.txt"); for(int i = 0; i < loops; ++i) file << i << ' '; file << std::endl; ToOutBang(0); // indicate end of work } FLEXT_THREAD_I(m_start) // special wrapper }; FLEXT_NEW("writer",writer) 10 Timers • Timer class using class methods or callback functions • Additional high-precision clock functions

class bangs: public flext_base { FLEXT_HEADER(bangs,flext_base)

Timer timer;

bangs() { AddInAnything("In"); AddOutBang("Out"); FLEXT_ADDMETHOD(0,m_interval); FLEXT_ADDTIMER(timer,m_bang); }

inline void m_interval(float intv) { timer.Periodic(intv*0.001); } inline void m_bang(void *) { ToOutBang(0); }

FLEXT_CALLBACK_F(m_interval); FLEXT_CALLBACK_T(m_bang); // timer callback };

FLEXT_NEW("bangs",bangs) // set up class

11 More features • Binding to symbols (named senders & receivers) • Libraries of externals • Interface classes to SndObj and STK frameworks

Future • flext as a shared library • System-wide inspectors for flext-based objects • Better integration into Pure Data? • Better support for Max messaging/timing • Integrated make system for flext externals

12 Download • Release versions from the flext website • Fresh stuff from Sourceforge CVS Prerequisites • Real-time system SDK • Compiler (free: gcc, cygwin, MinGW) Support • PD and Max mailing lists • flext online documentation and tutorials • Open source externals

13 Applications • fluid~ – soundfont external by Frank Barknecht • tbext – object collection by Tim Blechmann • readanysf~ – sample/stream-player by August Black

• xsample – a collection of sample objects • vasp modular – vector assembling signal processor • py/pyext – Python-based external objects • pool – a hierarchical database object • dyn~ – dynamic object management • fftease – library of spectral processors

14