|  | #include <assert.h>
#include <iostream>
#include "asserts.h"
#include "SinOscillator.h"
using namespace std;
// test that it can be hooked up
template<typename T>
static void test1()
{
    SinOscillatorParams<T> p;
    SinOscillatorState<T> s;
    SinOscillator<T, true>::setFrequency(p, T(.1));
    T x = SinOscillator<T, true>::run(s, p);
    (void) x;
}
// test that it makes output
template<typename T>
static void test2()
{
    SinOscillatorParams<T> p;
    SinOscillatorState<T> s;
    SinOscillator<T, false>::setFrequency(p, T(.1));
    T x = SinOscillator<T, false>::run(s, p);
    assert(x == 0);
    x = SinOscillator<T, false>::run(s, p);
    assert(x > 0);
}
// test that sin lookup is correct
template<typename T>
static void test3()
{
    SinOscillatorParams<T> params;
    SinOscillatorState<T> s;
    SinOscillator<T, true>::setFrequency(params, T(.1));
    auto& lookup = params.lookupParams;
    const double delta = .00001;
    // sin(0) == 0;
    T y = LookupTable<T>::lookup(*lookup, 0);
    assert(AudioMath::closeTo(y, 0, delta));
    // sin(2pi) == 0
    y = LookupTable<T>::lookup(*lookup, 1);
    assert(AudioMath::closeTo(y, 0, delta));
    // sin(pi/2) == 1
    y = LookupTable<T>::lookup(*lookup, .25);
    assert(AudioMath::closeTo(y, 1, delta));
    // sin(pi) == 0
    y = LookupTable<T>::lookup(*lookup, .5);
    assert(AudioMath::closeTo(y, 0, delta));
}
// test that output is correct freq
template<typename T>
static void test4()
{
    const int clocksPerPeriod = 64;
    SinOscillatorParams<T> params;
    SinOscillatorState<T> state;
    SinOscillator<T, false>::setFrequency(params, T(1.0 / clocksPerPeriod));
    const double delta = .00001;
    T output, quadrature;
    for (int i = 0; i <= clocksPerPeriod; ++i) {
        SinOscillator<T, false>::runQuadrature(output, quadrature, state, params);
        if (i == 0) {
            // sin+cos(0) = 0 + 1
            assert(AudioMath::closeTo(output, 0, delta));
            assert(AudioMath::closeTo(quadrature, 1, delta));
        }
        if (i == 64) {
            // sin+cos(0) = 0 + 1
            assert(AudioMath::closeTo(output, 0, delta));
            assert(AudioMath::closeTo(quadrature, 1, delta));
        }
        if (i == 16) {
            // sin+cos(pi/2) = 1  0
            assert(AudioMath::closeTo(output, 1, delta));
            assert(AudioMath::closeTo(quadrature, 0, delta));
        }
        if (i == 32) {
            // sin+cos(pi) = 0  -1
            assert(AudioMath::closeTo(output, 0, delta));
            assert(AudioMath::closeTo(quadrature, -1, delta));
        }
        if (i == 48) {
            // sin+cos(3pi/2) = -1  0
            assert(AudioMath::closeTo(output, -1, delta));
            assert(AudioMath::closeTo(quadrature, 0, delta));
        }
    }
}
template<typename T>
static void testDistortion()
{
    SinOscillatorParams<T> params;
    SinOscillatorState<T> s;
    SinOscillator<T, true>::setFrequency(params, T(.0423781));
    auto& lookup = params.lookupParams;
    double err = 0;
    for (double d = 0; d < 1; d += .00123) {
        double x = LookupTable<T>::lookup(*lookup, (T) d);
        double y = sin(d * AudioMath::Pi * 2);
      //  printf("d=%f sin=%f look=%f\n", d, y, x);
        assertClose(x, y, .01);
        const double e = std::abs(x - y);
        err = std::max(err, e);
    }
    double errDb = AudioMath::db(err);
   // printf("THD = %f\n", errDb);
    assertLT(errDb, -80);
}
template<typename T>
static void test()
{
    test1<T>();
    test2<T>();
    test3<T>();
    test4<T>();
    testDistortion<T>();
}
void testSinOscillator()
{
    test<double>();
    test<float>();
}
 |