[chuck-users] Solved: stereo ugens yet once more

Lukas Degener degenerl at cs.uni-bonn.de
Tue Apr 24 19:25:06 EDT 2007



Lukas Degener schrieb:
> hi again,
>
>  could you tell me what's the current state of affairs concerning stereo
> (multi-channel) ugens?
>
> I'm looking through the code and I can see that there is somthing going
> on, but I was not yet able to completely grasp the idea. :-)
>
> I see I can specify in and outs in type_engine_import_ugen_begin(...),
> Further it seems that for each channel, a "sub"-ugen is generated for
> me,  everything basically looks put in place allready...so...
>
> How do I control how those "sub-ugens" are ticked?  Would it be wise to
> just set their tick function pointer directly? 
I just tried exactly that. And, yes, it does works.


Here's a summary:


1) In the DLL_QUERY function, I make sure my ugen inherits UGen_Stereo.

(...)
if( !type_engine_import_ugen_begin( env, "Knarzomat", "UGen_Stereo", 
env->global(),
                                        knarzomat_ctor, knarzomat_dtor,
                                        knarzomat_tick, NULL ) )
(...)


2) I used the "constructor" of my custom ugen to rewire the tick 
callbacks of the left and right channel.

CK_DLL_CTOR( knarzomat_ctor ){

    Knarzomat * d = new Knarzomat();   
   
    OBJ_MEMBER_UINT(SELF, knarzomat_offset_data) = (t_CKUINT)d;   
   
    /* don't try this at home :-) */
    Chuck_UGen * me = ((Chuck_UGen *)SELF);
    me->m_multi_chan[0]->tick = knarzomat_tick_left;
    me->m_multi_chan[1]->tick = knarzomat_tick_right;
}

3) Finally, my tick callbacks look like this:
Knarzomat::tick(double)  causes the ugen to calculate a sample for both 
channels.
The result is stored in Knarzomat::leftOut and Knarzomat::rightOut.
The argument of the tick method is used to avoid redundant calculations.

CK_DLL_TICK(knarzomat_tick){   
    t_CKDOUBLE t = ((Chuck_UGen *)SELF)->m_time;
   
    Knarzomat * d =(Knarzomat *)OBJ_MEMBER_UINT(SELF, 
knarzomat_offset_data );   
    d->tick(t);
    *out = d->leftOut+d->rightOut;
    return TRUE;
}
CK_DLL_TICK(knarzomat_tick_left){
   
    t_CKDOUBLE t = ((Chuck_UGen *)SELF)->m_time;
    Chuck_UGen * owner = ((Chuck_UGen *)SELF)->owner;
    Knarzomat * d =(Knarzomat *)OBJ_MEMBER_UINT(owner, 
knarzomat_offset_data );
    d->tick(t);
    *out = d->leftOut;
    return TRUE;
}
CK_DLL_TICK(knarzomat_tick_right){
    t_CKDOUBLE t = ((Chuck_UGen *)SELF)->m_time;
    Chuck_UGen * owner = ((Chuck_UGen *)SELF)->owner;
    Knarzomat * d =(Knarzomat *)OBJ_MEMBER_UINT(owner, 
knarzomat_offset_data );   
    d->tick(t);
    *out = d->rightOut;
    return TRUE;
}


That's it. Works right away.
Probably not the most elegant solution, though. Please let me know if I 
did anything particulary stupid. :-)

Best Regards,
--lu



More information about the chuck-users mailing list