Fundamentals
Export Targets
Code Export
Patcher UI
Special Topics
RNBO Raspberry Pi OSCQuery Runner
Using the FFT
How to use the fft~ and ifft~ objects for spectral processing in RNBO.
This article assumes you have some familiarity with spectral processing in Max, either with pfft~ or with fft~ and ifft~. RNBO’s fft~ and ifft~ objects are almost identical to the equivalent Max objects, so any patches using fft~ in Max work directly in RNBO. While RNBO does not currently provide pfft~, it’s possible to emulate pfft~ in RNBO, as you’ll see in this article.
For more information on the fft~ and ifft~ objects in Max, see:
Built-in Windowing
Unlike Max’s fft~ and ifft~, RNBO fft~ and ifft~ feature built-in windowing functions like Hann, Hamming, and Blackman. The default in RNBO is to not use any windowing, making it easy to copy over Max patches using fft~ and ifft~ without changing behavior.
With built-in windowing, RNBO FFTs patches can be much simpler than their Max equivalents. Take a look at this Max noise reduction patch. It performs an FFT on the signal, obtaining the amplitude and phase of each frequency component. Then, it mutes any components that fall under an amplitude threshold. Notice how much of the patch deals with applying a windowing function to the input and output of the noise reduction process.
In the equivalent RNBO patch, all of the windowing happens automatically within the fft~ and ifft~ objects.
You can reduce duplication further by using abstractions. The secret to making this work is using patcher argument syntax to dynamically pass in the window size and phase offset to fft~ and ifft~.
Now if you want to update the processing logic, you only need to change it in one place. If you want to use four overlapping FFTs instead of two, you can easily duplicate the abstraction and update the arguments.
With this abstraction technique, the resulting patcher looks a lot more like an equivalent pfft~ patch.
Custom Window Functions
If you need to use a windowing function that isn’t built-in to the RNBO fft~, you can provide a reference to a buffer to use as a custom windowing function. The fft~ object will automatically read from the buffer and apply the contents as a windowing function for each spectral frame. In the following phase vocoder example, a buffer containing the square root of the Hann windowing function is used in the FFT and inverse FFT processing.
Example: Spectral Filtering
The classic “Forbidden Planet” example patch implements a graphical EQ using pfft~. The patch peeks into a buffer that contains amplitude values for each FFT bin and scales the spectral data accordingly.
In the following example, we recreate the Forbidden Planet patch using RNBO.
FFTs and codebox
RNBO FFTs are stateful operators which can be used in codebox~. There are two variants of FFT operators available: buffered (fftbuffer) and streaming (fftstream/ifftstream).
Buffered FFTs are most useful when you want to do non-realtime processing.
Streaming FFTs are best for realtime contexts when you don’t want to handle buffering yourself. (In fact, fftstream/ifftstream use fftbuffer under the hood.)
The following RNBO patch computes the spectral content of a buffer using fftbuffer in codebox. Note the following about using fftbuffer:
The FFT is performed “in-place.” This means the buffer of data you input to fftbuffer gets replaced with the results of the calculations. In this example, we copy over the input data to a workspace buffer to preserve the original buffer.
The fftbuffer operator expects a buffer of interleaved real and complex values. Since we only have real input in this example, the workspace buffer is twice the size of the input and all of the complex values are left as zero.
The following example demonstrates using the streaming FFT operators to create another spectral EQ.
Resetting FFT processing
Each fft~/ifft~ object in your patch maintains an internal buffer of data and processing index. If you ever want to clear and synchronize all FFTs while patching in RNBO, you can do so by restarting Max’s DSP.
Materials in this article