Alright - I’m posting the full code below, since I feel like maybe there is a larger issue at hand.
It’s definitely true that the getPoint
needs some kind of callback - but I’m not sure how that works. I might be missing where it is in the documentation… I’m attempting to pass the bufNum, start, and stop points in the FluidPlotter now - but it requires the same situation with reading from the FluidDataSet.getPoint
…
I’ll look closer at @tedmoore’s example also, since I think it will take me a little longer to understand the separate OSC calls - but if I’m understanding correctly, that’s the only way to do this?
Thanks for all your patience.
//establish two data sets.
~dataset1 = FluidDataSet(s); //store all incoming analysis with ID.
~dataset2 = FluidDataSet(s); //[ID, bufferNumber, startSample, number of samples];
// Change the call to analyse to take both datasets and update them with a new slice buffer
~b = Buffer.read(s, FluidFilesPath("Nicol-LoopE-M.wav")); //load Buffer
~sliced = ~onsetSlicer.(~b);
~analyze.(~sliced, ~b, ~dataset1, ~dataset2);
// FluidFilesPath();
// for subsequent files, process should be the same
~b = Buffer.read(s, FluidFilesPath("Green-Box639.wav")); //load Buffer
~sliced = ~onsetSlicer.(~b);
~analyze.(~sliced, ~b, ~dataset1, ~dataset2);
//onset function and analysis function
~onsetSlicer = {|mainBuf|
var indices = Buffer(s);
FluidBufOnsetSlice.processBlocking(s,mainBuf,
metric:9,threshold:0.05,
indices:indices,action:{
"found % slice points".format(indices.numFrames).postln;
"average duration per slice: %".format(mainBuf.duration (indices.numFrames+1)).postln;
});
indices;
};
~analyze ={|slices, currentBuf, analysis_dataset, index_dataset|
slices.loadToFloatArray(action:{
arg fa;
var mfccs = Buffer(s);
var stats = Buffer(s);
var flat = Buffer(s);
var offset = 0;
analysis_dataset.size({|o| offset = o;});
s.sync;
fa.doAdjacentPairs{
arg start, end, i;
var num = end - start;
var slice_info = Buffer.sendCollection(s, [slices.bufnum, start, num]);
FluidBufMFCC.processBlocking(s,currentBuf,start,num,features:mfccs,numCoeffs:13,startCoeff:1);
FluidBufStats.processBlocking(s,mfccs,stats:stats,select:[\mean]);
FluidBufFlatten.processBlocking(s,stats,destination:flat);
index_dataset.addPoint(i + offset, slice_info);
analysis_dataset.addPoint(i + offset,flat);
slice_info.free;
};
s.sync;
mfccs.free;
stats.free;
flat.free;
});
};
(
~umapped = FluidDataSet(s);
FluidUMAP(s,numNeighbours:15,minDist:0.9).fitTransform(~dataset1,~umapped,action:{"umap done".postln});
)
(
~normed = FluidDataSet(s);
FluidNormalize(s).fitTransform(~umapped,~normed);
)
(
~tree = FluidKDTree(s).fit(~normed);
~normed.dump({
arg dict;
var point = Buffer.alloc(s,2);
var point2 = Buffer(s);
var valueArray = [];
var previous = nil;
defer{
FluidPlotter(dict:dict,mouseMoveAction:{
arg view, x, y;
//[x,y].postln;
point.setn(0,[x,y]);
~tree.kNearest(point,1,{
arg nearest;
if(nearest != previous){
~dataset2.getPoint(nearest, point2, {|fa|valueArray = fa;});
//valueArray.postln;
view.highlight_(nearest);
~play_slice.(valueArray[0], valueArray[1], valueArray[2]);
previous = nearest;
}
});
});
}
});
)
(
~play_slice = {
arg bufNum, start, stop;
{
var phs = Phasor.ar(0,BufRateScale.ir(bufNum),start,stop);
var sig = BufRd.ar(1,bufNum,phs);
var dursecs = (stop - start) / BufSampleRate.ir(bufNum);
var env;
dursecs = min(dursecs,1);
env = EnvGen.kr(Env([0,1,1,0],[0.03,dursecs-0.06,0.03]),doneAction:2);
sig.dup * env;
}.play;
};
)