#include #include #include "asserts.h" #include "SinOscillator.h" using namespace std; // test that it can be hooked up template static void test1() { SinOscillatorParams p; SinOscillatorState s; SinOscillator::setFrequency(p, T(.1)); T x = SinOscillator::run(s, p); (void) x; } // test that it makes output template static void test2() { SinOscillatorParams p; SinOscillatorState s; SinOscillator::setFrequency(p, T(.1)); T x = SinOscillator::run(s, p); assert(x == 0); x = SinOscillator::run(s, p); assert(x > 0); } // test that sin lookup is correct template static void test3() { SinOscillatorParams params; SinOscillatorState s; SinOscillator::setFrequency(params, T(.1)); auto& lookup = params.lookupParams; const double delta = .00001; // sin(0) == 0; T y = LookupTable::lookup(*lookup, 0); assert(AudioMath::closeTo(y, 0, delta)); // sin(2pi) == 0 y = LookupTable::lookup(*lookup, 1); assert(AudioMath::closeTo(y, 0, delta)); // sin(pi/2) == 1 y = LookupTable::lookup(*lookup, .25); assert(AudioMath::closeTo(y, 1, delta)); // sin(pi) == 0 y = LookupTable::lookup(*lookup, .5); assert(AudioMath::closeTo(y, 0, delta)); } // test that output is correct freq template static void test4() { const int clocksPerPeriod = 64; SinOscillatorParams params; SinOscillatorState state; SinOscillator::setFrequency(params, T(1.0 / clocksPerPeriod)); const double delta = .00001; T output, quadrature; for (int i = 0; i <= clocksPerPeriod; ++i) { SinOscillator::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 static void testDistortion() { SinOscillatorParams params; SinOscillatorState s; SinOscillator::setFrequency(params, T(.0423781)); auto& lookup = params.lookupParams; double err = 0; for (double d = 0; d < 1; d += .00123) { double x = LookupTable::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 static void test() { test1(); test2(); test3(); test4(); testDistortion(); } void testSinOscillator() { test(); test(); }