In this assignment you are asked to create a spectrum analyzer, but now using Faust instead of the juce FFT library. Through this assignment you will learn how to:

- Use the Faust libraries
- Learn how to write Faust code
- Perform time-domain spectral analysis
- Interface JUCE with Faust

As usual, feel free to go wild! However, your implementation must have the following components:

- Your plugin must display the
**real time**spectrum of your input signal. This spectrum must be computed using Faust - Your plugin must be controllable
*through*Faust - Smoothing Time (ms)
- Another parameter of your choice

This project will build off of Assignment 1. Your GUI from the previous assignment can be reused. Just make sure to remove all references to the JUCE FFT library. You will now be generating your data via Faust.

To analyze our input signal we will use the Faust library's `mth_octave_analyzer`

functions from their `analyzers.lib`

library.

The Mth-Octave Analyzer implements a filterbank which splits the signal into a parallel bank of signals, one for each spectral band. For our purposes, we will use the default analyzer which in turn uses bandpass filters based off of 6th-order elliptic filters:

`mth_octave_analyzer_default = mth_octave_analyzer6e;`

`mth_octave_analyzer_default`

has three parameters:

`M`

number of band-slices per octave (>1)`ftop`

upper bandlimit of the Mth-octave bands (< SR/2)`N`

total number of bands = number of output signals

`M`

equal to 1 we will
produce `N`

octave
bands, starting with a highpass band crossing over to the next band below at frequency
`ftop`

, and band-splitting downward from there by octaves.
To see the block diagram of this filter bank, say (at the CLI)
`faust2firefox ~/faust/examples/filtering/filterBank.dsp`

and click down three levels to see the octave filter-bank architecture.
For a simpler example, consider:

`process = an.mth_octave_analyzer_default(1, 10000, 2);`

which results in the following block-diagram:
This process splits the spectrum into two bands having a crossover frequency at `ftop`

= 10 kHz.
In this case, only a lowpass and highpass are used (no bandpass sections). If we increase `N`

to 3, then the lowpass band gets
split into a new lowpass cutting off at 5 kHz, introducing a
bandpass from 5 to 10 kHz, and so forth

The following Faust program can be adapted to check your filter bank in Python, Octave, or MATLAB, etc.:

```
import("stdfaust.lib");
N = 3;
fTop = 10000;
bandsPerOctave = 1;
displayOffsetDB = 5;
process = 1-1' : an.mth_octave_analyzer_default(bandsPerOctave, fTop, N)
: par(k,N,*(pow(10.0,(k*displayOffsetDB)/20.0)));
```

This Faust program, as written, outputs three signals containing the band impulse-responses.Taking an FFT and displaying them overlaid yields the following magnitude frequency response overlay:

The parameter `M`

will change the size of the octave band being used. This can be used to implement fractional octave smoothing. If we wanted 1/3-octave smoothing we would then set `M`

to 3. With `M`

equal to 3 and `N`

both equal to 5 we produce three 1/3rd octave bands between 10 kHz and 20 kHz with two additional highpass and lowpass bands above 20 kHz and below 10 kHz.

Try implementing `an.mth_octave_analyzer_default(3, 10000, 14)`

and listening to the different channels!

In our previous assignment we used a leaky integrator to smooth the output of FFT. Here we will do the same using a combination of the `si.smooth()`

and `ba.tau2pole()`

functions.

`si.smooth`

is in Faust's signals library and implements a dc-unity gain one-pole lowpass filter, which is essentially our leaky integrator. We need to provide the `si.smooth()`

function with our pole location. To do this we call `ba.tau2pole()`

and provide our time constant to the function. Since we want to smooth `N`

bands we use the `par`

integrator

`par(i, N,si.smooth(ba.tau2pole(tau))`

Since we want to take the power of our signal before smoothing we'll use the `par`

iterator and an absolute value before we smooth our functions `par(i, N, abs(_)^2)`

.
We want to control our \(\tau\) parameter like before. Add an `hslider`

to your Faust code.

`tau = hslider("smoothTime", 0, 0, 10, 0.1)*0.001;`

Implement a your filterbank in Faust and compile it to C++ and add it into your JUCE project as in Assignment 1.5.

It could be helpful to delete the old FFT size macros and replace them with macros that define the size of our Faust filterbank

```
#define N 12 // yourNumberOfBands
#define M 3 // yourBandSlices
```

We also need to create new float arrays to use in our visualizer plot:

```
float fbData[N];
float frequencies[N];
```

Attach `fbData`

to your `Visualizer`

in your plugin constructor. In `prepareToPlay`

calculate the center frequencies of your frequency bands. Hint: look at the Faust implementation of `an.mth_octave_analyzer`

To store the output of Faust filterbank we will declare a `juce::AudioBuffer<float>`

private member. Based on our Faust code our audio buffer member should have `N`

channels (the number filterbank bands) and match the number of samples of our input buffer.
So we will declare

`juce::AudioBuffer<float> fbBuffer`

in our header file. And in `prepareToPlay`

we will set our buffer size

`fbBuffer.setSize(nBands, samplesPerBlock)`

Now we can allocate a double pointer, say `float **faustOutputPtr`

in our header, and in `prepareToPlay`

attach your Faust audio buffer to this pointer

`faustOutputPtr = fbBuffer.getArrayOfWritePointers(); `

Use this buffer and pointer combination to call our `compute`

function on the first channel of our input in `processBlock`

`fDSP->compute(buffer.getNumSamples(), buffer.getArrayOfWritePointers(), faustOutputPtr);`

After calling `compute`

we need to write our output to our filterbank plot

```
for (int band = 0; band < N; band++)
{
for (int samp = 0; samp < buffer.getNumSamples(), samp++)
{
fbData[bin] = faustOutputPtrs[bin][samp];
plot->update();
}
}
```

Now we can update our filterbank plot at every sample! Trying adding in the other parameters your used in your previous assignment to your Faust code and hooking them up in JUCE!