[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[sc-users] FFT filtering with linear or exponential partial freq series



some FFT filter experiments for anyone who's interested in doing something similar ....

ciao, -sciss-


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


s.boot;

~soundPath = "sounds/AlphavilleIlArrive.aif";	// should be monophonic!!

~fftSize = 4096; // evtl. mit 2048 oder 8192 (das ist der hoechste erlaubte wert) probieren?
~filter = Buffer.alloc( s, ~fftSize, 1 );

~sound = Buffer.read( s, ~soundPath );
~fftBuf = Buffer.alloc( s, ~fftSize, 1 );

// ERSTER VERSUCH : LINEARE FILTER-FREQUENZEN
~freq = 140;
~filter.loadCollection([ Array.fill( ~fftSize.div(2), { arg i; var freq = s.sampleRate/~fftSize * i, nextFreq = s.sampleRate/~fftSize * (i+1); if( freq.div(~freq) < nextFreq.div(~freq), 1, 0 )}), Array.fill ( 1024, 0 )].lace );

(
x = { arg out = 0, amp = 1;
	var in, chain;
in = PlayBuf.ar(1, ~sound.bufnum, BufRateScale.kr( ~sound.bufnum ), loop: 1);
	chain = FFT( ~fftBuf.bufnum, in );
	chain = PV_Mul( chain, ~filter.bufnum );
	Out.ar( out, amp * IFFT( chain ) );
}.play;
)

~freq = 100;
~filter.loadCollection([ Array.fill( ~fftSize.div(2), { arg i; var freq = s.sampleRate/~fftSize * i, nextFreq = s.sampleRate/~fftSize * (i+1); if( freq.div(~freq) < nextFreq.div(~freq), 1, 0 )}), Array.fill ( 1024, 0 )].lace );


/// NEUER VERSUCH : GEOMETRISCHE FILTER-FREQUENZEN

~baseFreq = 30;
~factor = 2.pow(1/7);
~freqs = Array.geom( 1000, ~baseFreq, ~factor; ).reject(_ > (s.sampleRate/2));
~filterMag = Array.fill( ~fftSize.div(2), 0 );
// das spektrum wird einfach berechnet, indem die jeweils naechsten FFT-bins gefuellt werden (gewichtet nach der tatsaechlichen lage der frequenz). die phasen sind alle Null ~freqs.do({ arg freq; var band = freq / s.sampleRate * ~fftSize, bandLo = band.floor.asInteger, bandHi = band.ceil.asInteger, weightHi = band % 1.0, weightLo = 1 - weightHi; ~filterMag[ bandLo ] = min( 1, ~filterMag[ bandLo ] + weightLo ); ~filterMag[ bandHi ] = min( 1, ~filterMag[ bandHi ] + weightHi ); });
~filter.loadCollection([ ~filterMag, Array.fill( 1024, 0 )].lace );

/// 3. : MIT KOMPLEMENTAEREM SPEKTRUM (SUMME MUSS AUSGANGSKLANG ENTSPRECHEN)
x.free;

~filterInv = Buffer.alloc( s, ~fftSize, 1 );
~fftBufInv = Buffer.alloc( s, ~fftSize, 1 );

~filterMagInv = 1 - ~filterMag;
~filterInv.loadCollection([ ~filterMagInv, Array.fill( 1024, 0 )].lace );

(
y = { arg out = 1, amp = 2, ampInv = 0.125;
	var inA, chainA, inB, chainB;
inA = PlayBuf.ar(1, ~sound.bufnum, BufRateScale.kr( ~sound.bufnum ), loop: 1);
	chainA = FFT( ~fftBuf.bufnum, inA );
	chainB = FFT( ~fftBufInv.bufnum, inA );
	chainA = PV_Mul( chainA, ~filter.bufnum );
	chainB = PV_Mul( chainB, ~filterInv.bufnum );
	Out.ar( out, [ amp * IFFT( chainA ), ampInv * IFFT( chainB )]);
//	Out.ar( out, (amp * (IFFT( chainA ) + IFFT( chainB ))));
}.play;
)

y.free;
~filter.free; ~filterInv.free; ~fftBuf.free; ~fftBufInv.free; ~sound.free;