Hi Lukas,
I think if this really works then it is a good idea actually, and very
easy to implement! I see now no problems why it should not work... And
no one knows here what was the idea of the original authors :)
The only drawback is that like this ugens with different number of
input and output channels are not supported, and the tick() function
of a sub-ugen has no acces to both input channels (only a problem for
some effects).
I once modified the chuck type and ugen things to work with any number
of in and out channels. A multi-channel ugen has "ichan" and "ochan"
member variables, these are mono ugens of special type and used as the
input/output for a single channel of a multichannel ugen. For
multichannel ugens every input channel is passed to the tick()
function, and it should produce every
output sample. There is no need to overwrite the tick functions for
the sub-ugens. This was a lot of changes in chuck itself, but it is
working now.
If you are interested I can send you the source code in private
(because the mailing list doesn't allow it by default). But
unfortunately I wil be offline again for a few days now..
Regards,
Imre
2007/4/25, Lukas Degener
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
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users