Here we go, a bit cleaned, and 3 NN per type of data. It looks like that:
and that is the code:
(
// We'll load all the Fluid Corpus Manipulation audio example files
~path = FluidFilesPath();
~loader = FluidLoadFolder(~path);
~monosource = Buffer(s);
~loader.play(s,action:{ |dataDictionary|
"Done loading".postln;
FluidBufCompose.process(s,~loader.buffer,numChans: 1,destination: ~monosource, action: {\done.postln});
});
)
// make the MFCCs
~mfccs = Buffer(s);
FluidBufMFCC.process(s, ~monosource, features: ~mfccs, startCoeff: 1, minFreq: 40, maxFreq: 10000, windowSize: 8192, padding: 0, action: {\done.postln})
~mfccDS = FluidDataSet(s).fromBuffer(~mfccs, action: {\done.postln})
~mfccDS.print
/// make the scaler and the normaliser
(
~norm = FluidNormalize(s,min: -1);
~scale = FluidStandardize(s).load(Dictionary.newFrom([\std, 120.dup(13), \mean, 0.dup(13), \cols, 13]));
~normedMFCCs = FluidDataSet(s);
~scaledMFCCs = FluidDataSet(s);
~norm.fitTransform(~mfccDS, ~normedMFCCs);
~scale.transform(~mfccDS, ~scaledMFCCs);
)
/// make 2d versions of each
(
~normed2d = FluidDataSet(s);
~scaled2d = FluidDataSet(s);
~umap = FluidUMAP(s);
)
~umap.fitTransform(~normedMFCCs, ~normed2d, action: {\done.postln}) //wait
~umap.fitTransform(~scaledMFCCs, ~scaled2d, action: {\done.postln}) //wait
(
~normed2d.print;
~scaled2d.print;
~normedMFCCs.print;
~scaledMFCCs.print;
)
///now plot and query
(
var query2d = Buffer.alloc(s,2);
var query13ds = Buffer.alloc(s,2);
var query2dn = Buffer.alloc(s,2);
var query13dn = Buffer.alloc(s,2);
var previous = -1;
var w = Window(bounds: Rect(width: 1900, height: 450)).front;
var source = TextField(w,Rect(5,420,80,20));
var dist2ds = 3.collect{|i|TextField(w,Rect(165+(i*80),420,55,20))};
var dist13ds = 3.collect{|i|TextField(w,Rect(665+(i*80),420,55,20))};
var dist2dn = 3.collect{|i|TextField(w,Rect(1165+(i*80),420,55,20))};
var dist13dn = 3.collect{|i|TextField(w,Rect(1665+(i*80),420,55,20))};
var pl1 = FluidPlotter(w,Rect(left: 0,width: 400,height: 400), xmin: -20, xmax: 20, ymin: -20, ymax: 20, mouseMoveAction: {
arg view, x, y, modifiers;
query2d.setn(0, [x,y]);
~scaled2d.kNearest(query2d, 1, {
arg nearest;
if (nearest != previous) {
Synth(\pointplayer, [\point, nearest.asInteger]);
previous = nearest;
defer{source.string = nearest};
~scaled2d.getPoint(nearest, query2d, {
~scaled2d.kNearest(query2d, 4, {
arg nearestO;
pl1.highlight = nearestO;
defer{nearestO[1..].do{|label, i| dist2ds[i].string = label}};
});
});
~scaledMFCCs.getPoint(nearest, query13ds, {
~scaledMFCCs.kNearest(query13ds, 4, {
arg nearestS;
pl2.highlight = nearestS;
defer{nearestS[1..].do{|label, i| dist13ds[i].string = label}};
});
});
~normed2d.getPoint(nearest, query2dn, {
~normed2d.kNearest(query2dn, 4, {
arg nearestN;
pl3.highlight = nearestN;
defer{nearestN[1..].do{|label, i| dist2dn[i].string = label}};
});
});
~normedMFCCs.getPoint(nearest, query13dn, {
~normedMFCCs.kNearest(query13dn, 4, {
arg nearestN13;
pl4.highlight = nearestN13;
defer{nearestN13[1..].do{|label, i| dist13dn[i].string = label}};
});
});
};
});
});
var pl2 = FluidPlotter(w,Rect(left: 500,width: 400,height: 400), xmin: -20, xmax: 20, ymin: -20, ymax: 20);
var pl3 = FluidPlotter(w,Rect(left: 1000,width: 400,height: 400), xmin: -20, xmax: 20, ymin: -20, ymax: 20);
var pl4 = FluidPlotter(w,Rect(left: 1500,width: 400,height: 400), xmin: -20, xmax: 20, ymin: -20, ymax: 20);
~scaled2d.dump{|x|pl1.dict = x; pl2.dict = x};
~normed2d.dump{|x|pl3.dict = x; pl4.dict = x};
SynthDef(\pointplayer, {
arg point, out = 0;
var start = point * 4096;
var dur = 8192 / SampleRate.ir;
Out.ar(out, PlayBuf.ar(1, ~monosource, startPos: start).dup * EnvGen.ar(Env.sine(dur),doneAction: 2));
}).send;
Button(w, Rect(85,420,20,20)).action_{Synth(\pointplayer, [\point, source.string.postln.asInteger])};
3.do{|i|Button(w, Rect(220+(i*80),420,20,20)).action_{Synth(\pointplayer, [\point, dist2ds[i].string.postln.asInteger])}};
3.do{|i|Button(w, Rect(720+(i*80),420,20,20)).action_{Synth(\pointplayer, [\point, dist13ds[i].string.postln.asInteger])}};
3.do{|i|Button(w, Rect(1220+(i*80),420,20,20)).action_{Synth(\pointplayer, [\point, dist2dn[i].string.postln.asInteger])}};
3.do{|i|Button(w, Rect(1720+(i*80),420,20,20)).action_{Synth(\pointplayer, [\point, dist13dn[i].string.postln.asInteger])}};
StaticText(w, Rect(5,400,100,20)).string_("source:");
StaticText(w, Rect(165,400,100,20)).string_("2D-scaled:");
StaticText(w, Rect(665,400,100,20)).string_("13D-scaled:");
StaticText(w, Rect(1165,400,100,20)).string_("2D-normalised:");
StaticText(w, Rect(1665,400,100,20)).string_("13D-normalised:");
)