# Example 4: Measuring the Signal-to-Noise Ratio

## Introduction

This example measures the signal-to-noise ratio (SNR) of the resynthesis by analyzing and resynthesizing a test signal and comparing the resynthesis result to the original.

Since it does not involve any audio file I/O, this example does not require the sndfile library, making it the shortest and simplest one by far.

## Preamble

```#include <iostream>
#include <iomanip>
#include <random>
#include <gaborator/gaborator.h>
```

## Amplitude Measurement

To calculate the signal-to-noise ratio, we need to measure the amplitude of the orignal signal and the error residue. We will use the root-mean-square amplitude, which is calculcated by the function `rms()`.

```double rms(const std::vector<float> &v) {
double sqsum = 0;
for (size_t i = 0; i < v.size(); i++) {
sqsum += v[i] * v[i];
}
return sqrt(sqsum);
}
```

## Main Program

For the test signal, we use a million samples of white noise with a uniform amplitude distribution between -1 and +1.

```int main(int argc, char **argv) {
size_t len = 1000000;
std::vector<float> signal_in(len);
std::minstd_rand rand;
std::uniform_real_distribution<> uniform(-1.0, 1.0);
for (size_t i = 0; i < len; i++)
signal_in[i] = uniform(rand);
```

Then we create a spectrum analyzer with 48 bands per octave and a frequency range of 3 decades (0.0005 to 0.5 times the sample rate):

```    gaborator::parameters params(48, 5e-4);
gaborator::analyzer<float> analyzer(params);
```

...and run the spectrum analyzis:

```    gaborator::coefs<float> coefs(analyzer);
analyzer.analyze(signal_in.data(), 0, len, coefs);
```

...resynthesize the signal into `signal_out`:

```    std::vector<float> signal_out(len);
analyzer.synthesize(coefs, 0, len, signal_out.data());
```

...measure the resynthesis error:

```    std::vector<float> error(len);
for (size_t i = 0; i < len; i++)
error[i] = signal_out[i] - signal_in[i];
```

...calculate the signal-to-noise ratio:

```    double snr = rms(signal_in) / rms(error);
```

...and print it in decibels:

```    std::cout << std::fixed << std::setprecision(1) << 20 * log10(snr) << " dB\n";
}
```

## Compiling

Like Example 1, this example can be built using a one-line build command:

```c++ -std=c++11 -I.. -O3 -ffast-math `pkg-config --cflags sndfile` snr.cc `pkg-config --libs sndfile` -o snr
```

Or using the vDSP FFT on macOS:

```c++ -std=c++11 -I.. -O3 -ffast-math -DGABORATOR_USE_VDSP `pkg-config --cflags sndfile` snr.cc `pkg-config --libs sndfile` -framework Accelerate -o snr
```

Or using PFFFT (see Example 1 for how to download and build PFFFT):

```c++ -std=c++11 -I.. -Ipffft -O3 -ffast-math -DGABORATOR_USE_PFFFT `pkg-config --cflags sndfile` snr.cc pffft/pffft.o pffft/fftpack.o `pkg-config --libs sndfile` -o snr
```

## Running

The program is run with no arguments:

```./snr
```

This will print the SNR which should be more than 100 dB if the library is working correctly.