@ -76,73 +76,30 @@ RETURNS::
EXAMPLES::
code::
// detrending explained
// define a test signal and a destination buffer
(
b = Buffer.sendCollection(s, Array.fill(44100,{|i| sin(i*pi/ (44100/640)) * (sin(i*pi/ 22050)).abs }));
b = Buffer.sendCollection(s, Array.fill(44100,{|i| sin(i*pi/ (44100/640)) * ((((35000-i)/30000)%0.8) + 0.2) }));
c = Buffer.new(s);
)
// the source is a sinewave that does not go to silence and has sharp-ish amplitude bumps as onsets we try to track
b.play
b.plot
//basic tests: absThresh sanity
FluidBufAmpSlice.process(s,b,indices:c, absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12)
//
FluidBufAmpSlice.process(s, b,indices: c,fastRampUp: 5,fastRampDown: 50,slowRampUp: 220,slowRampDown: 220, onThreshold: 10, offThreshold: 10,floor: -60);
c.query
c.getn(0,c.numFrames*2 ,{|item|item.postln;})
c.getn(0,c.numFrames,{|item|item.postln;})
//basic tests: absThresh hysteresi s
FluidBufAmpSlice.process(s,b,indices:c, absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -16)
//beware of multiple triggers at the begining of the 2nd cycle above). A solution: Schmidth trigger s
FluidBufAmpSlice.process(s, b,indices: c,fastRampUp: 5,fastRampDown: 50,slowRampUp: 220,slowRampDown: 220, onThreshold: 10, offThreshold: 7,floor: -60);
c.query
c.getn(0,c.numFrames*2 ,{|item|item.postln;})
c.getn(0,c.numFrames,{|item|item.postln;})
//basic tests: absThresh min slice
FluidBufAmpSlice.process(s,b,indices:c, absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12, minSliceLength:441)
// we got most of them sorted, but there is another solution: minslicelength
FluidBufAmpSlice.process(s, b,indices: c,fastRampUp: 5,fastRampDown: 50,slowRampUp: 220,slowRampDown: 220, onThreshold: 10, offThreshold: 7,floor: -60, minSliceLength: 500);
c.query
c.getn(0,c.numFrames*2,{|item|item.postln;})
//basic tests: absThresh min silence
FluidBufAmpSlice.process(s,b,indices:c, absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12, minSilenceLength:441)
c.query
c.getn(0,c.numFrames*2,{|item|item.postln;})
//mid tests: absThresh time hysteresis on
FluidBufAmpSlice.process(s,b,indices:c, absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12, minLengthAbove:441)
c.query
c.getn(0,c.numFrames*2,{|item|item.postln;})
//mid tests: absThresh time hysteresis off
FluidBufAmpSlice.process(s,b,indices:c, absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12, minLengthBelow:441)
c.query
c.getn(0,c.numFrames*2,{|item|item.postln;})
//mid tests: absThresh with lookBack
FluidBufAmpSlice.process(s,b,indices:c, absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12, lookBack:441)
c.query
c.getn(0,c.numFrames*2,{|item|item.postln;})
//mid tests: absThresh with lookAhead
FluidBufAmpSlice.process(s,b,indices:c, absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12, lookAhead:441)
c.query
c.getn(0,c.numFrames*2,{|item|item.postln;})
//mid tests: absThresh with asymetrical lookBack and lookAhead
FluidBufAmpSlice.process(s,b,indices:c, absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12, lookBack:221, lookAhead:441)
c.query
c.getn(0,c.numFrames*2,{|item|item.postln;})
//advanced tests: absThresh hysteresis, long tail
FluidBufAmpSlice.process(s,b,indices:c, absRampUp:2205, absRampDown:2205, absThreshOn:-60, absThreshOff: -70)
c.query
c.getn(0,c.numFrames*2,{|item|item.postln;})
//solution: have to recut with relThresh
FluidBufAmpSlice.process(s,b,indices:c, absRampUp:2205, absRampDown:2205, absThreshOn:-60, absThreshOff: -70, relRampUp:5, relRampDown:220, relThreshOn:-1, relThreshOff:-2)
c.query
c.getn(0,c.numFrames*2,{|item|item.postln;})
//beware of double trig. a solution: minSliceLength
FluidBufAmpSlice.process(s,b,indices:c, absRampUp:2205, absRampDown:2205, absThreshOn:-60, absThreshOff: -70, relRampUp:5, relRampDown:220, relThreshOn:-1, relThreshOff:-2, minSliceLength:2205)
c.query
c.getn(0,c.numFrames*2,{|item|item.postln;})
c.getn(0,c.numFrames,{|item|item.postln;})
::
STRONG::A musical example.::
@ -154,25 +111,22 @@ c = Buffer.new(s);
)
// slice the samples
FluidBufAmpSlice.process(s,b,indices:c, absRampUp:4410, absRampDown:4410, absThreshOn:-60, absThreshOff: -70, relRampUp:10, relRampDown:2205, relThreshOn:13, relThreshOff:10, minSliceLength:4410, highPassFreq:20)
FluidBufAmpSlice.process(s,b,indices:c,fastRampUp: 10,fastRampDown: 2205,slowRampUp: 4410,slowRampDown: 4410,onThreshold: 10,offThreshold: 5,floor: -40,minSliceLength: 4410,highPassFreq: 20);
c.query
c.getn(0,c.numFrames*2,{|item|item.postln;})
//reformatting to read the onsets and offsets as pairs
c.getn(0,c.numFrames*2,{|items|items.reshape(c.numFrames,2).do({|x| x.postln});})
c.getn(0,c.numFrames,{|item|item.postln;})
//loops over a splice with the MouseX, taking the respective onset and offset of a given slice
(
{
BufRd.ar(1, b,
Phasor.ar(0,1,
BufRd.kr(2, c,
MouseX.kr(0, BufFrames.kr(c)), 0, 1)[0],
BufRd.kr(2, c,
MouseX.kr(1, BufFrames.kr(c)), 0, 1)[1],
BufRd.kr(2,c,
MouseX.kr(0, BufFrames.kr(c)), 0, 1)[0]
), 0, 1);
}.play;
BufRd.ar(1, b,
Phasor.ar(0,1,
BufRd.kr(1, c,
MouseX.kr(0, BufFrames.kr(c) - 1), 0, 1),
BufRd.kr(1, c,
MouseX.kr(1, BufFrames.kr(c)), 0, 1),
BufRd.kr(1,c,
MouseX.kr(0, BufFrames.kr(c) - 1), 0, 1)), 0, 1);
}.play;
)
::
@ -193,13 +147,11 @@ c = Buffer.new(s);
// with basic params
Routine{
t = Main.elapsedTime;
FluidBufAmpSlice.process(s,b, indices: c, absRampUp:1, absRampDown:20 );
FluidBufAmpSlice.process(s,b, indices: c, fastRampUp: 10,fastRampDown: 2205,slowRampUp: 4410,slowRampDown: 4410, onThreshold: 10,offThreshold: 5 );
(Main.elapsedTime - t).postln;
}.play
)
// list the indicies of detected attacks - the two input channels have been summed. The two channels of the output, respectively onset and offset indices, are interleaved as this is the SuperCollider buffer data formatting
c.getn(0,c.numFrames*2,{|item|item.postln;})
// a more readable version: deinterleave onsetand offset
c.getn(0,c.numFrames*2,{|items|items.reshape(c.numFrames,2).do({|x| x.postln});})
// list the indicies of detected attacks - the two input channels have been summed.
c.getn(0,c.numFrames,{|item|item.postln;})
::