tableRand 						arbitrary random distributions
asRandomTable

// keep z and c as a global random table
// using the "l" key (when th plot view is in focus) you can unlock the plot view 
// and draw into the array.
// have a look at the mapping table: it changes only a very little, but this change has 
// a distinct effect on the distribution

(
var v, env, size=180; // keep w, z, d global

env = Env([0, 1, 0, 0, 1, 0], [0.3, 1, 1, 1, 0.2].normalizeSum, [-0.4,8, 'step', 'lin']);
c = Array.fill(size, { arg i; env[i / size] });

z = c.asRandomTable;

// views:

v = z.plot("mapping table");
w = c.plot("distribution function");

// now this produces values of the desired distribution:

f = { z = c.asRandomTable; d.value = z;  };

d = v.view.children[1].children[0]; // dig for multislider view.
w.view.children[1].children[0].mouseUpAction = { f.value };

)

(
SynthDef(\pgrain, 
	{ arg out = 0, freq=800, sustain=0.001, amp=0.5, pan = 0;
		var window;
		window = Env.sine(sustain, amp);
		Out.ar(out, 
			Pan2.ar(
				SinOsc.ar(freq),
				pan
			) * EnvGen.ar(window, doneAction:2)
		)
	}
).store;
)

Tdef(\x).play;

(
Tdef(\x, {
	loop {
		s.sendBundle(0.2, 
			["/s_new", \pgrain, -1, 1, 1, \freq, z.tableRand.linexp(0,1,200, 18000)]
		);
		0.03.wait;
	}

});
)

// tuning randomness on the server with the above created randmoTable
// using waveshaping, the same method can be done on an audio signal:

// allocate a buffer and write the random table into them
s.sendBundle(nil, ["/b_alloc", 144, 1, z.size, ["/b_setn", 144, 0, z.size] ++ z]);

// play a placeholder proxy
Ndef(\x).play;

// use the random values for sine frequency distribution
(
Ndef(\x, {
	var inRand, outRand, bufSize;
	bufSize = BufSamples.kr(144);
	inRand = TRand.kr(0, 1.0, Impulse.kr(MouseY.kr(0.2, 400, 1)));
	outRand = Shaper.kr(144, inRand);
	SinOsc.ar(
		LinExp.kr(outRand, 0, 1, 300, 7000)
	) * 0.1

});
)

// or for colored noise:

(
Ndef(\x, {
	var inRand, outRand, bufSize;
	bufSize = BufSamples.kr(144);
	inRand = WhiteNoise.ar;
	outRand = Shaper.ar(144, inRand);
})
)

// to continue editing the distribution with the GUI left from above, use this function:
(
f = { 
	z = c.asRandomTable; 
	d.value = z; 
	s.sendBundle(nil, ["/b_setn", 144, 1, z.size] ++ z);

};
)

// end, clear variables
d = z = w = nil;
Ndef(\x).clear;