Is there a simple way to convert Ugen output into an Array?

I’m looking for a simple way to turn this into an array but not coming up with anything. Signal looked promising, but no cigar.

{Perlin3.ar(*{Line.ar(0, 1000, 30)}.dup(3))}.plot(1);

Any ideas? I looked at this thread but the solution seems quite complex Is it possible to get the output of a ugen as an array of floats (audio buffer)?

Any help greatly appreciated.

(Side note, this was posted in a quote block, not a code block – use triple-backticks.)

If you save the plotter in a variable, then you can get the data from the plot.

p = { Perlin3.ar(*{Line.ar(0, 1000, 30)}.dup(3)) }.plot(1);

// wait for display, then...
p.value[0]  // I think, not at the computer now

hjh

2 Likes

Thanks jamshark, I got confused as I thought the array wouldn’t all be stored in 0. I tried to return p.value[7] got nothing and assumed wrongly nothing was stored in there.

Appreciate your help.

Plots may be multichannel, so the value of a plot is an array of the channels.

hjh

1 Like

Is there a way to make it only spit out an Array after a set amount of cycles? Looks very useful , but the array goes on forever.

you can use clump for that.

In general:


{ Perlin3.ar(*{Line.ar(0, 1000, 30)}.dup(3))}.getToFloatArray(0.01, action: { |array| array.postln; });

(
fork {
	var ugenFunc = { Perlin3.ar(*{Line.ar(0, 1000, 30)}.dup(3))};
	var cond = CondVar.new;
	var array;
	ugenFunc.getToFloatArray(0.01, action: { |x| array = x; cond.signalOne });
	cond.wait;
	// do something with the array
	array.postln
}
)
1 Like

clump wasn’t it,

It was copyRange.
array.copyRange(0, 8).postcs;

Im trying to take something like SinOcs and make a little array that imitates its output for something like amplitude in a pattern

Is there any way to shorten the numbers the array spits out?
Im getting this from a SinOsc
[0.0, 0.00014246479258873, 0.00028492958517745, 0.00042739437776618, 0.0005698591703549, 0.00071232399204746, 0.00085478869732469, 0.00099725346080959, 0.0011397181078792]

You can just round the array to whatever resolution you want, eg.

[0.0, 0.00014246479258873, 0.00028492958517745, 0.00042739437776618, 0.0005698591703549, 0.00071232399204746, 0.00085478869732469, 0.00099725346080959, 0.0011397181078792].round(0.0001)
// [ 0.0, 0.0001, 0.0003, 0.0004, 0.0006, 0.0007, 0.0009, 0.001, 0.0011 ]
1 Like

You can use the duration arg of loadToFloatArray to generate only the number of samples you need.
Remember also to de-interleave the array if you have multiple channels by .clump(numChannels).flop

(
s.waitForBoot{
	
	var numSamples = 25;  // number of samples you want
	var cond = CondVar(); // used to wait for the function to generate samples
	var numChannels = 3;  // for multichannel output
	var outArray;         // the array to store your output
	{
		SinOsc.ar(2000 * (1..numChannels)) // 3 channels of signal
	}.loadToFloatArray(
		duration: numSamples / s.sampleRate, // just generatea as much as you need
		action: { |array|
			outArray = array.clump(numChannels).flop; // de-interleave the channels
			cond.signalOne;
		}
	);
	cond.wait; // wait for the function to generate the output
	
	// do something with the array
	outArray.plot;
	
}
)
1 Like

Thank you, All very helpful. Thanks again