Hi all -
I was hoping to clarify a few things about basic slicing for myself today.
I am currently experimenting with basic slicers like FluidBufAmpGate
and FluidBufOnsetSlice
. These essentially slice the entirety of a source file, based on the distance between index points, defined by a registered dynamic change.
Due to the approach, there seems to be a lot of “extra” information. For instance, if I use FluidBufGate
, I will get slices where the amplitude is above the onThreshold
until it drops below offThreshold
- that’s what I want! But I will also get I will get slices where the amplitude is below the offThreshold
until it exceeds the onThreshold
- maybe I don’t want those so much.
In the case of the onset slice, I’m getting all of the sound between one onset and the next onset.
Is there a way to use these slicers to only extract the onset or the positive gate? Or does that require additional analysis and a following stage of sorting those results? Am I misunderstanding something about slicing?
Thanks for all the help!
//basic test slicer
(
~slicer = {|mainBuf|
var indices = Buffer(s);
FluidBufAmpGate.processBlocking(s, mainBuf,
onThreshold: -10,
offThreshold: -50,
minSliceLength: 500,
indices:indices,
action:{|array|
indices.loadToFloatArray(action:{ |array|
array = array.clump(2);
array.do{
arg arr, i, x;
var saveBuffer = Buffer(s);
var startFrame = arr[0];
var numFrames = arr[1] - startFrame;
var ampAnalysis;
FluidBufCompose.processBlocking(s, mainBuf,
startFrame,
numFrames,
destination:saveBuffer,
destStartFrame:0,
action:{
saveBuffer.write(
"/Users/a/Desktop/untitled folder/"++i++".aif",
numFrames:numFrames, startFrame:0); }); //numFrames/startFrame for newBuffer
};
});
"found % slice points".format(indices.numFrames).postln;
"average duration per slice: %".format(mainBuf.duration (indices.numFrames+1)).postln;
});
};
)
Maybe I’m missing something, but just eyeballing your code, I don’t think you’ll get the slices you describe here. Can you show us some examples (maybe with FluidWaveform?) to clarify the issue?
Oh ok - yes, I see now that the slicer is doing everything it should be - but I am still at a little bit of a loss for how to apply analysis to the sliced information.
In the following example, I’m using the "Nicol-LoopE-M.wav"
drum loop to standardize the question. The idea is that I’d like to slice a file and then use FluidAmpFeature to only preserve slices within a certain decibel range. I think I am close - but I seem to have found some trouble with the final FluidBufCompose. It is pulling the previously indexed times and creating gaps for the areas that have been omitted…
Any advice on “best practices” for writing this code would also be appreciated…
Thanks!
(
~slicer = {|mainBuf|
var indices = Buffer(s);
var final = Buffer(s);
var new=[];
FluidBufAmpGate.processBlocking(s, mainBuf,
onThreshold: -10,
offThreshold: -30,
minSliceLength: 800,
indices:indices,
action:{|array|
{FluidWaveform(mainBuf,indices)}.defer;
indices.loadToFloatArray(action:{ |array|
array = array.clump(2);
array.do{
arg arr, i, x;
var sliceStats = Buffer(s);
var featBuffer = Buffer(s);
var startFrame = arr[0];
var numFrames = arr[1] - startFrame;
FluidBufAmpFeature.processBlocking(s,
source: mainBuf,
features: featBuffer,
startFrame: startFrame,
numFrames: numFrames);
FluidBufStats.processBlocking(s,
source:featBuffer,
stats:sliceStats,
select: [\mean],
numChans:1);
sliceStats.loadToFloatArray(action:{|m, index|
if ((m[0]>6) && (m[0]>10)){
FluidBufCompose.processBlocking(s,
source: mainBuf,
destination: final,
destStartFrame: startFrame,
startFrame: startFrame,
numFrames: numFrames)}});
}
})
});
~f = final;
};
);
~z=Buffer.read(s, FluidFilesPath("Nicol-LoopE-M.wav"));
~o=~slicer.(~z);
Well, I suppose this is one way to do it - although, I think I am still curious about what is “common vernacular.” I imagine there are better ways.
I think one obvious thing is: I can’t change the sliceStats
logic without running all of the code again, due to the intricately nested way this all seems to work.
(
~slicer = {|mainBuf|
var indices = Buffer(s);
var final = Buffer(s);
var counter = 0;
FluidBufAmpGate.processBlocking(s, mainBuf,
onThreshold: -10,
offThreshold: -30,
minSliceLength: 800,
indices:indices,
action:{|array|
{FluidWaveform(mainBuf,indices)}.defer;
indices.loadToFloatArray(action:{ |array|
array = array.clump(2);
array.do{
arg arr, i, x;
var saveBuffer = Buffer(s);
var featBuffer = Buffer(s);
var sliceStats = Buffer(s);
var startFrame = arr[0];
var numFrames = arr[1] - startFrame;
var ampAnalysis;
FluidBufAmpFeature.processBlocking(s,
source: mainBuf,
features: featBuffer,
startFrame: startFrame,
numFrames: numFrames);
FluidBufStats.processBlocking(s,
source:featBuffer,
stats:sliceStats,
select: [\mean],
numChans:1,
action: {
sliceStats.loadToFloatArray(action:{|m|
if ((m[0]>2) && (m[0]<12)) {
FluidBufCompose.processBlocking(
s,
source: mainBuf,
startFrame: startFrame,
numFrames: numFrames,
destination: final,
destStartFrame: counter)};
counter = counter+numFrames;
~f = final;
})
});
}});
});
indices;
};
)