FilterKernels are helper classes.
FilterKernels main funcionality is to obtain a set of filter coefficients based on the kernel’s current configuration. Name it, a Kernel’s current Filter selection and the Filter’s parameters values.

Just like modifications to a Kernel’s filter parameters, Filter selection itself can be made at any time.

Magnitude of frequency bands a FilterKernel passes or rejects can be plotted and Filter paametters edited via MagnitudeResponseView


FilterKernelBase

FilterKernelBase is an abstract class and supplies all of FilterKernels base behavior. Parents FOSKernel and SOSKernel. A First and a Second Order Sections filter kernels respectively.

FilterKernel-hierarchy

FilterKernels provide methods to interact with the current filter selection paramters:

  • cutoff frequency
  • q *
  • dbGain *

(*) where applicable

FilterKernels implement a magnitudeResponse method that calculates filters Magnitude Response for the current filter selection.

FilterKernel::magnitudeResponse(viewWidth, minFreq=20.0, maxFreq);

Using FilterKernels

Create FilterKernel instances

SOSKernel::new(freq=100.0, q=0.7, dBGain=0.0, filterKey='BPeakEQ', sampleRate=44100.0);

Where

  • freq - initial filter kernel cutoff frequency
  • q - initial q
  • dbGain - initial gain in dBs
  • filterKey - A Symbol, one of the installed filters on that particular FilterKernel
  • sampleRate - the kernel’s operation Sample Rate

FilterKernel installed filters

SOSKernel.filters.keys; // installed filters

Query and modify kernel parameters

// getter
FilterKernel::frequency
FilterKernel::q
FilterKernel::gain

// setters
FilterKernel::frequency_   // does not perform calculations or update dependants
FilterKernel::setFrequency // performa calculations and update dependants

FilterKernel::q_           // does not perform calculations or update dependants
FilterKernel::setQ         // performa calculations and update dependants

FilterKernel::gain_        // does not perform calculations or update dependants
FilterKernel::setGain      // performa calculations and update dependants

Invoke calculations and update dependants

FilterKernel::paramsChanged;

Select and query kernel filter filter type

FilterKernel::filterKey // Getter a Symbol
FilterKernel::selectFilterType(inFilterKey); // Symbol

FilterKernel::filterClass // Getter a Class
FilterKernel::selectFilterClass(inFilterClass);
FilterKernel::filterClass_(inFilterClass);

Query and modify kernel coefficients

// Query coefficients array
FilterKernel::coefs

// Set coefficients. Updates dependants, does not perform calculations.
// must invoke FilterKernel::paramsChanged
FilterKernel::setCoefs(in_a0, in_a1, in_a2, in_b1, in_b2);

FilterKernel states - save and restore

FilterKernel::snapshot
FilterKernel::restore(inState);

Installing new filters to a FilterKernel

Extending FilterKernel supported Filters can be easily done by adding instances of KernelFilter to FilterKernel’s filters class Dictionary.

KernelFilter::new(name, className, freqKey='freq', gainKey='db', qKey='rq', isQreciprocal=true);
  • name - Name of the filter. This name will appear on menus.
  • className - The filter Class. The class must respondTo the coefs method. The Coefs method calculates and returns a set of coefficients for the supplied filter parameters. This can also be a Function that calculates coefficients from filter’s parameters.
  • freqKey - Argument name for the filter’s Cutoff ferquency parameter in the coefs method.
  • gainKey - Argument name for the filter’s Gain parameter in the coefs method. nil if not applicable
  • qKey - Argument name for the filter’s Q parameter in the coefs method. nil if not applicable
  • isQreciprocal - true if the Q argument is supplied to the Filter as the reciprocal value of Q (ie, rq, rs etc.).

Filter implementations

The only requierment for Filters to work as a FilterKernel’s Filter is they must implement a pure lang side coefs Class method. That is, there shouldn’t be any dependencies to UGens in this Method.
The *coefs method transforms the filter parameters values into a coefficients array.

LowBoost.sc Lowshelf second order filter class definition example.

//------------------------------------------------------------------
//	DAFX, Digital Audio Effects (Wiley ed.)
//	chapter 2 	: filters
//	section 2.3 : Equalizers
//	page 53 	: second order shelving filter design
//------------------------------------------------------------------

// low-freq shelving boost
// blackrain

LowBoost {
	*ar { arg in, freq=400.0, db=0.0, mul=1.0, add=0.0;
		var coefs;
		coefs = this.coefs(freq, db, SampleDur.ir);
		^SOS.ar(in, *coefs ++ [mul, add]);
	}
	*kr { arg in, freq=400.0, db=0.0, mul=1.0, add=0.0;
		var coefs;
		coefs = this.coefs(freq, db, SampleDur.ir);
		^SOS.kr(in, *coefs ++ [mul, add]);
	}
	*coefs { arg freq=400.0, db=0.0, sampleDur=(44100.reciprocal);
		var v0g, fc, denom, fc_pow2, tmp1, tmp2;
		var a0, a1, a2, b1, b2;

		v0g = pow(10.0, db / 20.0);
		fc	= (pi*freq*sampleDur).tan;
		fc_pow2 = fc.pow(2);
		tmp1 = (2.sqrt*fc) + fc_pow2;
		tmp2 = ((2*v0g).sqrt * fc) + (v0g*fc_pow2);
		denom = 1.0 + tmp1;

		a0 = (1 + tmp2) / denom;
		a1 =  2 * (v0g*fc_pow2 - 1) / denom;
		a2 = (1 - tmp2) / denom;
		b1 = -2 * (fc_pow2 - 1) / denom;
		b2 = (1 - tmp1).neg / denom;
		
		^[a0, a1, a2, b1, b2]
	}
}

Adding LowBoost to SOSKernel

// Install a LowBoost Filter into a FilterKernel (an SOSKernel here)
(
	SOSKernel.filters.put('LowBoost',
		KernelFilter.new('LowBoost', LowBoost, 'freq', 'db', nil, false)
	);
)

// List all the installed filters
SOSKernel.filters.keys;



Examples

// one liner
v = SOSKernel.new.view;
k = v.kernels.first;

Multiple FilterKernels: An SOS and an FOS FilterKernels.

// Multiple FilterKernels
k = SOSKernel.new;
j = FOSKernel.new;
j.setFrequency(1000);

v = k.view;
v.kernels = [k, j];

SOSKernel examples

s.boot;

b = Buffer.read(s, "/path/to/your/audio/file)");

(
[1,2].do({ arg chns;
	SynthDef("soskernel-ctrl-"++chns.asString, { |inbus=2, outbus=0, bufnum, rate=1.0, t_trig=1, startPos=0, loop=1, amp=1.0, bypass=0|
		var coefs, coefsctl,fx,dry,z;
		coefs = 0!5;
		coefsctl = \coefs.kr(coefs);
		dry = PlayBuf.ar(2, bufnum, BufRateScale.kr(bufnum) * rate, t_trig, startPos, loop, Done.freeSelf);
		// dry = In.ar(inbus,chns);
		fx = SOS.ar(dry, *coefsctl);
		Out.ar(outbus, ((dry*bypass)+((1-bypass)*fx)) * amp);
	}).add;
});
)

k=SOSKernel.new;
k.coefs;

a=Synth("soskernel-ctrl-2", [\coefs, k.coefs, \bufnum, b.bufnum]);
a.trace;

a.set(\amp, 0.7);
a.set(\amp, 1);

v=k.view;
v.action={|view,kernel| a.set(\coefs, kernel.coefs, \bypass, 1 - kernel.enabled.binaryValue); };

(
v.action={|view,kernel,changed|
	//changed.postln;
	case
	{ changed == \coefs or:{ changed == \filterKey } } {
		a.set(\coefs, kernel.coefs);
	}
	{ changed == \bypass } {
		a.set(\bypass, 1 - kernel.enabled.binaryValue);
	};
};
)

s.dumpOSC(1);
s.dumpOSC(0);

k.filterClass_(BLowPass); a.set(\coefs, k.coefs);
k.setFrequency(2300.0); a.set(\coefs, k.coefs);
k.setFrequency(5200.0); a.set(\coefs, k.coefs);
k.setQ(0.7); a.set(\coefs, k.coefs);
k.setQ(2.5); a.set(\coefs, k.coefs);
k.setQ(1.2); a.set(\coefs, k.coefs);

k.selectFilterType(\BPeakEQ);
k.setFrequency(2300.0);
k.setGain(3.0);
a.set(\coefs, k.coefs);

k.setQ(0.7); a.set(\coefs, k.coefs);
k.setFrequency(5200.0); a.set(\coefs, k.coefs);
k.setGain(3.5); a.set(\coefs, k.coefs);


k.filterClass_(BHiShelf); a.set(\coefs, k.coefs);
k.setFrequency(1000.0); a.set(\coefs, k.coefs);
k.setGain(3.5); a.set(\coefs, k.coefs);
k.setQ(2.4); a.set(\coefs, k.coefs);
k.setQ(0.7); a.set(\coefs, k.coefs);

a.set(\bypass, 1);
a.set(\bypass, 0);

k.frequency_(1000.0);
k.q_(0.7);
k.gain_(0.0);
k.paramsChanged;
k.changed(\freq);
a.set(\coefs, k.coefs);
v.refresh

a.free;
b.free;



Instalation

Clone MagnitudeResponseView repository and move its folder inside the Extensions folder in SuperCollider3 User Support directory or place MagnitudeResponseView repository folder anywhere you want in your file system and add its path to your includes folder in sclang config section in SCIDE prefs.

ie, in the IDE:

Click Edit Menu -> Preferences and click on interpreter.

and recompile Class Library.

If you don’t have GIT available in your system, you can simply download a snapshot of the MagnitudeResponseView repository as a zip file from the Download links at the bottom left on that page and install that as a quark:

Quarks.install("~/path/to/MagnitudeResponseView/MagnitudeResponseView.quark")

Recompile Class Library and you are done.

This is a local copy of the latest snapshot.