"restructure" flat array to map values to array NamedControls

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.

Perhaps reshapeLike.

hjh

awesome, it seems this will probably work:

a = [ [ 0.30379746835443, 0.43037974683544 ], [ 0.0, 0.026315789473684 ], [ 0.0, 0.11111111111111 ], 0.44444444444444 ];
b = [0.303797, 0.43038, 0, 0.0263158, 0, 0.111111, 0.444444];
c = b.reshapeLike(a);