[LAD] Prototyping algorithms and ideas

Albert Graef Dr.Graef at t-online.de
Thu Jan 24 00:33:04 UTC 2008


Darren Landrum wrote:
> If you wanted to quickly prototype an idea for a DSP routine, how would 
> you go about it? It would need to work in real-time, but it wouldn't 
> really need to be super-efficient for testing ideas.

As long as the DSP doesn't need any tight feedback loops, Pd [1] or some
such patching environment is probably the easiest way to go.

[1] http://puredata.info/

For more advanced stuff, or if you need to build your own custom DSP
components, use Faust [2]. It's the most advanced DSP programming
language available right now. Also, it's a real DSP language which
allows you to program to the bare metal, instead of just patching
together some ready-made components. I guess that's what you want.

[2] http://faust.grame.fr/

Faust is a purely functional language (signals are streams of samples,
DSPs are functions operating on those, which can easily combined in
various ways using Faust's block diagram operators). It compiles to C++,
output code is very good (comparable to carefully hand-crafted code),
and it interfaces nicely to different environments like Jack, LADSPA,
Pd, Max/MSP, VST, SC3, to name just a few. There's also a script to
generate ready-to-use Pd patches from Faust programs which makes testing
pretty easy. Also, you can compile your Faust programs online on the
Faust website if you don't want to bother installing the Faust compiler
(which is quite easy, though, it should readily compile on any Linux box).

For more information, see Yann Orlarey et al's LAC/ICMC 2006 paper and
my LAC 2007 paper (the latter is specifically about the Faust-Pd
interface). You can find these and a lot more on the Faust website [3].
Julius Smith from CCRMA has a tutorial and various examples [4,5], and
you can find some further Faust examples like guitar effects, various
synthesis algorithms and even a KCS decoder on my Q website [6]. The
Faust distribution also includes a lot of examples. (There's no book on
Faust yet, so right now you'll have to find your way using the examples,
the quick reference guide included in the Faust distribution, and the
various tutorials available.)

[3] http://faust.grame.fr/pubs.php
[4] http://ccrma.stanford.edu/realsimple/faust/
[5] http://ccrma.stanford.edu/realsimple/faust_strings/faust_strings.html
[6] http://q-lang.sourceforge.net/examples.html#Pd

Faust has a learning curve, especially if you never used a functional
programming language before. But it's definitely worth it, and it's
addictive. ;-) Once mastered, you can program fairly complex DSPs in a
few lines, and you don't have to worry about those nasty block wrapover
issues which make programming non-trivial DSPs directly in C a pita. And
since the output code is just plain C++ (the compiled DSP algorithm
itself is actually C, being wrapped up in a C++ class for tidyness), you
can easily integrate it into your own programs once you're done prototyping.

To whet your appetite, here are a few Faust examples. A simple chorus
effect:

chorus(dtime,freq,depth,phase,x)
		= x+level*fdelay(1<<16, t, x)
with {
	t	= SR*dtime/2*(1+depth*tblosc(1<<16, sin, freq, phase));
};

Or how about a generic biquad filter:

filter(b0,b1,b2,a0,a1,a2)	= f : (+ ~ g)
with {
	f(x)	= (b0/a0)*x+(b1/a0)*x'+(b2/a0)*x'';
	g(y)	= 0-(a1/a0)*y-(a2/a0)*y';
};

Note that ~ is Faust's feedback loop operator; the local f function is
the feedforward, g the feedback part of the filter. x' means signal x
delayed by one sample. Pretty easy. And here's how you use that
definition to define a low shelf filter, straight from Robert
Bristow-Johnson's Audio EQ Cookbook. f0 is the shelf midpoint frequency,
g the desired gain in dB. S is the shelf slope parameter, we always set
that to 1 here:

low_shelf(f0,g)		= filter(b0,b1,b2,a0,a1,a2)
with {
	S  = 1;
	A  = pow(10,g/40);
	w0 = 2*PI*f0/SR;
	alpha = sin(w0)/2 * sqrt( (A + 1/A)*(1/S - 1) + 2 );

	b0 =    A*( (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha );
	b1 =  2*A*( (A-1) - (A+1)*cos(w0)                   );
	b2 =    A*( (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha );
	a0 =        (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha;
	a1 =   -2*( (A-1) + (A+1)*cos(w0)                   );
	a2 =        (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha;
};

You can find these examples and a lot more in my Faust guitar effects
collection (see ref. [6] above). Also make sure to take a look at Julius
Smith's examples, he's Da Man. :)

HTH,
Albert

-- 
Dr. Albert Gr"af
Dept. of Music-Informatics, University of Mainz, Germany
Email:  Dr.Graef at t-online.de, ag at muwiinfa.geschichte.uni-mainz.de
WWW:    http://www.musikinformatik.uni-mainz.de/ag



More information about the Linux-audio-dev mailing list