Commit b2dcb71f authored by thomas's avatar thomas
Browse files

bugfixes and optimizations, especially for DSP under Max/MSP

git-svn-id: https://svn.grrrr.org/ext/trunk@1124 4d9ac71a-51e6-0310-8455-cad1006bcd31
parent 1c8f08ca
......@@ -17,6 +17,7 @@ Version history:
- added header file flfeatures.h for compile-time detection of version-specific features
- typed flext::NewAligned allocator
- fixed severe Altivec bug (load unaligned)... thanks to Ian Ollmann
- restructured initialization and finalization (esp. Max DSP stuff)
0.5.0:
- fixes for 64 bit builds (size_t is integer type of pointer size)
......
......@@ -52,6 +52,10 @@ bool flext_obj::init_ok;
void flext_obj::ProcessAttributes(bool attr) { process_attributes = attr; }
#if FLEXT_SYS == FLEXT_SYS_MAX
static const t_symbol *sym__shP = NULL;
#endif
/////////////////////////////////////////////////////////
// Constructor
//
......@@ -64,7 +68,7 @@ flext_obj :: FLEXT_CLASSDEF(flext_obj)()
#if FLEXT_SYS == FLEXT_SYS_PD
m_canvas = canvas_getcurrent();
#elif FLEXT_SYS == FLEXT_SYS_MAX
m_canvas = (t_patcher *)gensym("#P")->s_thing;
m_canvas = (t_patcher *)sym__shP->s_thing;
x_obj->curinlet = 0;
#endif
}
......@@ -78,6 +82,13 @@ flext_obj :: ~FLEXT_CLASSDEF(flext_obj)()
x_obj = NULL;
}
void flext_obj::__setup__(t_classid)
{
#if FLEXT_SYS == FLEXT_SYS_MAX
sym__shP = MakeSymbol("#P");
#endif
flext::Setup();
}
bool flext_obj::Init() { return true; }
bool flext_obj::Finalize() { return true; }
......
......@@ -210,7 +210,7 @@ class FLEXT_SHARE FLEXT_CLASSDEF(flext_obj):
public:
//! Creation callback
static void __setup__(t_classid) { flext::Setup(); }
static void __setup__(t_classid);
/*! \brief This is a temporary holder
\warning don't touch it!
......
......@@ -518,12 +518,15 @@ public: // needed by VC++ 6
protected:
FLEXT_CLASSDEF(flext_base)();
virtual ~FLEXT_CLASSDEF(flext_base)();
/*! \brief Set up inlets and outlets, method and attribute lists
*/
virtual bool Init();
/*! \brief Deallocate all kinds of stuff
*/
virtual void Exit();
/*! \defgroup FLEXT_C_ATTR Attribute handling methods (object scope)
@{
......
......@@ -18,10 +18,6 @@ WARRANTIES, see the file, "license.txt," in this distribution.
// === flext_dsp ==============================================
#if FLEXT_SYS == FLEXT_SYS_JMAX
const t_symbol *flext_dsp::dspsym = MakeSymbol("__flext_dspfun__");
#endif
void flext_dsp::Setup(t_classid id)
{
t_class *c = getClass(id);
......@@ -33,52 +29,45 @@ void flext_dsp::Setup(t_classid id)
CLASS_MAINSIGNALIN(c,flext_hdr,defsig); // float messages going into the left inlet are converted to signal
add_dsp(c,cb_dsp);
add_method1(c,cb_enable,"enable",A_FLOAT);
#elif FLEXT_SYS == FLEXT_SYS_JMAX
fts_dsp_declare_function(dspsym,dspmeth);
fts_class_message_varargs(c, fts_s_put, cb_dsp);
fts_class_message_varargs(c, MakeSymbol("enable"), cb_enable);
#else
#error Platform not supported!
#endif
}
flext_dsp::FLEXT_CLASSDEF(flext_dsp)():
#if FLEXT_SYS == FLEXT_SYS_JMAX
srate(fts_dsp_get_sample_rate()), // should we set it?
blksz(fts_dsp_get_tick_size()),
#else
srate(sys_getsr()),blksz(sys_getblksize()),
#endif
chnsin(0),chnsout(0),
flext_dsp::FLEXT_CLASSDEF(flext_dsp)()
: srate(sys_getsr()),blksz(sys_getblksize())
, vecs(NULL)
#if FLEXT_SYS != FLEXT_SYS_MAX
dspon(true),
, dspon(true)
#endif
invecs(NULL),outvecs(NULL)
{}
#if FLEXT_SYS == FLEXT_SYS_MAX
bool flext_dsp::Init()
{
#if FLEXT_SYS == FLEXT_SYS_JMAX
fts_dsp_object_init(thisHdr());
#endif
}
if(!flext_base::Init())
return false;
// according to the Max/MSP SDK this should be prior to any inlet creation, BUT
// that doesn't seem to be true... multiple signal ins and additional inlets don't seem to work then
dsp_setup(thisHdr(),CntInSig()); // signal inlets
return true;
}
#endif
flext_dsp::~FLEXT_CLASSDEF(flext_dsp)()
void flext_dsp::Exit()
{
#if FLEXT_SYS == FLEXT_SYS_JMAX
fts_dsp_object_delete(thisHdr());
#endif
#if FLEXT_SYS == FLEXT_SYS_MAX
// switch off dsp as the dsp function might get called afterwards (different thread)
thisHdr()->z_disabled = true;
// according to David Z. one should do that first...
dsp_free(thisHdr());
#endif
if(invecs) delete[] invecs;
if(outvecs) delete[] outvecs;
flext_base::Exit();
if(vecs) delete[] vecs;
}
#if FLEXT_SYS == FLEXT_SYS_JMAX
void flext_dsp::dspmeth(fts_word_t *w)
{
}
#else
t_int *flext_dsp::dspmeth(t_int *w)
{
flext_dsp *obj = (flext_dsp *)(size_t)w[1];
......@@ -95,11 +84,8 @@ t_int *flext_dsp::dspmeth(t_int *w)
}
return w+2;
}
#endif
#if FLEXT_SYS == FLEXT_SYS_JMAX
void flext_dsp::cb_dsp(fts_object_t *c, int winlet, fts_symbol_t s, int ac, const fts_atom_t *at)
#elif FLEXT_SYS == FLEXT_SYS_MAX
#if FLEXT_SYS == FLEXT_SYS_MAX
void flext_dsp::cb_dsp(t_class *c,t_signal **sp,short *count)
#else
void flext_dsp::cb_dsp(t_class *c,t_signal **sp)
......@@ -113,94 +99,52 @@ void flext_dsp::cb_dsp(t_class *c,t_signal **sp)
#if FLEXT_SYS == FLEXT_SYS_PD
// min. 1 input channel! (CLASS_MAININLET in pd...)
if(!in) in = 1;
#else
if(in+out == 0) return;
#endif
// store current dsp parameters
#if FLEXT_SYS == FLEXT_SYS_JMAX
fts_dsp_descr_t *dsp = (fts_dsp_descr_t *)fts_get_pointer(at+0);
obj->srate = fts_dsp_get_input_srate(dsp,0);
obj->blksz = fts_dsp_get_input_size(dsp,0); // is this guaranteed to be the same as sys_getblksize() ?
#else
obj->srate = sp[0]->s_sr;
obj->blksz = sp[0]->s_n; // is this guaranteed to be the same as sys_getblksize() ?
#endif
// store in and out signal vectors
if(in != obj->chnsin) {
if(obj->invecs) delete[] obj->invecs;
obj->invecs = in?new t_signalvec[in]:NULL;
obj->chnsin = in;
}
for(i = 0; i < in; ++i)
obj->invecs[i] =
#if FLEXT_SYS == FLEXT_SYS_JMAX
fts_dsp_get_input_name(dsp,i);
#else
sp[i]->s_vec;
#endif
if((in+out) && !obj->vecs)
obj->vecs = new t_signalvec[in+out];
if(out != obj->chnsout) {
if(obj->outvecs) delete[] obj->outvecs;
obj->outvecs = out?new t_signalvec[out]:NULL;
obj->chnsout = out;
}
for(i = 0; i < in; ++i)
obj->vecs[i] = sp[i]->s_vec;
for(i = 0; i < out; ++i)
obj->outvecs[i] =
#if FLEXT_SYS == FLEXT_SYS_JMAX
fts_dsp_get_output_name(dsp,i);
#else
sp[in+i]->s_vec;
#endif
obj->vecs[in+i] = sp[in+i]->s_vec;
// with the following call derived classes can do their eventual DSP setup
if(obj->CbDsp()) {
// set the DSP function
#if FLEXT_SYS == FLEXT_SYS_JMAX
fts_atom_t args;
fts_set_pointer(args,obj);
fts_dsp_add_function(dspsym,1,args);
#else
dsp_add((t_dspmethod)dspmeth,1,obj);
#endif
}
}
/*
#if FLEXT_SYS == FLEXT_SYS_JMAX
void flext_dsp::cb_dsp_init(fts_object_t *c, int winlet, fts_symbol_t *s, int ac, const fts_atom_t *at)
{
fts_dsp_add_object(c);
}
void flext_dsp::cb_dsp_delete(fts_object_t *c, int winlet, fts_symbol_t *s, int ac, const fts_atom_t *at)
{
fts_dsp_remove_object(c);
}
#endif
*/
void flext_dsp::m_dsp(int /*n*/,t_signalvec const * /*insigs*/,t_signalvec const * /*outsigs*/) {}
bool flext_dsp::CbDsp()
{
m_dsp(Blocksize(),invecs,outvecs);
// invoke legacy method
m_dsp(Blocksize(),InSig(),OutSig());
return true;
}
// this function will be overridden anyway - the probably useless default is clearing all outputs
void flext_dsp::m_signal(int n,t_sample *const * /*insigs*/,t_sample *const *outs)
{
for(int i = 0; i < CntOutSig(); ++i) ZeroSamples(outs[i],n);
}
void flext_dsp::CbSignal() { m_signal(Blocksize(),invecs,outvecs); }
void flext_dsp::CbSignal()
{
// invoke legacy method
m_signal(Blocksize(),InSig(),OutSig());
}
#if FLEXT_SYS == FLEXT_SYS_PD
void flext_dsp::cb_enable(t_class *c,t_float on) { thisObject(c)->dspon = on != 0; }
#elif FLEXT_SYS == FLEXT_SYS_JMAX
void flext_dsp::cb_enable(fts_object_t *c, int winlet, fts_symbol_t s, int ac, const fts_atom_t *at)
{ thisObject(c)->dspon = fts_get_int(at+0) != 0; }
#endif
......@@ -52,23 +52,19 @@ public:
int Blocksize() const { return blksz; }
//! returns array of input vectors (CntInSig() vectors)
t_sample *const *InSig() const { return invecs; }
t_sample *const *InSig() const { return vecs; }
//! returns input vector
t_sample *InSig(int i) const { return invecs[i]; }
t_sample *InSig(int i) const { return vecs[i]; }
//! returns array of output vectors (CntOutSig() vectors)
t_sample *const *OutSig() const { return outvecs; }
t_sample *const *OutSig() const { return vecs+CntInSig(); }
//! returns output vector
t_sample *OutSig(int i) const { return outvecs[i]; }
t_sample *OutSig(int i) const { return vecs[CntInSig()+i]; }
//! typedef describing a signal vector
#if FLEXT_SYS == FLEXT_SYS_JMAX
typedef fts_symbol_t t_signalvec;
#else
typedef t_sample *t_signalvec;
#endif
//! @}
......@@ -145,48 +141,34 @@ public:
protected:
FLEXT_CLASSDEF(flext_dsp)();
virtual ~FLEXT_CLASSDEF(flext_dsp)();
#if FLEXT_SYS == FLEXT_SYS_MAX
virtual bool Init();
#endif
virtual void Exit();
private:
// not static, could be different in different patchers..
float srate;
int blksz;
int chnsin,chnsout;
t_signalvec *vecs;
// setup function
static void Setup(t_classid c);
// callback functions
#if FLEXT_SYS == FLEXT_SYS_JMAX
static void cb_dsp(fts_object_t *o, int winlet, fts_symbol_t s, int ac, const fts_atom_t *at);
// static void cb_dsp_init(fts_object_t *o, int winlet, fts_symbol_t *s, int ac, const fts_atom_t *at);
// static void cb_dsp_delete(fts_object_t *o, int winlet, fts_symbol_t *s, int ac, const fts_atom_t *at);
#elif FLEXT_SYS == FLEXT_SYS_MAX
#if FLEXT_SYS == FLEXT_SYS_MAX
static void cb_dsp(t_class *c,t_signal **s,short *count);
#else
static void cb_dsp(t_class *c,t_signal **s);
#endif
#if FLEXT_SYS != FLEXT_SYS_MAX
#if FLEXT_SYS == FLEXT_SYS_JMAX
static void cb_enable(fts_object_t *o, int winlet, fts_symbol_t s, int ac, const fts_atom_t *at);
#else
static void cb_enable(t_class *c,t_float on);
#endif
bool dspon;
#endif
// dsp stuff
#if FLEXT_SYS == FLEXT_SYS_JMAX
static void dspmeth(fts_word_t *);
static const t_symbol *dspsym;
#else
static t_int *dspmeth(t_int *w);
#endif
t_signalvec *invecs,*outvecs;
};
#endif
......@@ -48,19 +48,42 @@ flext_base::FLEXT_CLASSDEF(flext_base)()
}
}
flext_base::~FLEXT_CLASSDEF(flext_base)()
/*! This virtual function is called after the object has been created, that is,
after the constructor has been processed.
It creates the inlets and outlets and the message and attribute lists.
\note You can override it in your own class, but be sure to call it,
\note otherwise no inlets/outlets will be created
\note All inlet, outlets, method and attribute declarations must be made before a call to Init!
\remark Creation of inlets/outlets can't be done upon declaration, as Max/MSP needs creation
\remark in reverse.
*/
bool flext_base::Init()
{
bool ok = flext_obj::Init();
if(ok) ok = InitInlets() && InitOutlets();
if(ok) {
if(HasAttributes() && m_holdaargc && m_holdaargv) {
// initialize creation attributes
ok = InitAttrib(m_holdaargc,m_holdaargv);
}
}
return ok;
}
/*! This virtual function is called before the destructor.
We do this because here we can still call virtual methods.
*/
void flext_base::Exit()
{
#if FLEXT_SYS == FLEXT_SYS_PD && !defined(FLEXT_NOATTREDIT)
// attribute editor window may still be open -> close it
gfxstub_deleteforkey(thisHdr());
#endif
#if FLEXT_SYS == FLEXT_SYS_MAX
// according to David Z. one should do that first...
if(insigs) dsp_free(thisHdr());
// if(insigs) dsp_freebox(thisHdr());
#endif
#ifdef FLEXT_THREADS
StopThreads();
#endif
......@@ -101,33 +124,11 @@ flext_base::~FLEXT_CLASSDEF(flext_base)()
delete[] outdesc;
}
#endif
}
/*! This virtual function is called after the object has been created, that is,
after the constructor has been processed.
It creates the inlets and outlets and the message and attribute lists.
\note You can override it in your own class, but be sure to call it,
\note otherwise no inlets/outlets will be created
\note All inlet, outlets, method and attribute declarations must be made before a call to Init!
\remark Creation of inlets/outlets can't be done upon declaration, as Max/MSP needs creation
\remark in reverse.
*/
bool flext_base::Init()
{
bool ok = flext_obj::Init();
if(ok) ok = InitInlets() && InitOutlets();
if(ok) {
if(HasAttributes() && m_holdaargc && m_holdaargv) {
// initialize creation attributes
ok = InitAttrib(m_holdaargc,m_holdaargv);
}
}
return ok;
flext_obj::Exit();
}
/*! Set up proxy classes and basic methods at class creation time
This ensures that they are processed before the registered flext messages
*/
......
......@@ -191,24 +191,25 @@ bool flext_base::InitInlets()
error("%s: All signal inlets must be left-aligned",thisName());
ok = false;
break;
case xlet_float:
inlets[ix] = NULL;
if(ix >= 10) {
post("%s: Only 9 float inlets possible",thisName());
ok = false;
}
else
floatin(x_obj,ix);
break;
case xlet_int:
inlets[ix] = NULL;
if(ix >= 10) {
post("%s: Only 9 int inlets possible",thisName());
ok = false;
}
else
intin(x_obj,ix);
break;
case xlet_float: {
if(ix < 10) {
inlets[ix] = NULL;
floatin(x_obj,ix);
break;
}
else
goto makeproxy;
}
case xlet_int: {
if(ix < 10) {
inlets[ix] = NULL;
intin(x_obj,ix);
break;
}
else
goto makeproxy;
}
makeproxy:
case xlet_any: // non-leftmost
case xlet_sym:
case xlet_list:
......@@ -221,12 +222,9 @@ bool flext_base::InitInlets()
}
}
}
// incnt = cnt;
if(insigs)
dsp_setup(thisHdr(),insigs); // signal inlets
}
while(ix >= 0) inlets[ix--] = NULL;
}
#else
#error
#endif
......
......@@ -42,14 +42,12 @@ add_method1(c,cb_px_ft ## IX,"ft" #IX,A_FLOAT)
void flext_base::cb_px_anything(t_class *c,const t_symbol *s,short argc,t_atom *argv)
{
// check if inlet allows anything (or list)
int ci = ((flext_hdr *)c)->curinlet;
thisObject(c)->CbMethodHandler(ci,s,argc,argv);
}
void flext_base::cb_px_int(t_class *c,long v)
{
// check if inlet allows int type
t_atom atom; SetInt(atom,v);
int ci = ((flext_hdr *)c)->curinlet;
thisObject(c)->CbMethodHandler(ci,sym_int,1,&atom);
......@@ -57,7 +55,6 @@ void flext_base::cb_px_int(t_class *c,long v)
void flext_base::cb_px_float(t_class *c,double v)
{
// check if inlet allows float type
t_atom atom; SetFloat(atom,v);
int ci = ((flext_hdr *)c)->curinlet;
thisObject(c)->CbMethodHandler(ci,sym_float,1,&atom);
......@@ -65,7 +62,6 @@ void flext_base::cb_px_float(t_class *c,double v)
void flext_base::cb_px_bang(t_class *c)
{
// check if inlet allows bang
int ci = ((flext_hdr *)c)->curinlet;
thisObject(c)->CbMethodHandler(ci,sym_bang,0,NULL);
}
......@@ -105,7 +101,7 @@ void flext_base::SetProxies(t_class *c)
add_bang(c,cb_px_bang);
add_method1(c,cb_px_int,"int",A_INT);
add_method1(c,cb_px_float,"float",A_FLOAT);
add_methodG(c,cb_px_anything,"list");
// add_methodG(c,cb_px_anything,"list");
add_anything(c,cb_px_anything);
#else
#error Not implemented!
......@@ -122,16 +118,4 @@ void flext_base::SetProxies(t_class *c)
ADD_IN_FT(8);
ADD_IN_FT(9);
}
#elif FLEXT_SYS == FLEXT_SYS_JMAX
void flext_base::jmax_proxy(fts_object_t *c, int winlet, fts_symbol_t s, int argc, const fts_atom_t *argv)
{
thisObject(c)->CbMethodHandler(winlet,s,argc,argv);
}
void flext_base::SetProxies(t_class *c)
{
fts_class_set_default_handler(c, jmax_proxy);
}
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment