hey, this is part two of an issue im trying to deal with. first part was solved here:
Im creating a function called ~makeMLP
with an Environment inside of it. To this function im passing an array of keys. These keys either belong to “single” NamedControl
or to an array NamedControl
. For these keys im allocating a Buffer
with the number of frames, i need to store the control values of the NamedControls
inside of it.
so i have this test SynthDef:
(
SynthDef(\test, {
var freqRange = \freqRange.kr([2500, 3500], spec: ControlSpec(100, 8000));
var ringRange = \ringRange.kr([0.1, 0.15], spec: ControlSpec(0.1, 2.0));
var ampRange = \ampRange.kr([0.1, 0.2], spec: ControlSpec(0.1, 1.0));
var sig = Splay.ar(
Array.fill(3, {
Ringz.ar(
Dust.ar(\dens.kr(5, spec: ControlSpec(1, 10))),
exprand(freqRange[0], freqRange[1]),
exprand(ringRange[0], ringRange[1]),
exprand(ampRange[0], ampRange[1])
)
})
).distort;
sig = sig * \amp.kr(0.5, spec: ControlSpec(0, 1));
Out.ar(\out.kr(0), sig);
}).add;
)
and this ~makeMLP
function:
(
~makeMLP = { |synthDefName, params|
Environment.make { |self|
self.know = true;
~synthDef = SynthDescLib.global[synthDefName].def ?? {
Error("SynthDef '%' not found".format(synthDefName)).throw
};
~params = params;
if (params.isNil or: params.isEmpty) {
Error("MLP: pass a non-empty array of parameter names to be controlled, % was given.".format(params)).throw
};
~nodeProxy = NodeProxy.audio(s, 2);
~nodeProxy.prime(~synthDef);
~getParamNums = { |self|
self.params.collect{ |key|
var val;
val = self.nodeProxy.get(key);
max(1, val.size);
}.sum;
};
~bufParams = Buffer.alloc(s, self.getParamNums);
};
};
)
if im passing this array of keys to the function its allocating a buffer with 7 frames for me:
(
x = ~makeMLP.(\test,
params: [
\freqRange,
\ringRange,
\ampRange,
\dens,
],
);
)
x.bufParams.numFrames;
→ 7
I then use a function / pseudo-method called ~getParamValuesUni
to scale the corresponding values for these keys between 0 and 1, which is necessary for my use case:
~getParamValuesUni = { |self|
self.params.collect { |key|
self.synthDef.specs[key].unmap(self.nodeProxy.get(key));
};
};
This outputs a nested array, in this case:
-> [ [ 0.30379746835443, 0.43037974683544 ], [ 0.0, 0.026315789473684 ], [ 0.0, 0.11111111111111 ], 0.44444444444444 ]
I then use a function / pseudo-method called ~addPoint
where this array is loaded into the Buffer
by using .loadCollection
with some action.
~addPoint = { |self, id|
self.bufParams.loadCollection(self.getParamValuesUni.flat, 0) {
... some action ...
};
};
To load the nested array into the Buffer
the array has to be flattened, so i use .flat
here.
I then play a Synth which reads the data from the Buffer
, uses it and passes data via SendReply
to an OSCFunc
which has this function in it, to map the values in the needed range again and updates the NodeProxy
by using .set
.
~setParamValues = { |self, vals|
self.params.do { |key, n|
self.nodeProxy.set(key, self.synthDef.specs[key].map(vals[n]))
};
};
When i poll the values Im sending via SendReply
to the OSCFunc
you can see that the “data structure” for the data im loading into the buffer and the data ~setParamValues
is receiving via SendReply
is identical:
UGen Array [0]: 0.303797
UGen Array [1]: 0.43038
UGen Array [2]: 0
UGen Array [3]: 0.0263158
UGen Array [4]: 0
UGen Array [5]: 0.111111
UGen Array [6]: 0.444444
My problem now is that the data in the flat array im receiving in the OSCFunc
should now either be assigned to a “single” NamedControl
or an array NamedControl
, so for the array NamedControls
the data has to be “restructured”.
So how does ~setParamValues
has to be changed to deal with array NamedControls
?
I hope you could follow me and have an idea how to solve that. many thanks.