|
-
- #include <assert.h>
- #include <iostream>
-
- #include "asserts.h"
- #include "AudioMath.h"
- #include "LookupTable.h"
- #include "LookupTableFactory.h"
-
- using namespace std;
-
- // test that we can call all the functions
- template<typename T>
- static void test0()
- {
- LookupTableParams<T> p;
- const int tableSize = 512;
-
- std::function<double(double)> f = [](double d) {
- return 0;
- };
-
- LookupTable<T>::init(p, tableSize, 0, 1, f);
- LookupTable<T>::lookup(p, 0);
- }
-
- // test that simple lookup works
- template<typename T>
- static void test1()
- {
- LookupTableParams<T> p;
- const int tableSize = 512;
-
- std::function<double(double)> f = [](double d) {
- return 100;
- };
-
- LookupTable<T>::init(p, tableSize, 0, 1, f);
- assert(LookupTable<T>::lookup(p, 0) == 100);
- assert(LookupTable<T>::lookup(p, 1) == 100);
- assert(LookupTable<T>::lookup(p, T(.342)) == 100);
- }
-
-
- // test that sin works
- template<typename T>
- static void test2()
- {
- LookupTableParams<T> p;
- const int tableSize = 512;
-
- std::function<double(double)> f = [](double d) {
- return std::sin(d);
- };
-
- LookupTable<T>::init(p, tableSize, 0, 1, f);
-
- const T tolerance = T(0.000001);
- for (double d = 0; d < 1; d += .0001) {
- T output = LookupTable<T>::lookup(p, T(d));
-
- const bool t = AudioMath::closeTo(output, std::sin(d), tolerance);
- if (!t) {
- cout << "failing with expected=" << std::sin(d) << " actual=" << output << " delta=" << std::abs(output - std::sin(d));
- assert(false);
- }
- }
- }
-
-
- // test that sin works on domain 10..32
- template<typename T>
- static void test3()
- {
- LookupTableParams<T> p;
- const int tableSize = 16;
-
- std::function<double(double)> f = [](double d) {
- const double s = (d - 10) / 3;
- return std::sin(s);
- };
-
- LookupTable<T>::init(p, tableSize, 10, 13, f);
-
- const T tolerance = T(0.01);
- for (double d = 10; d < 13; d += .0001) {
- const T output = LookupTable<T>::lookup(p, T(d));
-
- const T expected = (T) std::sin((d - 10.0) / 3);
- const bool t = AudioMath::closeTo(output, expected, tolerance);
- if (!t) {
- cout << "failing with d=" << d << " expected=" << expected << " actual=" << output << " delta=" << std::abs(output - std::sin(d));
- assert(false);
- }
- }
- }
-
- // test that sin at extremes works
- template<typename T>
- static void test4()
- {
- LookupTableParams<T> exponential;
-
- const T xMin = -5;
- const T xMax = 5;
-
- std::function<double(double)> expFunc = AudioMath::makeFunc_Exp(-5, 5, 2, 2000);
- LookupTable<T>::init(exponential, 128, -5, 5, expFunc);
-
- // Had to loosen tolerance to pass with windows gcc. Is there a problem
- // with precision, or is this expected with fast math?
- const T tolerance = T(0.0003);
- T outputLow = LookupTable<T>::lookup(exponential, xMin);
-
- T outputHigh = LookupTable<T>::lookup(exponential, xMax);
-
- bool t = AudioMath::closeTo(outputLow, 2, tolerance);
- if (!t) {
- cout << "failing l with expected=" << 2 << " actual=" << outputLow << " delta=" << std::abs(outputLow - 2) << std::endl;
- assert(false);
- }
- t = AudioMath::closeTo(outputHigh, 2000, tolerance);
- if (!t) {
- cout << "failing h with expected=" << 2000 << " actual=" << outputHigh << " delta=" << std::abs(outputHigh - 2000) << std::endl;
- assert(false);
- }
- }
-
- template<typename T>
- static void testDiscrete1()
- {
- LookupTableParams<T> lookup;
-
- T y[] = {0, 10};
- LookupTable<T>::initDiscrete(lookup, 2, y);
-
- assertEQ(LookupTable<T>::lookup(lookup, 0), 0);
- assertEQ(LookupTable<T>::lookup(lookup, .5), 5);
- assertEQ(LookupTable<T>::lookup(lookup, 1), 10);
-
- assertEQ(LookupTable<T>::lookup(lookup, T(.1)), 1);
- assertClose(LookupTable<T>::lookup(lookup, T(.01)), T(.1), .00001);
- }
-
- template<typename T>
- static void testDiscrete2()
- {
- LookupTableParams<T> lookup;
-
- T y[] = {100, 100.5, 2000, -10};
- LookupTable<T>::initDiscrete(lookup, 4, y);
-
- assertEQ(LookupTable<T>::lookup(lookup, 0), 100);
- assertEQ(LookupTable<T>::lookup(lookup, 1), 100.5);
- assertEQ(LookupTable<T>::lookup(lookup, 2), 2000);
- assertEQ(LookupTable<T>::lookup(lookup, 3), -10);
-
- assertEQ(LookupTable<T>::lookup(lookup, 2.5), 1000 - 5);
- }
-
- template<typename T>
- static void testExpSimpleLookup()
- {
- LookupTableParams<T> lookup;
- LookupTableFactory<T>::makeExp2(lookup);
-
- const double xMin = LookupTableFactory<T>::expXMin();
- const double xMax = LookupTableFactory<T>::expXMax();
- assert(5 > xMin);
- assert(11 < xMax);
- assertClose(LookupTable<T>::lookup(lookup, 5), std::pow(2, 5), .01);
- assertClose(LookupTable<T>::lookup(lookup, 11), std::pow(2, 11), 2); // TODO: tighten
- }
-
-
-
- // test that extreme inputs is clamped
- template<typename T>
- static void testExpRange()
- {
- LookupTableParams<T> lookup;
- LookupTable<T>::makeExp2(lookup);
- auto k1 = LookupTable<T>::lookup(lookup, -1);
- auto k2 = LookupTable<T>::lookup(lookup, 11);
-
- assertClose(LookupTable<T>::lookup(lookup, -1), LookupTable<T>::lookup(lookup, 0), .01);
- assertClose(LookupTable<T>::lookup(lookup, 11), LookupTable<T>::lookup(lookup, 10), .01);
- assertClose(LookupTable<T>::lookup(lookup, -100), LookupTable<T>::lookup(lookup, 0), .01);
- assertClose(LookupTable<T>::lookup(lookup, 1100), LookupTable<T>::lookup(lookup, 10), .01);
- }
-
-
- template<typename T>
- static void testExpTolerance(T centsTolerance)
- {
- const T xMin = (T) LookupTableFactory<T>::expXMin();
- const T xMax = (T) LookupTableFactory<T>::expXMax();
-
- LookupTableParams<T> table;
- LookupTableFactory<T>::makeExp2(table);
- for (T x = xMin; x <= xMax; x += T(.0001)) {
- T y = LookupTable<T>::lookup(table, x); // and back
- double accurate = std::pow(2.0, x);
- double errorCents = std::abs(1200.0 * std::log2(y / accurate));
- assertClose(errorCents, 0, centsTolerance);
- }
- }
-
- template <typename T>
- static void testBipolarSimpleLookup()
- {
- LookupTableParams<T> lookup;
- LookupTableFactory<T>::makeBipolarAudioTaper(lookup);
-
- assertClose(LookupTable<T>::lookup(lookup, 0), 0, .01);
- assertClose(LookupTable<T>::lookup(lookup, 1), 1, .01);
- assertClose(LookupTable<T>::lookup(lookup, -1), -1, .01);
- }
-
-
- template <typename T>
- static void testBipolarTolerance()
- {
- LookupTableParams<T> lookup;
- LookupTableFactory<T>::makeBipolarAudioTaper(lookup);
- const double toleratedError = 1 - AudioMath::gainFromDb(-.1);// let's go for one db.
- assert(toleratedError > 0);
-
- auto refFuncPos = AudioMath::makeFunc_AudioTaper(LookupTableFactory<T>::audioTaperKnee());
- auto refFuncNeg = [refFuncPos](double x) {
- assert(x <= 0);
- return -refFuncPos(-x);
- };
-
- for (double x = -1; x < 1; x += .001) {
-
- const T test = LookupTable<T>::lookup(lookup, (T) x);
- T ref = 1234;
- if (x < 0) {
- ref = (T) refFuncNeg(x);
- } else {
- ref = (T) refFuncPos(x);
- }
- assertClose(test, ref, toleratedError);
- }
- }
-
- template<typename T>
- static void test()
- {
- test0<T>();
- test1<T>();
- test2<T>();
- test3<T>();
- test4<T>();
- testDiscrete1<T>();
- testDiscrete2<T>();
- testExpSimpleLookup<T>();
- testExpTolerance<T>(100); // 1 semitone
- testExpTolerance<T>(10);
- testExpTolerance<T>(1);
- testBipolarSimpleLookup<T>();
- testBipolarTolerance<T>();
- }
-
- void testLookupTable()
- {
- test<float>();
- test<double>();
- }
|