diff --git a/release-packaging/HelpSource/Classes/FluidAmpSlice.schelp b/release-packaging/HelpSource/Classes/FluidAmpSlice.schelp index 82af2ee..f1098d0 100644 --- a/release-packaging/HelpSource/Classes/FluidAmpSlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidAmpSlice.schelp @@ -51,112 +51,35 @@ RETURNS:: EXAMPLES:: code:: -//basic tests: absThresh sanity +// detrending explained +// the source is a sinewave that does not go to silence and has sharp-ish amplitude bumps as onsets we try to track ( -{var env, source = SinOsc.ar(320,0,LFTri.ar(10).abs); - env = FluidAmpSlice.ar(source,absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12); - [source, env] -}.plot(0.1); -) -//basic tests: absThresh hysteresis -( -{var env, source = SinOsc.ar(320,0,LFTri.ar(10).abs); - env = FluidAmpSlice.ar(source,absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -16); - [source, env] -}.plot(0.1); -) -//basic tests: absThresh min slice -( -{var env, source = SinOsc.ar(320,0,LFTri.ar(10).abs); - env = FluidAmpSlice.ar(source,absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12, minSliceLength:441); - [source, env] -}.plot(0.1); -) -//basic tests: absThresh min silence -( -{var env, source = SinOsc.ar(320,0,LFTri.ar(10).abs); - env = FluidAmpSlice.ar(source,absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12, minSilenceLength:441); - [source, env] -}.plot(0.1); -) -//mid tests: absThresh time hysteresis on -( -{var env, source = SinOsc.ar(320,0,LFTri.ar(10).abs); - env = FluidAmpSlice.ar(source,absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12, minLengthAbove:441); - [DelayN.ar(source,0.1,441/44100), env] -}.plot(0.1); -) -//mid tests: absThresh time hysteresis off -( -{var env, source = SinOsc.ar(320,0,LFTri.ar(10).abs); - env = FluidAmpSlice.ar(source,absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12, minLengthBelow:441); - [DelayN.ar(source,0.1,441/44100), env] -}.plot(0.1); -) -//mid tests: absThresh with lookBack -( -{var env, source = SinOsc.ar(320,0,LFTri.ar(10).abs); - env = FluidAmpSlice.ar(source,absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12,lookBack:441); - [DelayN.ar(source,0.1,441/44100), env] -}.plot(0.1); -) -//mid tests: absThresh with lookAhead -( -{var env, source = SinOsc.ar(320,0,LFTri.ar(10).abs); - env = FluidAmpSlice.ar(source,absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12,lookAhead:441); - [DelayN.ar(source,0.1,441/44100), env] -}.plot(0.1); -) -//mid tests: absThresh with asymetrical lookBack and lookAhead -( -{var env, source = SinOsc.ar(320,0,LFTri.ar(10).abs); - env = FluidAmpSlice.ar(source,absRampUp:5, absRampDown:50, absThreshOn:-12, absThreshOff: -12,lookBack:221, lookAhead:441); - [DelayN.ar(source,0.1,441/44100), env] -}.plot(0.1); -) -//advanced tests: absThresh hysteresis, long tail -( -{var env, source = SinOsc.ar(320,0,LFTri.ar(10).abs); - env = FluidAmpSlice.ar(source,absRampUp:220, absRampDown:220, absThreshOn:-60, absThreshOff: -70); - [source, env] -}.plot(0.1); -) -//solution: have to recut with relThresh -( -{var env, source = SinOsc.ar(320,0,LFTri.ar(10).abs); - env = FluidAmpSlice.ar(source,absRampUp:220, absRampDown:220, absThreshOn:-60, absThreshOff: -70, relRampUp:5, relRampDown:200, relThreshOn:1, relThreshOff:0); +{var env, source = SinOsc.ar(320,0,LFSaw.ar(20,0, -0.4, 0.6)); + env = FluidAmpSlice.ar(source,fastRampUp: 5,fastRampDown: 50,slowRampUp: 220,slowRampDown: 220, onThreshold: 10, offThreshold: 10,floor: -60); [source, env] }.plot(0.08); ) -//beware of double trig +//beware of double trigger at the begining of the 2nd cycle above). A solution: Schmidth triggers ( -{var env, source = SinOsc.ar(320,0,LFTri.ar(10).abs); - env = FluidAmpSlice.ar(source,absRampUp:220, absRampDown:220, absThreshOn:-60, absThreshOff: -70, relRampUp:5, relRampDown:200, relThreshOn:1, relThreshOff:0); +{var env, source = SinOsc.ar(320,0,LFSaw.ar(20,0, -0.4, 0.6)); + env = FluidAmpSlice.ar(source,fastRampUp: 5,fastRampDown: 50,slowRampUp: 220,slowRampDown: 220, onThreshold: 10, offThreshold: 7,floor: -60); [source, env] -}.plot(0.005); +}.plot(0.08); ) -//a solution: minSliceLength +// another solution: minslicelength ( -{var env, source = SinOsc.ar(320,0,LFTri.ar(10).abs); - env = FluidAmpSlice.ar(source,absRampUp:220, absRampDown:220, absThreshOn:-60, absThreshOff: -70, relRampUp:5, relRampDown:200, relThreshOn:1, relThreshOff:0, minSliceLength:2205); +{var env, source = SinOsc.ar(320,0,LFSaw.ar(20,0, -0.4, 0.6)); + env = FluidAmpSlice.ar(source,fastRampUp: 5,fastRampDown: 50,slowRampUp: 220,slowRampDown: 220, onThreshold: 10, offThreshold: 7,floor: -60, minSliceLength: 220); [source, env] -}.plot(0.005); +}.plot(0.08); ) -//drum slicing, many ways +//quick drum onsets //load a buffer b = Buffer.read(s,File.realpath(FluidAmpSlice.class.filenameSymbol).dirname.withTrailingSlash ++ "../AudioFiles/Nicol-LoopE-M.wav"); -//have fun with a gate (explore lookahead and lookback, but correct for latency) ( {var env, source = PlayBuf.ar(1,b); - env = FluidAmpSlice.ar(source,absRampUp:1103, absRampDown:2205, absThreshOn:-27, absThreshOff: -31, minSilenceLength:1100, lookBack:441, highPassFreq:40); - [DelayN.ar(source,delaytime:441/44100), env] -}.plot(2,separately:true); -) - -( -{var env, source = PlayBuf.ar(1,b, loop:1); - env = FluidAmpSlice.ar(source, absRampUp:4410, absRampDown:4410, absThreshOn:-60, absThreshOff: -70, relRampUp:10, relRampDown:2205, relThreshOn:12, relThreshOff:9, minSilenceLength:4410, highPassFreq:20); - [source, Trig.ar(env,0)] + env = FluidAmpSlice.ar(source,fastRampUp: 10,fastRampDown: 2205,slowRampUp: 4410,slowRampDown: 4410,onThreshold: 10,offThreshold: 5,floor: -40,minSliceLength: 4410,highPassFreq: 20); + [source, env] }.play; ) :: diff --git a/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp b/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp index 9777088..7221343 100644 --- a/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp @@ -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 hysteresis -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 triggers +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;}) ::