flext 0.6.2
|
Currently there exist two widely used modular systems for real-time audio that can be extended by self-written objects (so called "externals"):
Max (http://www.cycling74.com) and Pure Data (http://www.pure-data.org) .
Both come with APIs that are not very different (as they share their origin), but as well not quite the same. Flext seeks to provide a unifying interface for the APIs of those real-time systems while also concentrating on making use of the advantages of the object orientation of the C++ language.
Consequently, flext allows to write externals (or libraries of a number of these), that can be compiled for both systems (with various compilers on a few platforms) without changes to the source code. Flext also tries to overcome some limitations of the real-time systems and introduces new features.
The advantages of flext are:
Naturally there are some cons, too:
Currently, flext supports
Flext is covered by the GPL.
flext - C++ layer for Max/MSP and pd (pure data) externals
Copyright (C) 2001-2005 Thomas Grill
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
In the official flext distribution, the GNU General Public License is in the file gpl.txt<BR> Also see the file license.txt for notes on referenced works and their license texts.
Download the latest flext version from http://grrrr.org/ext/flext .
Alternatively, you can check out the cvs version from http://sourceforge.net/projects/pure-data .
As a developer, you should know the C++ language, how to use a makefile (especially necessary for linux) and how to steer your compiler.
Flext can be compiled as a static library which has then to be linked to the code of your external. For most applications you won't have to use any of the native PD or Max/MSP API functions as they are all encapsulated by flext.
So let's come to the point... how does a typical flext object look like?
This is the object "attr1", one of the flext tutorial examples:
// enable attribute processing #define FLEXT_ATTRIBUTES 1 // include flext header #include <flext.h> // check for appropriate flext version #if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 400) #error You need at least flext version 0.4.0 #endif
With these lines, all the necessary definitions from the flext package have been included.
class attr1: public flext_base { FLEXT_HEADER(attr1,flext_base)
A flext class is simply defined by inheriting from the flext_base (see also FLEXT_CLASS) or flext_dsp (see also Flext dsp class) classes. Additionally some information has to be added using FLEXT_HEADER (see Flext class header)
public: // constructor attr1();
Normally the constructor takes the creation arguments of an object. Here there are none.
protected: void m_trigger(float f); // stored argument float arg;
These are methods and data elements for internal class usage. Flext doesn't know about them as long as they are not registered.
private: // callback for method "m_trigger" (with one float argument) FLEXT_CALLBACK_F(m_trigger); // define attribute callbacks for variable "arg" (with GET and SET properties) FLEXT_ATTRVAR_F(arg); };
For each method that shall be exposed to the realtime-system (for receiving messages) and every attribute (for setting and getting values) callbacks have to be set up. The functions in the groups Declare callbacks for class methods and FLEXT_D_ATTRIB allow for their convenient definition.
// instantiate the class FLEXT_NEW("attr1",attr1)
With FLEXT_NEW the class is registered for the real-time system. The number of creation arguments and their types must be taken into account here. There are several variants depending on whether a message oriented (see Stand-alone class instantiation) or a DSP object (see Dsp class instantiation) is created and whether it resides in a object library (see Library class instantiation and Dsp library class instantiation).
attr1::attr1(): arg(0) // initialize argument { // define inlets AddInAnything(); // first inlet of type anything (index 0) // define outlets AddOutFloat(); // one float outlet (has index 0)
Every inlet and outlet that the object shall have has to be registered. This is done with the functions in Announce in-/outlet functions.
// register methods FLEXT_ADDMETHOD(0,m_trigger); // register method (for floats) "m_trigger" for inlet 0 FLEXT_ADDATTR_VAR1("arg",arg); // register attribute "arg" with variable arg }
Likewise, every method (called by a message) (see Add flext methods) and every attribute (see Announce object attributes) exposed to the system has to be registered. Here the registration at instance creation is shown - there's another way by registering at class setup level, which is more efficient but can only be used if the methods or attributes used are known beforehand (see Add flext methods within class scope and Announce object attributes at class scope).
void attr1::m_trigger(float f) { float res = arg+f; // output value to outlet ToOutFloat(0,res); // (0 stands for the outlet index 0) }
This is a method that is triggered with a message. It does some calculation and then outputs a value to an outlet. There are numerous functions (see Output data to inlets/outlets) supporting that functionality.
Be sure to work through the examples provided with the flext tutorial. These should give you an overview about the possibilities of flext. The "modules" link at the top of the page leads to a complete reference of flext functions and classes.