Merge branch 'clients/inter_client_comms' of https://bitbucket.org/flucoma/flucoma-supercollider into clients/inter_client_comms

nix
Gerard 6 years ago
commit d5f692cf0e

@ -23,7 +23,7 @@
mfcc = FluidBufMFCC.kr(src,startFrame:start,numFrames:num,numChans:1,features:~mfccbuf[voice],trig:1);
stats = FluidBufStats.kr(~mfccbuf[voice],stats:~statsbuf[voice],trig:Done.kr(mfcc));
flatten = FluidBufFlatten.kr(~statsbuf[voice],~flatbuf[voice],trig:Done.kr(stats));
writer = FluidDataSetWr.kr(label,~flatbuf[voice],~ds,trig:Done.kr(flatten))
writer = FluidDataSetWr.kr(~ds,label,buf: ~flatbuf[voice],trig:Done.kr(flatten))
});
)

@ -1,149 +0,0 @@
// TB2 SC Playground V0
/*
Current stinkers:
1) Producing flat datapoints for FluidDataSet (i.e. flattening and cherry picking a multichannel buffer) takes bloody ages due to all the server syncing. I can't work out how to do it reliably outwith a Routine (which would certainly be quicker, to my mind)
2) Functions from the classes don't yet directly return things, and you have to access their return data through actions. This is partly because I don't know what the correct thing to do w/r/t blocking is, so I'm hoping GR will do it properly
*/
//STEP 0: start server
s.reboot;
if(s.hasBooted.not){"Warning: server not running".postln};
//STEP 1: Get some files
Buffer.freeAll;
(
FileDialog.new(fileMode:2,okFunc:{|x| ~path = x[0];
~audioBuffers = SoundFile.collectIntoBuffers(~path+/+'*',s);
~lookup = Dictionary(n:~audioBuffers.size);
~audioBuffers.do{|b| ~lookup.add(b.path->b)};
});
)
//STEP 2: Make a FluidDataSet
~dataset = FluidDataSet.new(s,"mfccs");
//STEP 3A: EITHER populate the dataset like so (and cry about how long the data point assembly takes)
(
Routine{
var tmpMFCCs = Buffer.new(s);
var tmpStats = Buffer.new(s);
var tmpFlat = Buffer.alloc(s,12 * 4 * 2, 1);//12 dims * 4 stats * 2 derivatives
s.sync;
~audioBuffers.do{|b|
("Analyzing" + b.path).postln;
FluidBufMFCC.process(s,b,features: tmpMFCCs);
FluidBufStats.process(s,source:tmpMFCCs, stats: tmpStats,numDerivs:1);
"stats".postln;
12.do{|i|
//This takes ages becayse of server syncing :-(
FluidBufCompose.process(s,tmpStats,0,2, i+1,1, destination: tmpFlat, destStartFrame: (i*8));
FluidBufCompose.process(s,tmpStats,4,1, i+1,1, destination: tmpFlat, destStartFrame: (i*8) + 2);
FluidBufCompose.process(s,tmpStats,6,3, i+1,1, destination:tmpFlat, destStartFrame: (i*8) + 3);
FluidBufCompose.process(s,tmpStats,11,1, i+1,1, destination: tmpFlat, destStartFrame: (i*8) + 6);
FluidBufCompose.process(s,tmpStats,13,1, i+1,1, destination:tmpFlat, destStartFrame: (i*8) + 7);
};
~dataset.addPoint(b.path,tmpFlat);
};
s.sync;
"Done".postln;
tmpFlat.free;
tmpStats.free;
tmpMFCCs.free;
}.play
)
//STEP 3B: OR populate the dataset with the flattening happening in langage side (much faster for now)
(
Routine{
var tmpMFCCs = Buffer.new(s);
var tmpStats = Buffer.new(s);
var langStats;
var langFlat;
var tmpFlat = Buffer.alloc(s,12 * 4 * 2, 1); //12 dims * 4 stats * 2 derivatives
s.sync;
~audioBuffers.do{|b|
("Analyzing" + b.path).postln;
FluidBufMFCC.process(s,b,features: tmpMFCCs);
FluidBufStats.process(s,source:tmpMFCCs, stats: tmpStats,numDerivs:1);
tmpStats.getn(0,182,{|y| langStats = y;});
s.sync;
"stats".postln;
langFlat = Array.new();
//taking the mean, std, min and max, and the mean, std, min and max of the first derivative, of each MFCCs except coeff 0 to dismiss amplitude)
[0,1,4,6,7,8,11,13].do({|i| var j,k; j =((i*13)+1); k = j + 11;langFlat = langFlat ++ langStats[j..k]});
tmpFlat.setn(0,langFlat);
s.sync;
~dataset.addPoint(b.path,tmpFlat);
};
s.sync;
"Done".postln;
tmpStats.free;
tmpMFCCs.free;
tmpFlat.free;
}.play
)
//check
~dataset.size({|x| x.postln})
//save
(
FileDialog.new(fileMode: 0, acceptMode: 1, okFunc:{|x| var file = x[0];
//if the file exists and is a json, delete it
if ((file.splitext[1] == "json") && (File.existsCaseSensitive(file)), {File.delete(file);"File Overwritten".postln;});
//if not json, make it so
if (file.splitext[1] != "json", {file = file ++ ".json";});
// then write
~dataset.write(file);
});
)
//STEP 3C: OR load in one you rolled earlier
FileDialog.new(fileMode: 0, acceptMode: 0, okFunc:{|x| ~dataset.read(x[0])});
//peek
c = Buffer.new(s)
~dataset.getPoint(~audioBuffers[3].path,c, { c.getn(0,96,{|x| x.postln})})
/*************************************/
//FluidKDTree
~kdtree = FluidKDTree.new(s)
~kdtree.fit(~dataset,action:{"fit".postln})
//match
~kdtree.kNearest(c,5,{|x| ~matches = x;})
~kdtree.kNearestDist(c,5,{|x| x.postln})
~lookup[~matches[4]].postln
/*************************************/
//FluidKMeans
~kMeans= FluidKMeans.new(s)
~kMeans.fit(~dataset,k:5,action:{"fit".postln})
// predicts in which cluster a point would be
~kMeans.predictPoint(c,{|x|x.postln})
// predicts which cluster each points of a dataset would be in, as a label
~labels = FluidLabelSet.new(s,"clusters")
~kMeans.predict(~dataset,~labels, {|x| x.postln})
~labels.getLabel(~audioBuffers[2].path,action:{|c| c.postln})
//query each item
(
Routine{
~labels.size({|x|x.do {|i|
~audioBuffers[i].path.postln;
~labels.getLabel(~audioBuffers[i].path,action:{|c| c.postln});
s.sync;
}
});
}.play
)
//labelset can be written as json
~labels.write(~path+/+"labels.json")

@ -3,13 +3,14 @@ s.reboot
~point = Buffer.alloc(s,1,1)
(
Routine{
10.do{|i|
~point.set(0,i);
s.sync;
~ds.addPoint(i.asString,~point,{("addPoint"+i).postln})
}
10.do{|i|
~point.set(0,i);
~ds.addPoint(i.asString,~point,{("addPoint"+i).postln});
s.sync;
}
}.play
)
~ds.print;
/*** KDTREE ***/
~tree = FluidKDTree.new(s)
@ -18,12 +19,11 @@ Routine{
k = 5; //play with this
(
Routine{
10.do{|i|
~point.set(0,i);
s.sync;
("Neighbours for point" + i).postln;
~tree.kNearest(~point, k, {|x| ("Labels:" + x).postln})
}
10.do{|i|
~point.set(0,i);
~tree.kNearest(~point, k, {|x| "Neighbours for a value of % are ".postf(i); x.postln});
s.sync;
}
}.play
)
@ -35,11 +35,11 @@ Routine{
(
Routine{
10.do{|i|
10.do{|i|
~point.set(0,i);
s.sync;
~kmeans.predictPoint(~point,{|x| ("Predicted Cluster for point" + i ++ ":" + x).postln})
}
~kmeans.predictPoint(~point,{|x| ("Predicted Cluster for a value of " + i ++ ":" + x).postln});
s.sync;
}
}.play
)
@ -48,12 +48,16 @@ Routine{
~kmeans.predict(~ds,~labels, {|x| ("Size of each cluster" + x).postln})
(
Routine{
var n;
~labels.size({|x|
x.asInteger.do{|i|
~labels.getLabel(i.asString,action: {|l|("Label for" + i ++ ":" + l).postln});
s.sync;
};});
}.play
~labels.size{|x|
Routine{x.asInteger.do{|i| //size does not return a value, but we can retrieve it via a function
~labels.getLabel(i,action: {|l|
("Label for entry " + i ++ ":" + l).postln;
});
s.sync;
}
}.play;
};
)
// or simply print it
~labels.print

@ -7,11 +7,12 @@ Routine{
var d;
if(i<=4,{d=i},{d=i+5});
~point.set(0,d);
~ds.addPoint(i.asString,~point,{("addPoint"+i).postln});
s.sync;
~ds.addPoint(i.asString,~point,{("addPoint"+i).postln})
}
}.play
)
~ds.print;
/*** KDTREE ***/
~tree = FluidKDTree.new(s)
@ -20,16 +21,16 @@ Routine{
k = 5; //play with this
(
Routine{
10.do{|i|
~point.set(0,i*2);
s.sync;
("Neighbours for point" + (i*2)).postln;
~tree.kNearest(~point, k, {|x| ("Labels:" + x).postln});
~tree.kNearestDist(~point,k,{|x| ("Distances:" + x).postln})
}
15.do{|i|
~point.set(0,i);
~tree.kNearest(~point, k, {|x| "Neighbours for a value of % are ".postf(i); x.post;" with respective distances of ".post;});
~tree.kNearestDist(~point,k,{|x| x.postln});
s.sync;
}
}.play
)
/*** KMEANS ***/
~kmeans = FluidKMeans.new(s)
@ -38,10 +39,10 @@ Routine{
(
Routine{
10.do{|i|
15.do{|i|
~point.set(0,i);
s.sync;
~kmeans.predictPoint(~point,{|x| ("Predicted Cluster for point" + i ++ ":" + x).postln})
~kmeans.predictPoint(~point,{|x| ("Predicted Cluster for a value of " + i ++ ":" + x).postln});
}
}.play
)
@ -51,12 +52,16 @@ Routine{
~kmeans.predict(~ds,~labels, {|x| ("Size of each cluster" + x).postln})
(
Routine{
var n;
~labels.size({|x|
x.asInteger.do{|i|
~labels.getLabel(i.asString,action: {|l|("Label for" + i ++ ":" + l).postln});
~labels.size{|x|
Routine{x.asInteger.do{|i| //size does not return a value, but we can retrieve it via a function
~labels.getLabel(i,action: {|l|
("Label for entry " + i ++ ":" + l).postln;
});
s.sync;
};});
}.play
}
}.play;
};
)
// or simply print it
~labels.print

@ -22,8 +22,8 @@ v.mouseDownAction = {|view, x, y|myx=x;myy=y;w.refresh;
// myx.postln;myy.postln;
Routine{
b.setn(0,[myx,myy]);
s.sync;
~knn.predictPoint(b, k, action: {|x|x.postln;});
s.sync;
}.play;};
//custom redraw function
@ -40,19 +40,19 @@ w.drawFunc = {
)
(
//populates a dataset with the same squares as the gui (their centres)
//populates a dataset with the same squares as the gui (their centres) (old method, iterating over buffers. A dictionary approach would be more efficient, see the example in this folder)
Routine{
50.do{|i|
var x = i.div(10)*30+20;
var y = i.mod(10)*30+20;
b.setn(0,[x,y]);
s.sync;
~simpleInput.addPoint(i.asString,b,{("Added Input" + i).postln});
~simpleOutput.addLabel(i.asString,"White",{("Added Output" + i).postln});
b.setn(0,[x+150,y]);
s.sync;
b.setn(0,[x+150,y]);
~simpleInput.addPoint((i+50).asString,b,{("Added Input" + (i+50)).postln});
~simpleOutput.addLabel((i+50).asString,"Red",{("Added Output" + (i+50)).postln});
s.sync;
}
}.play;
)

@ -6,14 +6,15 @@
(
// fill up the dataset with 20 entries of 10 column/dimension/descriptor value each. The naming of the item's label is arbitrary as usual
20.do({
arg i;
Buffer.loadCollection(s,Array.fill(~nb_of_dim,{rrand(0.0,100.0)}),action:{
arg buf;
~dataset.addPoint("point-"++i.asInteger.asString,buf);
buf.free;
Routine{
var buf = Buffer.alloc(s,~nb_of_dim);
20.do({ arg i;
buf.loadCollection(Array.fill(~nb_of_dim,{rrand(0.0,100.0)}));
~dataset.addPoint("point-"++i.asInteger.asString, buf);
s.sync;
});
});
buf.free;
}.play
)
~dataset.print;

Loading…
Cancel
Save