PV_ExtractRepeat extract a repeating loop out from audio

PV_ExtractRepeat(chain, loopbuf, loopdur, memorytime, which=0, ffthop=0.5, thresh=1)

If you have a signal that consists of some fixed looping audio (e.g. a beat) plus some varying content (e.g. singing), this UGen uses a simple binary-masking technique to try and separate the looping bit from the non-looping bit. The quality of the separation is quite rough, but useful in some circumstances.

Note that this unit estimates the loop characteristics online in real time, meaning it takes a few times through the loop before the separation really kicks in. This means that at any point, any novel element is included in the nonrepeating part, even if it's really a loop that's starting.

You must know the loop duration - this unit will not estimate it for you.

chain - an fft chain

loopbuf - a buffer where data about the loop is calculated/stored. num frames should be enough to hold the loop (you'll get a warning if not), num channels should be (fftsize/2 + 1).

loopdur - duration in seconds of the bit you want extracted. (You can change the loop duration on-the-fly but you'll get some unhelpful results while the unit settles in to the new loop duration.)

memorytime - how quickly (in seconds) the recursive estimation converges

which - set to 0 to extract the loop, set to 1 to extract everything else

ffthop - this should match the hop size used in the FFT. typically 0.5.

thresh - threshold for allocating bins to repeating/nonrepeating. Default is 1, and raising it means more gets allocated to the repeating part.

Example

In this example we create definite looping and non-looping stuff using some synthetic material, but you might find it more interesting to use DiskIn to read in some dance music...

s.boot

// Create audio containing repeating and varying components, merged in the same channel:

(

x = {

var trigs, looplen = 2, loopy, varying;

trigs = Impulse.kr(6/looplen) + Impulse.kr(4/looplen);

loopy = BPF.ar(WhiteNoise.ar * EnvGen.ar(Env.perc(0.01, 0.3), trigs), LFCub.kr(1/looplen).exprange(100, 5000));

varying = Pulse.ar(LFNoise0.kr(6/looplen).exprange(100, 500).cpsmidi.round.midicps) * 0.1;

(loopy + varying).dup

}.play;

)

// Now the thing that will attempt to separate them out again (inc a buffer for it to use):

~loopbuf = Buffer.alloc(s, 200, 513);

(

y = { |which=1, active=1|

var son = In.ar(0);

var chain = FFT(LocalBuf(1024), son);

chain = PV_ExtractRepeat(chain, ~loopbuf, 2, memorytime:30, which:which);

ReplaceOut.ar(0, Select.ar(active, [son, IFFT(chain)]).dup);

}.play(x, addAction: \addAfter);

)

y.set(\which, 0) // focus on the nonrepeating bit

y.set(\which, 1) // focus on the repeating bit

y.set(\active, 0) // back to normal

y.set(\active, 1) // filter it again

y.free;

x.free;

//////////////////////////////////////

// With music:

~track = "~/tmpwavs/Postal Service - Such Great Heights.mp3.2.wav".standardizePath; ~bpm=116.6;

~track = "~/tmpwavs/Amy Winehouse - Rehab.mp3.wav".standardizePath; ~bpm=145.1;

~looplen = 480/~bpm;

b = Buffer.cueSoundFile(s, ~track, 0, 2);

x = { DiskIn.ar(2, b) }.play;

// Now the thing that will attempt to separate them out again (inc a buffer for it to use):

~loopbuf = Buffer.alloc(s, 1000, 513);

(

y = { |which=1, active=1, thresh=1|

var son = In.ar(0);

var chain = FFT(LocalBuf(1024), son);

chain = PV_ExtractRepeat(chain, ~loopbuf, ~looplen, memorytime:30, which:which, thresh:thresh);

ReplaceOut.ar(0, Select.ar(active, [son, IFFT(chain)]).dup);

}.play(x, addAction: \addAfter);

)

y.set(\which, 0) // focus on the nonrepeating bit

y.set(\which, 1) // focus on the repeating bit

y.set(\active, 0) // back to normal

y.set(\active, 1) // filter it again

y.set(\which, 0, \thresh, 1.5) // trying a higher threshold

y.free;

x.free;

b.close

Based on the technique presented in this paper (but different - adapted for online estimation and with some other little differences):

Zafar Rafii and Bryan Pardo. "A Simple Music/Voice Separation Method based on the Extraction of the Repeating Musical Structure," 36th International Conference on Acoustics, Speech and Signal Processing (ICASSP 2011), Prague, Czech Republic, May 22-27, 2011.

http://www.cs.northwestern.edu/~zra446/research.html