ah, yeah im not sure this works in poly patches... id need to test.
(usually im using this technique in mono patches)
How to read a table two subpatch levels deep
Right. I need this to work in the polypatch or the whole idea of using tables for the mpe modmatrix will not work, since the whole point is to have globally available variables.
Ok Damn!
I just checked with a subpatch within a subpatch... it works. but not in mpe poly patch mode.
That is a real bummer. Is there a work around? can it be fixed? For example, can we address the main patch directly without going through the chain of parents, like with: root/test
I am using that type of table reference, in a poly patch and it works fine.
Attach a screenshot maybe?
nope .. not possible as far as i remember.
(that said, id need to go double check the generator code, see if there was a special case defined)
the underlying issue is...
any reference in a polyphonic voice is considered to be 'per voice', there is no way to differentiate common elements like the reference to the parent.
there is no way to go from the root, its relative
(*) unfortunately, given 2.0.0 is just released, id not want to dig into the 1.0 code now.. as id prefer to concentrate on 2.0
(note: 2.0.0 has same 'issue')
Ahh but my subpatch is not MPE. It works for regular poly, haven't tried MPE, though. Which Technobear says might be an issue.....
is there a way to use the poly/index to find the table in the main patch?
is there another way to do it? I thought maybe i could put the tables in the voice patch, but then will all my tables be copied as many times as there are voices in the polypatch?
That's what I do in all my patches. I think it has to be like that, that's how polyphony works, I think, that you have to assign all objects in the polyphonic subpatch to each of it's own voice. Or else it will not be polyphonic.
Is there a way to implement poly mpe manually?
I mean without using the subpatch settings.
If I copy my voice 4 times, make them each mono and make them react each to a single channel, wouldn't that be equivalent to using the polyphonic expression subpatch setting?
that way I could use the table properly.
k, just to confuse things
in 1.0.12, yes its specific to polyexpression - looks like a bug
in 2.0.0, the issue is with all polyphonic sub patches, as there is a bit of code generation that has not yet been 'ported',
I cannot think of a workaround... other than writing a custom object, which can bypass the issue by not using attributes (and parents)
you use attributes (see table/read as an example) to get the names,
then you need to be very careful of things likes scaling (again see table/read and write for examples)
but its very likely you do NOT want to do this... since if your not careful you'll just re-create the same issue in your own object
what you want to do is a singleton pattern (or a global static if you wanna be a bit hacky) , this will then be in scope to all objects, regardless of where they are in the patch.
(note to self: I need to have a look at this in 2.0, see if the new memory/patch layout changes this at all!)
Thanks @thetechnobear
Are there any beginner resources for this?
I've never even heard of singleton patterns. I don't mind being hacky but I am a real beginner in c++. I don't know where to start.
If I could access the tables in an object and do all the computations within the object, I think I could save a bunch of ram. But when a table is read within an object, within a subpatch, is it still two subpatch levels down? Because if it is essentially just one level down, then it could work. Right?
Yes one reason is because you would have a lot less inlets and outlets, which uses sram.
As a quick aside, in case it's useful -
regarding poly patches: for my poly midi Looper I have a table in the parent patch and then use polyindex inside the poly subpatch to tell it where to right into the table. Like, if polyindex=0 write to offset 0, if polyindex=1 write to offset 100, or whatever. Haven't touched mpe though...
How big are the tables? If they're small I wouldn't worry about them being multiplied. Thinking about it, isn't it more or less the same? Instead of one big table in the parent patch you have lots of smaller ones in the subpatches? But then if you needed to save the table it's easier with one big one...
thanks, I'm not sure how to use polyindex for this. How can I find this poly midi looper? is it in the community patches? I could take a look.
I am not using one big table but a bunch of smaller tables. One for each source (which manages the amounts of mod being sent to all the destinations).
@jaffasplaffa @MattilynMattroe @thetechnobear
Thanks for pointing me in this direction... I had a go at programming my own object and it sort of works... but could use some help making it better. The first version i made, to my surprise, actually works, but still uses up a bit too much ram (i need 44 of them in my voice patch (which means this number is times 4) to link up all the modulation targets. With this version I was able to get 21 of them going. Not bad at all! Huge increase in efficiency.
The first object i made was this:
It collects the appropriate tables. The target attribute corresponds to the offset for that modulation destination, so I'll set that individually for each one. The other attributes are the tables. The mod amounts are processed from unipolar to bipolar, and then they are multiplied with the corresponding values of the modulation sources. Then these are all summed with the initial value and sent to the output.
int te1 = attr_t1.array[_USAT((attrtarget),attr_t1.LENGTHPOW)]<<attr_t1.GAIN;
int te2 = attr_t2.array[_USAT((attrtarget),attr_t2.LENGTHPOW)]<<attr_t2.GAIN;
int tl1 = attr_t3.array[_USAT((attrtarget),attr_t3.LENGTHPOW)]<<attr_t3.GAIN;
int tl2 = attr_t4.array[_USAT((attrtarget),attr_t4.LENGTHPOW)]<<attr_t4.GAIN;
int tx = attr_t5.array[_USAT((attrtarget),attr_t5.LENGTHPOW)]<<attr_t5.GAIN;
int ty = attr_t7.array[_USAT((attrtarget),attr_t6.LENGTHPOW)]<<attr_t6.GAIN;
int tz = attr_t7.array[_USAT((attrtarget),attr_t7.LENGTHPOW)]<<attr_t7.GAIN;
int bpe1 = (te1-(1<<26))<<1;
int bpe2 = (te2-(1<<26))<<1;
int bpl1 = (tl1-(1<<26))<<1;
int bpl2 = (tl2-(1<<26))<<1;
int bpx = (tx-(1<<26))<<1;
int bpy = (ty-(1<<26))<<1;
int bpz = (tz-(1<<26))<<1;
int se1 = attr_ms.array[_USAT((0),attrms.LENGTHPOW)]<<attr_ms.GAIN;
int se2 = attr_ms.array[_USAT((1),attrms.LENGTHPOW)]<<attr_ms.GAIN;
int sl1 = attr_ms.array[_USAT((2),attrms.LENGTHPOW)]<<attr_ms.GAIN;
int sl2 = attr_ms.array[_USAT((3),attrms.LENGTHPOW)]<<attr_ms.GAIN;
int sx = attr_ms.array[_USAT((4),attrms.LENGTHPOW)]<<attr_ms.GAIN;
int sy = attr_ms.array[_USAT((5),attrms.LENGTHPOW)]<<attr_ms.GAIN;
int sz = attr_ms.array[_USAT((6),attrms.LENGTHPOW)]<<attr_ms.GAIN;
int e1 = ___SMMUL(bpe1<<3,se1<<2);
int e2 = ___SMMUL(bpe2<<3,se2<<2);
int l1 = ___SMMUL(bpl1<<3,sl1<<2);
int l2 = ___SMMUL(bpl2<<3,sl2<<2);
int xt = ___SMMUL(bpx<<3,sx<<2);
int yt = ___SMMUL(bpy<<3,sy<<2);
int zt = ___SMMUL(bpz<<3,sz<<2);
outlet_total = e1 + e2 + l1 + l2 + xt + yt + zt + inlet_initial;
But obviously this is not efficient.
So I've tried to compress everything into a single equation:
outlet_total =
(__SMMUL((((attrt1.array[USAT((attr_target),attr_t1.LENGTHPOW)]<<attr_t1.GAIN)-(1<<26))<<1)<<3,(attr_ms.array[USAT((0),attr_ms.LENGTHPOW)]<<attr_ms.GAIN)<<2))+
(__SMMUL((((attrt2.array[USAT((attr_target),attr_t2.LENGTHPOW)]<<attr_t2.GAIN)-(1<<26))<<1)<<3,(attr_ms.array[USAT((1),attr_ms.LENGTHPOW)]<<attr_ms.GAIN)<<2))+
(__SMMUL((((attrt3.array[USAT((attr_target),attr_t3.LENGTHPOW)]<<attr_t3.GAIN)-(1<<26))<<1)<<3,(attr_ms.array[USAT((2),attr_ms.LENGTHPOW)]<<attr_ms.GAIN)<<2))+
(__SMMUL((((attrt4.array[USAT((attr_target),attr_t4.LENGTHPOW)]<<attr_t4.GAIN)-(1<<26))<<1)<<3,(attr_ms.array[USAT((3),attr_ms.LENGTHPOW)]<<attr_ms.GAIN)<<2))+
(__SMMUL((((attrt5.array[USAT((attr_target),attr_t5.LENGTHPOW)]<<attr_t5.GAIN)-(1<<26))<<1)<<3,(attr_ms.array[USAT((4),attr_ms.LENGTHPOW)]<<attr_ms.GAIN)<<2))+
(__SMMUL((((attrt7.array[USAT((attr_target),attr_t6.LENGTHPOW)]<<attr_t6.GAIN)-(1<<26))<<1)<<3,(attr_ms.array[USAT((5),attr_ms.LENGTHPOW)]<<attr_ms.GAIN)<<2))+
(__SMMUL((((attrt7.array[USAT((attr_target),attr_t7.LENGTHPOW)]<<attr_t7.GAIN)-(1<<26))<<1)<<3,(attr_ms.array[USAT((6),attr_ms.LENGTHPOW)]<<attr_ms.GAIN)<<2))+
inlet_initial;
This compiles but for some reason the DSP maxes out...
Any ideas?
The DSP is usually nowhere near maxing out. Is this too much for a single operation or something like that?
answered on your other topic here
please can I ask that next time you do not cross-post...
its unnecessary to have multiple topics, and creates noise on the forum, and it will not get you a faster response
also, please ensure you search the forum... axoloti has been around a good amount of time, and we have helped a lot of new users, so there is a ton of good information on the forum already.