PolyPitch Polyphonic pitch tracker

PolyPitch.ar(input, maxvoices=4,levelcompressionfactor=(-0.1),mixleftterm=4.0,torprec=0.0000001,cancellationweight=1.0,polyphonyestimategamma=0.66)

Polyphonic pitch tracker implementing:

Anssi Klapuri (2008) Multipitch analysis of polyphonic music and speech signals using an auditory model. IEEE Transactions on Audio, Speech, and Language Processing 16(2): 255-266

The UGen returns an array of outputs in the format:

[numberofvoicesdetected, frequency in Hz of voice 1, salience of voice 1, frequency of voice 2, salience of voice 2, ...]

The parameter set-up is quite delicate, but some parameters from the paper are made available. The UGen requires sampling rate of 44100, and 64 sample blocksize.

The current codebase uses libsamplerate internally (http://www.mega-nerd.com/SRC/), by Erik de Castro Lopo. The FFT implementation is also currently based on Mac specific Accelerate library code.

input - input signal

maxvoices -Maximum polyphony tracked.

levelcompressionfactor -Equation (5) in the paper, this value is v-1

mixleftterm -Sets relative weight of left term in equation (10), that is, stigma in equation (11). Klapuri notes that high values here are fine for non-drum signals, but drum signals may require more noise robust frontend via a lower mixleftterm.

torprec - Precision of search in Algorithm 1 (p. 260)

cancellationweight -d in Table 1, p.261

polyphonyestimategamma -gamma in equation (17)

(

{

var in, tracked;

//in = Mix(SinOsc.ar([440,990,775],0,0.1));

in = Mix(Saw.ar([440,990,775],0.1));

//in= SoundIn.ar;

tracked=PolyPitch.kr(in,6,-0.1,10.0);

tracked.poll;

//Out.ar(0,Pan2.ar(in));

}.play

)

(

{

var in, tracked;

in= SoundIn.ar;

tracked=PolyPitch.kr(in,6,-0.1,10.0);

SendReply.kr(Impulse.kr(44100/2048),'polyparam',tracked);

}.play

)

(

SynthDef(\ppsine,{arg amp=0.0, freq= 440,pan=0.0;

Out.ar(0,Pan2.ar(Saw.ar(freq.lag(0.01),amp.lag(0.01)),pan))

}).add;

)

(

b = Array.fill(6,{Synth(\ppsine)})

)

(

var count= 0;

o.remove;

o = OSCresponder(nil, 'polyparam', { |t, r, msg|

var numvoices = msg[3];

count= (count+1)%1;

if(count==0) {

msg.postln;

6.do{|i| var index = 4+(i*2);

if(i<numvoices) {

b[i].set(\freq,msg[index]*4,\amp,0.2); //*(msg[index+1])

}

{

b[i].set(\amp,0.0);

}

};

}

}).add;

)

c = {(SoundIn.ar*0.5)!2}.play

c.free;