You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
373 lines
9.4 KiB
Plaintext
373 lines
9.4 KiB
Plaintext
s.boot;
|
|
// 1. Load a folder of sounds
|
|
(
|
|
~load_folder = {
|
|
arg folder_path, action;
|
|
var loader = FluidLoadFolder(folder_path);
|
|
loader.play(s,{
|
|
"loaded % soundfiles".format(loader.index.size).postln;
|
|
action.(loader.buffer);
|
|
});
|
|
};
|
|
// 2. Slice
|
|
~slice = {
|
|
arg buffer, action;
|
|
Routine{
|
|
var indices = Buffer(s);
|
|
s.sync;
|
|
FluidBufNoveltySlice.process(s,buffer,indices:indices,threshold:0.5,action:{
|
|
"% slices found".format(indices.numFrames).postln;
|
|
"average duration in seconds: %".format(buffer.duration/indices.numFrames).postln;
|
|
action.(buffer,indices);
|
|
});
|
|
}.play;
|
|
};
|
|
// 3. Analyze
|
|
~analyze = {
|
|
arg buffer, indices, action;
|
|
Routine{
|
|
var feature_buf = Buffer(s);
|
|
var stats_buf = Buffer(s);
|
|
var point_buf = Buffer(s);
|
|
var cond = Condition.new;
|
|
var ds = FluidDataSet(s);
|
|
s.sync;
|
|
indices.loadToFloatArray(action:{
|
|
arg fa;
|
|
fa.doAdjacentPairs{
|
|
arg start, end, i;
|
|
var num = end - start;
|
|
|
|
// === PICK YOUR ANALYSIS (JUST CHOOSE 1) ===
|
|
FluidBufMFCC.process(s,buffer,start,num,features:feature_buf,numCoeffs:13,startCoeff:1).wait;
|
|
// FluidBufChroma.process(s,~loader.buffer,start,num,features:feature_buf).wait;
|
|
// FluidBufSpectralShape.process(s,buffer,start,num,features:feature_buf).wait;
|
|
//FluidBufPitch.process(s,buffer,start,num,features:feature_buf).wait;
|
|
|
|
FluidBufStats.process(s,feature_buf,stats:stats_buf).wait;
|
|
FluidBufFlatten.process(s,stats_buf,numFrames:1,destination:point_buf).wait;
|
|
|
|
ds.addPoint("slice-%".format(i),point_buf);
|
|
"% / % done".format(i+1,indices.numFrames-1).postln;
|
|
};
|
|
|
|
ds.print;
|
|
action.(buffer,indices,ds);
|
|
});
|
|
}.play;
|
|
};
|
|
// 4. Reduce to 2 Dimensions
|
|
~umap = {
|
|
arg buffer, indices, ds, action, numNeighbours = 15, minDist = 0.1;
|
|
Routine{
|
|
var standardizer = FluidStandardize(s);
|
|
var umap = FluidUMAP(s,2,numNeighbours,minDist);
|
|
|
|
var redux_ds = FluidDataSet(s);
|
|
|
|
s.sync;
|
|
|
|
standardizer.fitTransform(ds,redux_ds,{
|
|
"standardization done".postln;
|
|
umap.fitTransform(redux_ds,redux_ds,{
|
|
"umap done".postln;
|
|
action.(buffer,indices,redux_ds);
|
|
});
|
|
});
|
|
}.play;
|
|
};
|
|
// 5. Gridify if Desired
|
|
~grid = {
|
|
arg buffer, indices, redux_ds, action;
|
|
Routine{
|
|
var normer = FluidNormalize(s);
|
|
var grider = FluidGrid(s);
|
|
var newds = FluidDataSet(s);
|
|
|
|
s.sync;
|
|
|
|
normer.fitTransform(redux_ds,newds,{
|
|
"normalization done".postln;
|
|
grider.fitTransform(newds,newds,{
|
|
"grid done".postln;
|
|
action.(buffer,indices,newds);
|
|
});
|
|
});
|
|
}.play;
|
|
};
|
|
// 6. Plot
|
|
~plot = {
|
|
arg buffer, indices, redux_ds, action;
|
|
Routine{
|
|
var kdtree = FluidKDTree(s);
|
|
var buf_2d = Buffer.alloc(s,2);
|
|
var scaler = FluidNormalize(s);
|
|
var newds = FluidDataSet(s);
|
|
var xmin = 0, xmax = 1, ymin = 0, ymax = 1;
|
|
|
|
s.sync;
|
|
|
|
scaler.fitTransform(redux_ds,newds,{
|
|
"scaling done".postln;
|
|
kdtree.fit(newds,{
|
|
"kdtree fit".postln;
|
|
newds.dump({
|
|
arg dict;
|
|
var previous, fp;
|
|
"ds dumped".postln;
|
|
fp = FluidPlotter(nil,Rect(0,0,800,800),dict,xmin:xmin,xmax:xmax,ymin:ymin,ymax:ymax,mouseMoveAction:{
|
|
arg view, x, y;
|
|
[x,y].postln;
|
|
buf_2d.setn(0,[x,y]);
|
|
kdtree.kNearest(buf_2d,{
|
|
arg nearest;
|
|
if(previous != nearest,{
|
|
var index = nearest.asString.split($-)[1].asInteger;
|
|
previous = nearest;
|
|
nearest.postln;
|
|
index.postln;
|
|
{
|
|
var startPos = Index.kr(indices,index);
|
|
var dur_samps = Index.kr(indices,index + 1) - startPos;
|
|
var sig = PlayBuf.ar(1,buffer,BufRateScale.ir(buffer),startPos:startPos);
|
|
var dur_sec = dur_samps / BufSampleRate.ir(buffer);
|
|
var env = EnvGen.kr(Env([0,1,1,0],[0.03,dur_sec-0.06,0.03]),doneAction:2);
|
|
sig.dup * env;
|
|
}.play;
|
|
});
|
|
});
|
|
});
|
|
action.(fp,newds);
|
|
});
|
|
});
|
|
});
|
|
}.play;
|
|
};
|
|
)
|
|
|
|
~load_folder.("/Users/macprocomputer/Desktop/_flucoma/favs mono fewer/");
|
|
|
|
~slice.();
|
|
|
|
~indices.postln;
|
|
|
|
FluidWaveform(~loader.buffer,~indices);
|
|
|
|
~analyze.();
|
|
|
|
~umap.();
|
|
|
|
~grid.();
|
|
|
|
~plot.();
|
|
|
|
FluidLabelSet
|
|
|
|
// ============== do all of it =======================
|
|
(
|
|
var path = "/Users/macprocomputer/Desktop/_flucoma/data_saves/%_2D_browsing_Pitch".format(Date.localtime.stamp);
|
|
~load_folder.("/Users/macprocomputer/Desktop/_flucoma/favs mono/",{
|
|
arg buffer0;
|
|
~slice.(buffer0,{
|
|
arg buffer1, indices1;
|
|
~analyze.(buffer1, indices1,{
|
|
arg buffer2, indices2, ds2;
|
|
|
|
/* path.mkdir;
|
|
buffer2.write(path+/+"buffer.wav","wav");
|
|
indices2.write(path+/+"indices.wav","wav","float");
|
|
ds2.write(path+/+"ds.json");*/
|
|
|
|
~umap.(buffer2,indices2,ds2,{
|
|
arg buffer3, indices3, ds3;
|
|
|
|
/* path.mkdir;
|
|
buffer3.write(path+/+"buffer.wav","wav");
|
|
indices3.write(path+/+"indices.wav","wav","float");
|
|
ds3.write(path+/+"ds.json");*/
|
|
|
|
~plot.(buffer3,indices3,ds3,{
|
|
arg plotter;
|
|
"done with all".postln;
|
|
~fp = plotter;
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
)
|
|
|
|
/*=============== Know Your Data =================
|
|
|
|
hmmm... there's a lot of white space in that UMAP plot. A few options:
|
|
|
|
1. Adjust the parameters of UMAP to make the plot look different.
|
|
- minDist
|
|
- numNeighbours
|
|
2. Gridify the whole thing to spread it out.
|
|
3. Remove some of the outliers to get a more full shape.
|
|
|
|
===================================================*/
|
|
|
|
// #2
|
|
(
|
|
Window.closeAll;
|
|
Task{
|
|
var folder = "/Users/macprocomputer/Desktop/_flucoma/data_saves/211103_121441_2D_browsing/";
|
|
var ds = FluidDataSet(s);
|
|
var buffer = Buffer.read(s,folder+/+"buffer.wav");
|
|
var indices = Buffer.read(s,folder+/+"indices.wav");
|
|
var normalizer = FluidNormalize(s);
|
|
var ds_grid = FluidDataSet(s);
|
|
var grid = FluidGrid(s);
|
|
var kdtree = FluidKDTree(s);
|
|
var pt_buf = Buffer.alloc(s,2);
|
|
|
|
s.sync;
|
|
|
|
ds.read(folder+/+"ds.json",{
|
|
"read".postln;
|
|
normalizer.fitTransform(ds,ds_grid,{
|
|
"normalized".postln;
|
|
grid.fitTransform(ds_grid,ds_grid,{
|
|
"grid done".postln;
|
|
normalizer.fitTransform(ds_grid,ds_grid,{
|
|
"normalized".postln;
|
|
kdtree.fit(ds_grid,{
|
|
"tree fit".postln;
|
|
normalizer.fitTransform(ds,ds,{
|
|
"normalized".postln;
|
|
ds.dump({
|
|
arg ds_dict;
|
|
ds_grid.dump({
|
|
arg ds_grid_dict;
|
|
|
|
defer{
|
|
var distances = Dictionary.new;
|
|
var max_dist = 0;
|
|
var win, plotter, uv;
|
|
|
|
var previous;
|
|
ds_dict.at("data").keysValuesDo({
|
|
arg id, pt;
|
|
var other, pt0, pt1, dist, distpoint;
|
|
|
|
/*
|
|
id.postln;
|
|
pt.postln;
|
|
"".postln;
|
|
*/
|
|
|
|
other = ds_grid_dict.at("data").at(id);
|
|
pt0 = Point(pt[0],pt[1]);
|
|
pt1 = Point(other[0],other[1]);
|
|
dist = pt0.dist(pt1);
|
|
distpoint = Dictionary.new;
|
|
|
|
if(dist > max_dist,{max_dist = dist});
|
|
|
|
distpoint.put("pt0",pt0);
|
|
distpoint.put("pt1",pt1);
|
|
distpoint.put("dist",dist);
|
|
distances.put(id,distpoint);
|
|
});
|
|
win = Window("FluidGrid",Rect(0,0,800,800));
|
|
win.background_(Color.white);
|
|
uv = UserView(win,win.bounds)
|
|
.drawFunc_({
|
|
var size_pt = Point(uv.bounds.width,uv.bounds.height);
|
|
|
|
distances.keysValuesDo({
|
|
arg id, distpoint;
|
|
var alpha = distpoint.at("dist") / max_dist;
|
|
var pt0 = distpoint.at("pt0") * size_pt;
|
|
var pt1 = distpoint.at("pt1") * size_pt;
|
|
|
|
pt0.y = uv.bounds.height - pt0.y;
|
|
pt1.y = uv.bounds.height - pt1.y;
|
|
|
|
/* id.postln;
|
|
distpoint.postln;
|
|
alpha.postln;
|
|
"".postln;
|
|
*/
|
|
|
|
Pen.line(pt0,pt1);
|
|
Pen.color_(Color(1.0,0.0,0.0,0.25));
|
|
Pen.stroke;
|
|
});
|
|
});
|
|
|
|
plotter = FluidPlotter(win,win.bounds,ds_dict,{
|
|
arg view, x, y;
|
|
pt_buf.setn(0,[x,y]);
|
|
kdtree.kNearest(pt_buf,{
|
|
arg nearest;
|
|
if(previous != nearest,{
|
|
var index = nearest.asString.split($-)[1].asInteger;
|
|
previous = nearest;
|
|
nearest.postln;
|
|
index.postln;
|
|
{
|
|
var startPos = Index.kr(indices,index);
|
|
var dur_samps = Index.kr(indices,index + 1) - startPos;
|
|
var sig = PlayBuf.ar(1,buffer,BufRateScale.ir(buffer),startPos:startPos);
|
|
var dur_sec = dur_samps / BufSampleRate.ir(buffer);
|
|
var env = EnvGen.kr(Env([0,1,1,0],[0.03,dur_sec-0.06,0.03]),doneAction:2);
|
|
sig.dup * env;
|
|
}.play;
|
|
});
|
|
});
|
|
});
|
|
plotter.background_(Color(0,0,0,0));
|
|
|
|
ds_grid_dict.at("data").keysValuesDo({
|
|
arg id, pt;
|
|
plotter.addPoint_("%-grid".format(id),pt[0],pt[1],0.75,Color.blue.alpha_(0.5));
|
|
});
|
|
|
|
win.front;
|
|
};
|
|
})
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
}.play(AppClock);
|
|
)
|
|
|
|
// #3
|
|
(
|
|
Routine{
|
|
var folder = "/Users/macprocomputer/Desktop/_flucoma/data_saves/211103_152523_2D_browsing/";
|
|
var ds = FluidDataSet(s);
|
|
var buffer = Buffer.read(s,folder+/+"buffer.wav");
|
|
var indices = Buffer.read(s,folder+/+"indices.wav");
|
|
var robust_scaler = FluidRobustScale(s,10,90);
|
|
var newds = FluidDataSet(s);
|
|
var dsq = FluidDataSetQuery(s);
|
|
s.sync;
|
|
|
|
// {indices.plot}.defer;
|
|
ds.read(folder+/+"ds.json",{
|
|
robust_scaler.fitTransform(ds,newds,{
|
|
dsq.addRange(0,2,{
|
|
dsq.filter(0,">",-1,{
|
|
dsq.and(0,"<",1,{
|
|
dsq.and(1,">",-1,{
|
|
dsq.and(1,"<",1,{
|
|
dsq.transform(newds,newds,{
|
|
~plot.(buffer,indices,newds);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
})
|
|
});
|
|
}.play;
|
|
) |