Skip to content
August 31, 2012 / jpeg729

Faust tips

Faust is a great framework for programming audio transformation programs and plugins. You write simple code and it compiles it first to C++ then to nearly any sort of plugin/standalone program. You can even upload it to be compiled on their site.

The code you write corresponds to a block diagram that illustrates the pathway the input will take. I found it really intuitive and within a day I had written an adaptive high-pass/low-pass filter with a window full of knobs and sliders to adjust its behaviour.

Here I shall write about a few of the features that took me time to figure out.

How to build a counter

counter = 1 : + ~ _ ;

1 starts a stream of data that just says 1 at each moment in time.

+ takes it in and adds it to its other input

~ is the recursion operator. It takes the output of the + operation and feeds it via the _ operator back in to the +

_ just lets its input pass through unchanged, that is why it doesn’t have a block for itself in the diagram

; tells the compiler the line has finished

So at time 0, the plus receives 1 and outputs 1

At time 1, the plus receives 1 and 1 from the delayed recursion, and outputs 2

At time 2, the plus receives 1 and 2 from the delayed recursion, and outputs 3

And so on.

Counting seconds

import("math.lib")
seconds = (1 : + ~ _ ) / SR

The import is needed in order to use SR = the sample rate.

The counter above goes up one for every sample. Divide by the sample rate and you have the number of seconds as a float. If you want a whole number use a cast. Like this…

seconds = (1 : + ~ _ ) / SR : int

Understanding smoothing

In filter.lib there is a useful function for lazily following the amplitude of a signal. It is called smooth, it takes one parameter to tell it how smooth to be. Combine it with tau2pole to have a better idea how fast it smooths. For example

smooth(tau2pole(number_of_seconds)) will get to within about 0.63 of a constant signal in number_of_seconds, and will get very close in 4 times that amount of time.

Here is the block diagram of smooth(0.9)

If you look closely you can see a line coming in from the left, it represents the input signal. The arrow going out on the right is a smoothed version.

Here is a breakdown of how it works.

At time 0, we multiply the input signal by 1 - smoothing_constant. Here that will be multiplying by 0.1. That value will pass though the + unchanged. Were are not very close yet.

At time 1, the recursion loop has picked up the previous output and multiplies it by the smoothing constant. Here that will be 0.9. We add to that 0.1 of the original signal as before, and we have 0.1 * signal + 0.1 * 0.9 * signal. That is closer to the original signal, and the estimate is just going to get better.

The smoothing constant can be chosen between 0 and 1, the smaller it is the faster it gets there, and the larger it is the slower it gets there. If you want to know how long it is going to take use tau2pole to calculate the smoothing constant, otherwise the smoothing speed will change depending on the sample rate of the input.

Remember: we are calculating all that based on a given input signal, which could be changing all the time. So we will be chasing it down all the time.

Graphical user interfaces

To start with read the tutorial pages 18 to 20. Now you know all about buttons, sliders and so on. Read this too. Even after that I hadn’t understood how to group and order the controls in my window. Then I studied some example code.

Grouping

I thought that to group controls there had to be a line somewhere saying hgroup("name", list of controls), but each control returns a number that will be used in some calculation or another. Didn’t seem logical.

Here is how it works.
Each time you run hgroup("name", hslider(...)) it adds a slider to the group called “name”. So instead of writing *(hslider("Gain", ...)) you can write *(hgroup("name", hslider("Gain", ...))) and it will be in the right place.

Now for some shorthand. Suppose I define a function like this
volume_controls(x) = hgroup("Volume controls", x);
Then I can just write *(volume_controls(hslider("Gain", ...))) and I know that my Gain slider will appear in the right group in my programs window.

You can even nest several levels of these to put groups within groups, groups next to simple controls, etc…

highpass_group(x) = vgroup("Highpass filter", x);
highpass_contents(x) = highpass_group(vgroup("Parameters", x));

Then you can put an enabled button in the highpass_group and then the controls for the parameters in a subgroup. Neater that way.

Ordering

In each group the controls appear in alphabetical order of their names, so it seems we are stuck with that. However if you put a word in square brackets in the name it disappears, so we can just start the names with a number in square brackets, e.g. "[1] Gain" or "[2] Treble" or "[3] Base".

Don’t put a colon in there because it might be treated like a parameter, for example, [style:knob] in the name will turn a slider into a knob if you compile in some formats. See the end of this page for more parameters.

Conclusion

Hope that helps you have more fun faster.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: