|
|
|
|
@ -94,12 +94,14 @@ fork{
|
|
|
|
|
~kmeans = FluidKMeans(s);
|
|
|
|
|
|
|
|
|
|
// Fit into 4 clusters
|
|
|
|
|
(
|
|
|
|
|
~kmeans.fitPredict(~dataset,~clusters, 4, action: {|c|
|
|
|
|
|
"Fitted.\n # Points in each cluster:".postln;
|
|
|
|
|
c.do{|x,i|
|
|
|
|
|
("Cluster" + i + "->" + x.asInteger + "points").postln;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Cols of kmeans should match dataset, size is the number of clusters
|
|
|
|
|
~kmeans.cols;
|
|
|
|
|
@ -120,6 +122,9 @@ fork{
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
//or faster by sorting the IDs
|
|
|
|
|
~clusters.dump{|x|~assignments = x.at("data").atAll(x.at("data").keys.asArray.sort{|a,b|a.asInteger < b.asInteger}).flatten.postln;}
|
|
|
|
|
|
|
|
|
|
//Visualise: we're hoping to see colours neatly mapped to quandrants...
|
|
|
|
|
(
|
|
|
|
|
d = ((~points + 1) * 0.5).flatten(1).unlace;
|
|
|
|
|
@ -150,13 +155,13 @@ w.front;
|
|
|
|
|
~ob = Bus.control(s); //output bus can be kr
|
|
|
|
|
~inpPoint = Buffer.alloc(s,2);
|
|
|
|
|
~outPoint = Buffer.alloc(s,1);
|
|
|
|
|
//Set properties on FluidKMeans:
|
|
|
|
|
~kmeans.inBus_(~ib).outBus_(~ob).inBuffer_(~inpPoint).outBuffer_(~outPoint);
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
//We make two Synths. One, before FluidKMeans, generates a random point and sends
|
|
|
|
|
//a trigger to query. The second, after FluidKMeans, gives us the predicted cluster //triggering upadtes from the outBus
|
|
|
|
|
(
|
|
|
|
|
//Set properties on FluidKMeans:
|
|
|
|
|
~kmeans.inBus_(~ib).outBus_(~ob).inBuffer_(~inpPoint).outBuffer_(~outPoint);
|
|
|
|
|
//pitching
|
|
|
|
|
{
|
|
|
|
|
var trig = Impulse.ar(10);
|
|
|
|
|
@ -170,6 +175,27 @@ w.front;
|
|
|
|
|
{
|
|
|
|
|
Poll.kr(In.kr(~ob),Latch.kr(BufRd.kr(1,~outPoint,0,interpolation:0),In.kr(~ob)),\cluster);
|
|
|
|
|
}.play(~kmeans.synth,addAction:\addAfter);
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// to sonify the output, here are random values alternating quadrant.
|
|
|
|
|
(
|
|
|
|
|
//Set properties on FluidKMeans:
|
|
|
|
|
~kmeans.inBus_(~ib).outBus_(~ob).inBuffer_(~inpPoint).outBuffer_(~outPoint);
|
|
|
|
|
//pitching
|
|
|
|
|
{
|
|
|
|
|
var count,trig,point;
|
|
|
|
|
trig = Impulse.ar(MouseX.kr(0,1).exprange(0.5,1000));
|
|
|
|
|
count = Stepper.ar(trig,0,0,3);
|
|
|
|
|
point = Latch.ar(WhiteNoise.ar([0.1,0.1],[count.div(2)-0.5,count.mod(2)-0.5]),trig);
|
|
|
|
|
BufWr.kr(point[0],~inpPoint,0);//annoying but triggered bufcompose or some other sort of entry here. (imagine having 20 mfccs here)
|
|
|
|
|
BufWr.kr(point[1],~inpPoint,1);
|
|
|
|
|
// Poll.kr(T2K.kr(trig),point,[\pointX,\pointY]);
|
|
|
|
|
Out.ar(~ib.index,[trig]);
|
|
|
|
|
trig*0.1;
|
|
|
|
|
}.play(~kmeans.synth,addAction:\addBefore);
|
|
|
|
|
//catching
|
|
|
|
|
{
|
|
|
|
|
SinOsc.ar((Latch.kr(BufRd.kr(1,~outPoint,0,interpolation:0),In.kr(~ob)) + 69).midicps,mul: 0.1);
|
|
|
|
|
}.play(~kmeans.synth,addAction:\addAfter);
|
|
|
|
|
)
|
|
|
|
|
::
|
|
|
|
|
|