I'm scratching my head wondering what's happening with an external i have written. The first 6 inlets work as expected, but not getting any response from inlets 7 and 8. I cut my code down as much as possible, and made a really simple external which just adds signals and outputs the result, but still getting this same behaviour.
In the howTo guide on writing externals, it mentions that an object can only be given a maximum of 6 arguments, or else needing a GIMME, so i was wondering if perhaps that 6 argument limit is somehow related here?
On 03/16/2016 03:13 AM, i go bananas wrote:
I'm scratching my head wondering what's happening with an external i have written. The first 6 inlets work as expected, but not getting any response from inlets 7 and 8. I cut my code down as much as possible, and made a really simple external which just adds signals and outputs the result, but still getting this same behaviour.
In the howTo guide on writing externals, it mentions that an object can only be given a maximum of 6 arguments, or else needing a GIMME, so i was wondering if perhaps that 6 argument limit is somehow related here?
i have written objects that have 64 inlet~s and i don't recall any problems.
so can you share some code?
gfards IOhannes
thanks Iohannes. it seems the inlets are fine,. and it's just an issue with the outlets, and probably a problem with me not being able to wrap my head around that weird clockwise outlet creation thing, and perhaps also this other issue of pd using the same address for inlets and outlets as an optimisation? it's also very likely to be an error in my code, but i honestly tried everything i could for most of the day, and could not get it working with the outlets running from left to right.
i have now managed to get the external working, by changing the order of outlet creation in tilde_dsp, that makes the outlets backwards.
for the moment, that is fine. but i would like to understand what is going wrong every time i try to use the outlets in left to right order.
am attaching a .zip with the code, the osx pd_darwin external compiled, and a test .pd file.
cheers, Matt
On 16/03/16 13:25, i go bananas wrote:
pd using the same address for inlets and outlets as an optimisation?
Yes, Pd recycles signal vectors so your output vector could be the same as the input vector, which means this code is unsafe because it could trash the inputs:
// loop through the 4 oscillators, adding the left to right: for (int osc = 0; osc < 4; osc++) { int n = (int)(w[14]); while (n--) *output[osc]++ = *left[osc]++ + *right[osc]++; }
The easiest fix would be to reverse the order of the loops:
int n = (int)(w[14]); while (n--) { for (int osc = 0; osc < 4; osc++) *output[osc] = *left[osc] + *right[osc]; output++; left++; right++; }
Your alternative method of changing the iolet creation orders is not a fix, it might "work" for one particular patch but another patch could break it again.
On 16/03/16 13:37, Claude Heiland-Allen wrote:
On 16/03/16 13:25, i go bananas wrote:
pd using the same address for inlets and outlets as an optimisation?
Yes, Pd recycles signal vectors so your output vector could be the same as the input vector, which means this code is unsafe because it could trash the inputs:
// loop through the 4 oscillators, adding the left to right: for (int osc = 0; osc < 4; osc++) { int n = (int)(w[14]); while (n--) *output[osc]++ = *left[osc]++ + *right[osc]++; }
The easiest fix would be to reverse the order of the loops:
int n = (int)(w[14]); while (n--) { for (int osc = 0; osc < 4; osc++) *output[osc] = *left[osc] + *right[osc]; output++; left++; right++; }
oops, this is wrong, I think
maybe *output[osc]++ = *left[osc]++ + *right[osc]++; would work in the inner loop in fact, I'm just not sure of the order of the C operations here...
Your alternative method of changing the iolet creation orders is not a fix, it might "work" for one particular patch but another patch could break it again.
Claude
On 03/16/2016 02:25 PM, i go bananas wrote:
thanks Iohannes. it seems the inlets are fine,. and it's just an issue with the outlets, and probably a problem with me not being able to wrap my head around that weird clockwise outlet creation thing, and perhaps also this other issue of pd using the same address for inlets and outlets as an optimisation?
most likely the latter.
i have now managed to get the external working, by changing the order of outlet creation in tilde_dsp, that makes the outlets backwards.
as claude has pointed out, this is not a fix, and just waits to break on next usage. which signals get re-used is a function of the surrounding patch, and unrelated to the creation order within the object's dsp-function.
msd IOhannes
Thanks Claude and Iohannes.
seems this is likely an issue with the recycled signals then...
i tried the method Claude suggested, and even with any tweak i could think of, it's still not working.
Iohannes, what do you mean when you say:
"which signals get re-used is a function of the surrounding patch, and unrelated to the creation order within the object's dsp-function."
???
Is there some sort of logic or rule to this?
On 03/16/2016 04:51 PM, i go bananas wrote:
Iohannes, what do you mean when you say:
"which signals get re-used is a function of the surrounding patch, and unrelated to the creation order within the object's dsp-function."
???
Is there some sort of logic or rule to this?
yes of course there is¹. the problem is, that it is none of your object's business and you cannot make any assumptions beforehand.
what you can do is check at runtime - in the dsp function - whether you have recycled signals, and call optimized code if not; but in any case you need to cater for the case that all signals actually refer to the same memory.
to cut this short: i think i'm not adding any additional information to what you already know, just expressing it in complicated terms.
gmsrd IOhannes
¹ the algorithm is in d_ugen.c.
this seems to work:
// loop through the 4 oscillators, adding the left to right:
t_sample l[4];
t_sample r[4];
t_sample out[4];
while (n--)
{
for (int osc = 3; osc >= 0; osc--)
{
l[osc] = *left[osc]++;
r[osc] = *right[osc]++;
out[osc] = l[osc] + r[osc];
}
for (int osc = 3; osc >= 0; osc--)
{
*output[osc]++ = out[osc];
}
}
oops, those weird for loops are just a throwback to something i tried that didn't work.
normal ones work fine: for (int osc = 0; osc < 4; osc++)
(sorry, just talking to myself here again)
actually, you don't need to copy the inlets into separate arrays. Just making a temp array for the outlets, writing to that in the main for loop, and then copying that to the outlet buffer in its own for loop is sufficient.
yes -- and you can allocate the temporary outputs on the stack using alloca().
cheers M
On Thu, Mar 17, 2016 at 10:31:06AM +0900, i go bananas wrote:
(sorry, just talking to myself here again)
actually, you don't need to copy the inlets into separate arrays. Just making a temp array for the outlets, writing to that in the main for loop, and then copying that to the outlet buffer in its own for loop is sufficient.
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
On 2016-03-17 03:06, Miller Puckette wrote:
yes -- and you can allocate the temporary outputs on the stack using alloca().
or allocate them on the heap in the "dsp"-routine: at this point you know whether the signals are recycled and how many samples you need, so you don't need to re-allocate every 1.5ms... fgmt IOhannes