Right, the leakage effect shouldn't be neglected. Here is an example: With samplerate 44100 and window size 2048 we have N = 1024, bin size ca 21.53 Hz. Let's see what happens with a sine wave of 441 Hz: Bin nums go up to N-1 = 1023 441 / (44100 / 2048) = 20.48 Crucial are bands 20, 21, 22, these are the discriminating wipe values. 1 / 1023 * (20..22) -> [ 0.019550342130987, 0.020527859237537, 0.021505376344086 ] ( f = { |bound| { var a, chain; a = SinOsc.ar(441, 0, 0.1); chain = FFT(LocalBuf(2048), a); chain = PV_BrickWall(chain, bound); IFFT(chain); }.play } ) // cut below bin 20, full signal returned x = f.(0.01955034) x.release // cut bin 20, dampened signal returned x = f.(0.01955035) // x = f.(0.02052785) x.release // cut bin 21, zero (except artefact at start) x = f.(0.02052786) Same with PV_BinRange ( g = { |loBin| { var a, chain; a = SinOsc.ar(441, 0, 0.1); chain = FFT(LocalBuf(2048), a); chain = PV_BinRange(chain, loBin, 100); IFFT(chain); }.play } ) // cut below bin 20, full signal returned x = g.(20) x.release x = g.(21) x.release x = g.(22) x.release To minimize the effect of a "transition bin" you'd have to take a larger window size, which results in a worse time resolution. There's always a trade-off with other options like steep filters. However with the exception of very low registers, where bins -- regarded as intervals -- are relatively large, the distinctiveness of the FFT approach is unique. Greetings Daniel |