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 libsndfile library, making it the shortest and simplest one by far.
#include <iostream> #include <iomanip> #include <random> #include <gaborator/gaborator.h>
To calculate the signal-to-noise ratio, we need to measure the
amplitude of the original signal and the error residue. We will use
the root-mean-square amplitude, which is calculated 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); }
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(gaborator::log_fq_scale(48, 5e-4)); gaborator::analyzer<float> analyzer(params);
...and run the spectrum analysis:
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"; }
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
The program is run with no arguments:
./snr
This will print the SNR which should be more than 100 dB when the library is working correctly.