Merge branch 'FluidWaveform-overlays' into dev

nix
Ted Moore 4 years ago
commit 8c63d3532f

@ -16,8 +16,8 @@ FluidPlotterPoint {
} }
} }
FluidPlotter { FluidPlotter : FluidViewer {
var <parent, <userView, <xmin, <xmax, <ymin, <ymax, <pointSize = 6, pointSizeScale = 1, dict_internal, <dict, shape = \circle, catColors, highlightIdentifier; var <parent, <userView, <xmin, <xmax, <ymin, <ymax, <pointSize = 6, pointSizeScale = 1, dict_internal, <dict, shape = \circle, highlightIdentifier;
*new { *new {
arg parent, bounds, dict, mouseMoveAction,xmin = 0,xmax = 1,ymin = 0,ymax = 1; arg parent, bounds, dict, mouseMoveAction,xmin = 0,xmax = 1,ymin = 0,ymax = 1;
@ -33,22 +33,12 @@ FluidPlotter {
ymin = ymin_; ymin = ymin_;
ymax = ymax_; ymax = ymax_;
this.createCatColors; this.createcategoryColors;
dict_internal = Dictionary.new; dict_internal = Dictionary.new;
if(dict_.notNil,{this.dict_(dict_)}); if(dict_.notNil,{this.dict_(dict_)});
this.createPlotWindow(bounds,parent_,mouseMoveAction,dict_); this.createPlotWindow(bounds,parent_,mouseMoveAction,dict_);
} }
createCatColors {
catColors = "1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf".clump(6).collect{
arg six;
Color(*six.clump(2).collect{
arg two;
"0x%".format(two).interpret / 255;
});
};
}
categories_ { categories_ {
arg labelSetDict; arg labelSetDict;
if(dict_internal.size != 0,{ if(dict_internal.size != 0,{
@ -67,11 +57,11 @@ FluidPlotter {
category_int = label_to_int.at(category_string); category_int = label_to_int.at(category_string);
if(category_int > (catColors.size-1),{ if(category_int > (categoryColors.size-1),{
"FluidPlotter:setCategories_ FluidPlotter doesn't have that many category colors. You can use the method 'setColor_' to set colors for individual points.".warn "FluidPlotter:setCategories_ FluidPlotter doesn't have that many category colors. You can use the method 'setColor_' to set colors for individual points.".warn
}); });
color = catColors[category_int]; color = categoryColors[category_int];
fp_pt.color_(color); fp_pt.color_(color);
}); });
this.refresh; this.refresh;

@ -1,15 +1,31 @@
FluidWaveform { FluidViewer {
var categoryColors;
createCatColors {
categoryColors = "1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf".clump(6).collect{
arg six;
Color(*six.clump(2).collect{
arg two;
"0x%".format(two).interpret / 255;
});
};
}
}
FluidWaveform : FluidViewer {
*new { *new {
arg audio_buf, slices_buf, bounds; arg audio_buf, slices_buf, feature_buf, bounds, lineWidth = 1;
^super.new.init(audio_buf,slices_buf, bounds); ^super.new.init(audio_buf,slices_buf, feature_buf, bounds, lineWidth);
} }
init { init {
arg audio_buf, slices_buf, bounds; arg audio_buf, slices_buf, feature_buf, bounds, lineWidth;
Task{ Task{
var path = "%%_%_FluidWaveform.wav".format(PathName.tmp,Date.localtime.stamp,UniqueID.next); var path = "%%_%_FluidWaveform.wav".format(PathName.tmp,Date.localtime.stamp,UniqueID.next);
var sfv, win, userView; var sfv, win, categoryCounter = 0;
this.createCatColors;
bounds = bounds ? Rect(0,0,800,200); bounds = bounds ? Rect(0,0,800,200);
win = Window("FluidWaveform",bounds); win = Window("FluidWaveform",bounds);
@ -18,26 +34,77 @@ FluidWaveform {
audio_buf.server.sync; audio_buf.server.sync;
sfv = SoundFileView(win,Rect(0,0,bounds.width,bounds.height)); sfv = SoundFileView(win,Rect(0,0,bounds.width,bounds.height));
sfv.peakColor_(Color(*0.75.dup(3)));
sfv.rmsColor_(Color.black);
sfv.background_(Color.white);
sfv.readFile(SoundFile(path)); sfv.readFile(SoundFile(path));
sfv.gridOn_(false); sfv.gridOn_(false);
File.delete(path); File.delete(path);
if(slices_buf.notNil,{ if(slices_buf.notNil,{
slices_buf.loadToFloatArray(action:{ slices_buf.numChannels.switch(
arg slices_fa; 1,{
slices_buf.loadToFloatArray(action:{
userView = UserView(win,Rect(0,0,bounds.width,bounds.height)) arg slices_fa;
.drawFunc_({ UserView(win,Rect(0,0,bounds.width,bounds.height))
slices_fa.do{ .drawFunc_({
arg start_samp; Pen.width_(lineWidth);
var x = start_samp.linlin(0,audio_buf.numFrames,0,bounds.width); slices_fa.do{
Pen.line(Point(x,0),Point(x,bounds.height)); arg start_samp;
Pen.color_(Color.red); var x = start_samp.linlin(0,audio_buf.numFrames,0,bounds.width);
Pen.line(Point(x,0),Point(x,bounds.height));
Pen.color_(categoryColors[categoryCounter]);
Pen.stroke;
};
categoryCounter = categoryCounter + 1;
});
});
},
2,{
slices_buf.loadToFloatArray(action:{
arg slices_fa;
slices_fa = slices_fa.clump(2);
UserView(win,Rect(0,0,bounds.width,bounds.height))
.drawFunc_({
Pen.width_(lineWidth);
slices_fa.do{
arg arr;
var start = arr[0].linlin(0,audio_buf.numFrames,0,bounds.width);
var end = arr[1].linlin(0,audio_buf.numFrames,0,bounds.width);
Pen.addRect(Rect(start,0,end-start,bounds.height));
Pen.color_(categoryColors[categoryCounter].alpha_(0.25));
Pen.fill;
};
categoryCounter = categoryCounter + 1;
});
});
},{
"FluidWaveform - indices_buf has neither 1 nor 2 channels. Not sure what to do with this.".warn;
}
);
});
if(feature_buf.notNil,{
feature_buf.loadToFloatArray(action:{
arg fa;
fa = fa.clump(feature_buf.numChannels).flop;
fa.do({
arg channel;
channel = channel.resamp1(bounds.width).linlin(channel.minItem,channel.maxItem,bounds.height,0);
UserView(win,Rect(0,0,bounds.width,bounds.height))
.drawFunc_({
Pen.moveTo(Point(0,channel[0]));
channel[1..].do{
arg val, i;
Pen.lineTo(Point(i+1,val));
};
Pen.color_(categoryColors[categoryCounter]);
categoryCounter = categoryCounter + 1;
Pen.stroke; Pen.stroke;
}; });
}); });
}); })
}); });
win.front; win.front;

@ -29,6 +29,7 @@ EXAMPLES::
code:: code::
s.boot;
// load a sound to slice // load a sound to slice
~drums = Buffer.read(s,File.realpath(FluidBufAmpSlice.class.filenameSymbol).dirname.withTrailingSlash ++ "../AudioFiles/Nicol-LoopE-M.wav"); ~drums = Buffer.read(s,File.realpath(FluidBufAmpSlice.class.filenameSymbol).dirname.withTrailingSlash ++ "../AudioFiles/Nicol-LoopE-M.wav");
@ -39,5 +40,24 @@ code::
FluidBufAmpSlice.process(s,~drums,indices:~indices,fastRampUp: 10,fastRampDown: 2205,slowRampUp: 4410,slowRampDown: 4410,onThreshold: 10,offThreshold: 5,floor: -40,minSliceLength: 4410,highPassFreq: 20); FluidBufAmpSlice.process(s,~drums,indices:~indices,fastRampUp: 10,fastRampDown: 2205,slowRampUp: 4410,slowRampDown: 4410,onThreshold: 10,offThreshold: 5,floor: -40,minSliceLength: 4410,highPassFreq: 20);
// plot the buffer with the indices overlayed // plot the buffer with the indices overlayed
FluidWaveform(~drums,~indices,Rect(0,0,800,200)); FluidWaveform(~drums,~indices,nil,Rect(0,0,800,200));
// do a descriptor analysis
~features = Buffer(s);
FluidBufLoudness.process(s,~drums,features:~features,action:{"done".postln;});
// copy just the first channel of that buffer to display it
~features2 = Buffer(s);
FluidBufCompose.process(s,~features,numChans:1,destination:~features2);
// plot the audio with the slices and the loudness analysis
FluidWaveform(~drums,~indices,~features2,Rect(0,0,1200,300));
// with gate info
~gate_analysis = Buffer(s);
FluidBufAmpGate.process(s,~drums,indices:~gate_analysis,onThreshold:-35,offThreshold:-35,minSliceLength:4410);
// it will plot the ons and offs
FluidWaveform(~drums,~gate_analysis,~features2,Rect(0,0,1200,300));
:: ::

Loading…
Cancel
Save