Hello list,
Back in March we had a discussion about getting signal inlets other than the main one to use floats as messages rather than signals.
I found a way to simulate this behavior (only for floats, not for anythings). A little background:
If you have a signal inlet, when you send a float to it, it stores that float in a field that the ugen graph function retrieves if it notices that inlet has no signal connection: if there's at least one signal connected, those are used, but if not, the float scalar is promoted to a signal. You can update that scalar even while a signal is connected.
You need to #include "g_canvas.h" to get started.
So the idea here is:
within your object class.
a creation arg.
connection feeding it. If so, then the scalar is ignored and you can use the signal as is. However, if you want the inlet to have zeroes when there's no signal inlet, rather than the scalar, you have to let your perform() routine know.
Before you can do 1) and 2), you need to keep the t_inlet pointer returned from inlet_new, something like:
x->x_rightinlet = inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
For 1), get a pointer to the float field and save it:
x->x_signalscalar = obj_findsignalscalar(x, 1); // second arg is the inlet index
Then to use it simply dereference it:
float scalar = *x->x_signalscalar; // this probably goes in your perform() routine
For 2), you want to set the float in the field, so you can just call the default float routine for inlets:
pd_float((t_pd *)x->x_rightinlet, f); // first arg is your inlet, cast as a (t_pd *), and the second is the input float
int forky_hasfeeders(t_object *x, t_glist *glist, int inno, t_symbol *outsym) { t_linetraverser t; linetraverser_start(&t, glist); while (linetraverser_next(&t)) if (t.tr_ob2 == x && t.tr_inno == inno && (!outsym || outsym == outlet_getsymbol(t.tr_outlet)) ) return (1); return (0); }
Which is called like so: forky_hasfeeders((t_object *)x, x->x_glist, 1, &s_signal);
This basically says "if there's a connection to the inlet in the 3rd arg, and it's from a signal outlet, return true." x->x_glist is set this way in the new() routine:
x->x_glist = canvas_getcurrent();
t_float scalar = *x->x_signalscalar; if (scalar != x->x_scalar) { x->x_scalar = scalar; // do other stuff, call functions, etc. }
I don't have time right now, but I'll make a minimal object later to illustrate.
I found a way to simulate this behaviour
I just wanna publicly thank you for being awesome :)
(only for floats, not for anythings)
it works for most of cyclone issues... more than in scope~, this is really crucial for other 4 objects in cyclone (bitand~, bitor~, bitxor~, delay~ [as in max7])
cheers
2016-07-14 13:29 GMT-03:00 Matt Barber brbrofsvl@gmail.com:
Hello list,
Back in March we had a discussion about getting signal inlets other than the main one to use floats as messages rather than signals.
I found a way to simulate this behavior (only for floats, not for anythings). A little background:
If you have a signal inlet, when you send a float to it, it stores that float in a field that the ugen graph function retrieves if it notices that inlet has no signal connection: if there's at least one signal connected, those are used, but if not, the float scalar is promoted to a signal. You can update that scalar even while a signal is connected.
You need to #include "g_canvas.h" to get started.
So the idea here is:
- in the new() routine, get access to the float scalar for your inlet
from within your object class.
- in the new() routine, optionally set the scalar field with a default or
a creation arg.
- check manually in your dsp() routine to see if that inlet has a signal
connection feeding it. If so, then the scalar is ignored and you can use the signal as is. However, if you want the inlet to have zeroes when there's no signal inlet, rather than the scalar, you have to let your perform() routine know.
- in the perform() routine, poll the scalar field for changes.
Before you can do 1) and 2), you need to keep the t_inlet pointer returned from inlet_new, something like:
x->x_rightinlet = inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
For 1), get a pointer to the float field and save it:
x->x_signalscalar = obj_findsignalscalar(x, 1); // second arg is the inlet index
Then to use it simply dereference it:
float scalar = *x->x_signalscalar; // this probably goes in your perform() routine
For 2), you want to set the float in the field, so you can just call the default float routine for inlets:
pd_float((t_pd *)x->x_rightinlet, f); // first arg is your inlet, cast as a (t_pd *), and the second is the input float
- is the trickiest part. The cyclone code does it this way:
int forky_hasfeeders(t_object *x, t_glist *glist, int inno, t_symbol *outsym) { t_linetraverser t; linetraverser_start(&t, glist); while (linetraverser_next(&t)) if (t.tr_ob2 == x && t.tr_inno == inno && (!outsym || outsym == outlet_getsymbol(t.tr_outlet)) ) return (1); return (0); }
Which is called like so: forky_hasfeeders((t_object *)x, x->x_glist, 1, &s_signal);
This basically says "if there's a connection to the inlet in the 3rd arg, and it's from a signal outlet, return true." x->x_glist is set this way in the new() routine:
x->x_glist = canvas_getcurrent();
- now in your perform() routine you can poll for changes:
t_float scalar = *x->x_signalscalar; if (scalar != x->x_scalar) { x->x_scalar = scalar; // do other stuff, call functions, etc. }
I don't have time right now, but I'll make a minimal object later to illustrate.
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list
Also, to be clear the effect will only take with dsp running, so it depends on the use case. You couldn't use this to pipe messages from the right inlet to an outlet (say) without dsp running, but most signal objects don't have that kind of behavior in the first place.
On Thu, Jul 14, 2016 at 12:47 PM, Alexandre Torres Porres porres@gmail.com wrote:
I found a way to simulate this behaviour
I just wanna publicly thank you for being awesome :)
(only for floats, not for anythings)
it works for most of cyclone issues... more than in scope~, this is really crucial for other 4 objects in cyclone (bitand~, bitor~, bitxor~, delay~ [as in max7])
cheers
2016-07-14 13:29 GMT-03:00 Matt Barber brbrofsvl@gmail.com:
Hello list,
Back in March we had a discussion about getting signal inlets other than the main one to use floats as messages rather than signals.
I found a way to simulate this behavior (only for floats, not for anythings). A little background:
If you have a signal inlet, when you send a float to it, it stores that float in a field that the ugen graph function retrieves if it notices that inlet has no signal connection: if there's at least one signal connected, those are used, but if not, the float scalar is promoted to a signal. You can update that scalar even while a signal is connected.
You need to #include "g_canvas.h" to get started.
So the idea here is:
- in the new() routine, get access to the float scalar for your inlet
from within your object class.
- in the new() routine, optionally set the scalar field with a default
or a creation arg.
- check manually in your dsp() routine to see if that inlet has a signal
connection feeding it. If so, then the scalar is ignored and you can use the signal as is. However, if you want the inlet to have zeroes when there's no signal inlet, rather than the scalar, you have to let your perform() routine know.
- in the perform() routine, poll the scalar field for changes.
Before you can do 1) and 2), you need to keep the t_inlet pointer returned from inlet_new, something like:
x->x_rightinlet = inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
For 1), get a pointer to the float field and save it:
x->x_signalscalar = obj_findsignalscalar(x, 1); // second arg is the inlet index
Then to use it simply dereference it:
float scalar = *x->x_signalscalar; // this probably goes in your perform() routine
For 2), you want to set the float in the field, so you can just call the default float routine for inlets:
pd_float((t_pd *)x->x_rightinlet, f); // first arg is your inlet, cast as a (t_pd *), and the second is the input float
- is the trickiest part. The cyclone code does it this way:
int forky_hasfeeders(t_object *x, t_glist *glist, int inno, t_symbol *outsym) { t_linetraverser t; linetraverser_start(&t, glist); while (linetraverser_next(&t)) if (t.tr_ob2 == x && t.tr_inno == inno && (!outsym || outsym == outlet_getsymbol(t.tr_outlet)) ) return (1); return (0); }
Which is called like so: forky_hasfeeders((t_object *)x, x->x_glist, 1, &s_signal);
This basically says "if there's a connection to the inlet in the 3rd arg, and it's from a signal outlet, return true." x->x_glist is set this way in the new() routine:
x->x_glist = canvas_getcurrent();
- now in your perform() routine you can poll for changes:
t_float scalar = *x->x_signalscalar; if (scalar != x->x_scalar) { x->x_scalar = scalar; // do other stuff, call functions, etc. }
I don't have time right now, but I'll make a minimal object later to illustrate.
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list
One last thing:
Since obj_findsignalscalar() isn't in m_pd.h, you have to declare it in your code:
EXTERN t_float *obj_findsignalscalar(t_object *x, int m);
On Thu, Jul 14, 2016 at 3:46 PM, Matt Barber brbrofsvl@gmail.com wrote:
Also, to be clear the effect will only take with dsp running, so it depends on the use case. You couldn't use this to pipe messages from the right inlet to an outlet (say) without dsp running, but most signal objects don't have that kind of behavior in the first place.
On Thu, Jul 14, 2016 at 12:47 PM, Alexandre Torres Porres < porres@gmail.com> wrote:
I found a way to simulate this behaviour
I just wanna publicly thank you for being awesome :)
(only for floats, not for anythings)
it works for most of cyclone issues... more than in scope~, this is really crucial for other 4 objects in cyclone (bitand~, bitor~, bitxor~, delay~ [as in max7])
cheers
2016-07-14 13:29 GMT-03:00 Matt Barber brbrofsvl@gmail.com:
Hello list,
Back in March we had a discussion about getting signal inlets other than the main one to use floats as messages rather than signals.
I found a way to simulate this behavior (only for floats, not for anythings). A little background:
If you have a signal inlet, when you send a float to it, it stores that float in a field that the ugen graph function retrieves if it notices that inlet has no signal connection: if there's at least one signal connected, those are used, but if not, the float scalar is promoted to a signal. You can update that scalar even while a signal is connected.
You need to #include "g_canvas.h" to get started.
So the idea here is:
- in the new() routine, get access to the float scalar for your inlet
from within your object class.
- in the new() routine, optionally set the scalar field with a default
or a creation arg.
- check manually in your dsp() routine to see if that inlet has a
signal connection feeding it. If so, then the scalar is ignored and you can use the signal as is. However, if you want the inlet to have zeroes when there's no signal inlet, rather than the scalar, you have to let your perform() routine know.
- in the perform() routine, poll the scalar field for changes.
Before you can do 1) and 2), you need to keep the t_inlet pointer returned from inlet_new, something like:
x->x_rightinlet = inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
For 1), get a pointer to the float field and save it:
x->x_signalscalar = obj_findsignalscalar(x, 1); // second arg is the inlet index
Then to use it simply dereference it:
float scalar = *x->x_signalscalar; // this probably goes in your perform() routine
For 2), you want to set the float in the field, so you can just call the default float routine for inlets:
pd_float((t_pd *)x->x_rightinlet, f); // first arg is your inlet, cast as a (t_pd *), and the second is the input float
- is the trickiest part. The cyclone code does it this way:
int forky_hasfeeders(t_object *x, t_glist *glist, int inno, t_symbol *outsym) { t_linetraverser t; linetraverser_start(&t, glist); while (linetraverser_next(&t)) if (t.tr_ob2 == x && t.tr_inno == inno && (!outsym || outsym == outlet_getsymbol(t.tr_outlet)) ) return (1); return (0); }
Which is called like so: forky_hasfeeders((t_object *)x, x->x_glist, 1, &s_signal);
This basically says "if there's a connection to the inlet in the 3rd arg, and it's from a signal outlet, return true." x->x_glist is set this way in the new() routine:
x->x_glist = canvas_getcurrent();
- now in your perform() routine you can poll for changes:
t_float scalar = *x->x_signalscalar; if (scalar != x->x_scalar) { x->x_scalar = scalar; // do other stuff, call functions, etc. }
I don't have time right now, but I'll make a minimal object later to illustrate.
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list