commit b8075712de243bee774f8e7ebe94b00c035b4246
parent ab53e7a651ccbea9069ca23a1846f664acdc4a44
Author: fundamental <mark.d.mccurry@gmail.com>
Date: Sun, 25 Apr 2021 16:26:07 -0400
Remove Cxxtest dependency
Looks like upstream is now a dead project.
Rather than try to revive that in any way, let's remove one dependency.
Diffstat:
50 files changed, 4284 insertions(+), 3850 deletions(-)
diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml
@@ -16,8 +16,6 @@ jobs:
- name: install_deps2
run: sudo apt-get install liblo-dev
- name: install_test_deps1
- run: sudo apt-get install --force-yes cxxtest python3
- - name: install_test_deps2
run: sudo apt-get install ruby
- name: submodule
run: git submodule update --init
diff --git a/.travis.yml b/.travis.yml
@@ -9,7 +9,6 @@ before_install:
- sudo apt-get install zlib1g-dev libmxml-dev libfftw3-dev dssi-dev libfltk1.3-dev fluid libxpm-dev
- sudo apt-get install liblo-dev
- sudo apt-get install libsndio-dev
- - sudo apt-get install --force-yes cxxtest
script:
diff --git a/README.adoc b/README.adoc
@@ -58,7 +58,6 @@ Optional:
- ALSA
- LASH
- DSSI
-- CxxTest (for unit tests)
Sibling projects
~~~~~~~~~~~~~~~~
@@ -74,4 +73,4 @@ ZynAddSubFX is available under the GPL-2.0-or-later license.
Have fun! :-)
---The ZynAddSubFX team
-\ No newline at end of file
+--The ZynAddSubFX team
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
@@ -18,10 +18,6 @@ find_package(Alsa)
find_package(Sndio)
find_package(FLTK)
find_package(OpenGL) #for FLTK
-find_package(CxxTest)
-if(CXXTEST_FOUND)
- set(CXXTEST_USE_PYTHON TRUE)
-endif()
# lash
if(PKG_CONFIG_FOUND AND NOT (${CMAKE_SYSTEM_NAME} STREQUAL "Windows"))
message("Looking For pkg config modules")
@@ -680,7 +676,6 @@ package_status(PORTAUDIO_FOUND "PA " "found" ${Yellow})
package_status(SNDIO_FOUND "SNDIO " "found" ${Yellow})
package_status(LASH_FOUND "Lash " "found" ${Yellow})
package_status(DSSI_FOUND "DSSI " "found" ${Yellow})
-package_status(CXXTEST_FOUND "CxxTest " "found" ${Yellow})
package_status(LashEnable "Lash " "enabled" ${Yellow})
package_status(DssiEnable "DSSI " "enabled" ${Yellow})
package_status(CompileTests "tests " "enabled" ${Yellow})
diff --git a/src/Tests/AdNoteTest.cpp b/src/Tests/AdNoteTest.cpp
@@ -0,0 +1,258 @@
+/*
+ ZynAddSubFX - a software synthesizer
+ AdNoteTest.h - CxxTest for Synth/ADnote
+ Copyright (C) 2009-2011 Mark McCurry
+ Copyright (C) 2009 Harald Hvaal
+ Authors: Mark McCurry, Harald Hvaal
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+
+
+#include "test-suite.h"
+#include <iostream>
+#include <fstream>
+#include <ctime>
+#include <string>
+#include "../Misc/Master.h"
+#include "../Misc/Util.h"
+#include "../Misc/Allocator.h"
+#include "../Synth/ADnote.h"
+#include "../Params/Presets.h"
+#include "../DSP/FFTwrapper.h"
+#include "../Synth/LFO.h"
+#include "../Params/LFOParams.h"
+#include "../globals.h"
+#include <rtosc/thread-link.h>
+
+using namespace std;
+using namespace zyn;
+
+SYNTH_T *synth;
+
+
+class AdNoteTest
+{
+ public:
+ rtosc::ThreadLink *tr;
+ ADnote *note;
+ AbsTime *time;
+ FFTwrapper *fft;
+ ADnoteParameters *defaultPreset;
+ Controller *controller;
+ Alloc memory;
+ float test_freq_log2;
+ WatchManager *w;
+ float *outR, *outL;
+
+ LFO *lfo;
+ LFOParams *lfop;
+ int randval(int min, int max)
+ {
+ int ret = rand()%(1+max-min)+min;
+ //printf("ret = %d (%d..%d)\n",ret, min,max);
+ return ret;
+ }
+
+ void randomize_params(void) {
+ lfop->Pintensity = randval(0,255);
+ lfop->Pstartphase = randval(0,255);
+ lfop->Pcutoff = randval(0,127);
+ lfop->PLFOtype = randval(0,6);
+ lfop->Prandomness = randval(0,255);
+ lfop->Pfreqrand = randval(0,255);
+ lfop->Pcontinous = randval(0,1);
+ lfop->Pstretch = randval(0,255);
+ lfop->fel = (consumer_location_type_t) randval(1,2);
+
+ }
+
+ void run_lfo_randomtest(void)
+ {
+ lfo = new LFO(*lfop, 440.0f, *time);
+ for(int i=0; i<100; ++i) {
+ float out = lfo->lfoout();
+ switch(lfop->fel)
+ {
+ case consumer_location_type_t::amp:
+ TS_ASSERT((-2.0f < out && out < 2.0f));
+ break;
+ case consumer_location_type_t::filter:
+ TS_ASSERT((-8.0f < out && out < 8.0f));
+ break;
+ case consumer_location_type_t::freq:
+ case consumer_location_type_t::unspecified:
+ default:
+ break;
+ }
+ }
+ }
+
+
+
+ void setUp() {
+ //First the sensible settings and variables that have to be set:
+ synth = new SYNTH_T;
+ synth->buffersize = 256;
+ //synth->alias();
+ time = new AbsTime(*synth);
+
+ outL = new float[synth->buffersize];
+ for(int i = 0; i < synth->buffersize; ++i)
+ *(outL + i) = 0;
+ outR = new float[synth->buffersize];
+ for(int i = 0; i < synth->buffersize; ++i)
+ *(outR + i) = 0;
+
+ tr = new rtosc::ThreadLink(1024,3);
+ w = new WatchManager(tr);
+
+ fft = new FFTwrapper(synth->oscilsize);
+ //prepare the default settings
+ defaultPreset = new ADnoteParameters(*synth, fft, time);
+
+ //Assert defaults
+ TS_ASSERT(!defaultPreset->VoicePar[1].Enabled);
+
+ XMLwrapper wrap;
+ cout << string(SOURCE_DIR) + string("/guitar-adnote.xmz")
+ << endl;
+ wrap.loadXMLfile(string(SOURCE_DIR)
+ + string("/guitar-adnote.xmz"));
+ TS_ASSERT(wrap.enterbranch("MASTER"));
+ TS_ASSERT(wrap.enterbranch("PART", 0));
+ TS_ASSERT(wrap.enterbranch("INSTRUMENT"));
+ TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT"));
+ TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT_ITEM", 0));
+ TS_ASSERT(wrap.enterbranch("ADD_SYNTH_PARAMETERS"));
+ defaultPreset->getfromXML(wrap);
+ //defaultPreset->defaults();
+
+ //verify xml was loaded
+ TS_ASSERT(defaultPreset->VoicePar[1].Enabled);
+
+
+
+ controller = new Controller(*synth, time);
+
+ //lets go with.... 50! as a nice note
+ test_freq_log2 = log2f(440.0f) + (50.0 - 69.0f) / 12.0f;
+ SynthParams pars{memory, *controller, *synth, *time, 120, 0, test_freq_log2, false, prng()};
+
+ note = new ADnote(defaultPreset, pars,w);
+
+ }
+
+ void tearDown() {
+ delete note;
+ delete controller;
+ delete defaultPreset;
+ delete fft;
+ delete [] outL;
+ delete [] outR;
+ FFT_cleanup();
+ delete synth;
+ }
+
+ void testDefaults() {
+ int sampleCount = 0;
+
+//#define WRITE_OUTPUT
+
+#ifdef WRITE_OUTPUT
+ ofstream file("adnoteout", ios::out);
+#endif
+ note->noteout(outL, outR);
+#ifdef WRITE_OUTPUT
+ for(int i = 0; i < synth->buffersize; ++i)
+ file << outL[i] << std::endl;
+
+#endif
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], 0.1924f, 0.0001f);
+ note->releasekey();
+
+ TS_ASSERT(!tr->hasNext());
+ w->add_watch("noteout/be4_mix");
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], -0.4717f, 0.0001f);
+ w->tick();
+ TS_ASSERT(tr->hasNext());
+
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ w->tick();
+ TS_ASSERT_DELTA(outL[255], 0.0646f, 0.0001f);
+
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], 0.1183f, 0.0001f);
+ w->tick();
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], -0.1169f, 0.0001f);
+ w->tick();
+
+ TS_ASSERT(tr->hasNext());
+ TS_ASSERT_EQUAL_STR("noteout/be4_mix", tr->read());
+ TS_ASSERT(!tr->hasNext());
+
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+
+
+ while(!note->finished()) {
+ note->noteout(outL, outR);
+#ifdef WRITE_OUTPUT
+ for(int i = 0; i < synth->buffersize; ++i)
+ file << outL[i] << std::endl;
+
+#endif
+ sampleCount += synth->buffersize;
+ }
+#ifdef WRITE_OUTPUT
+ file.close();
+#endif
+
+ TS_ASSERT_EQUAL_INT(sampleCount, 30208);
+
+ lfop = new LFOParams();
+ lfop->fel = zyn::consumer_location_type_t::amp;
+ lfop->freq = 2.0f;
+ lfop->delay = 0.0f;
+ for(int i=0; i<10000; ++i) {
+ randomize_params();
+ run_lfo_randomtest();
+ }
+
+
+ }
+
+#define OUTPUT_PROFILE
+#ifdef OUTPUT_PROFILE
+ void testSpeed() {
+ const int samps = 15000;
+
+ int t_on = clock(); // timer before calling func
+ for(int i = 0; i < samps; ++i)
+ note->noteout(outL, outR);
+ int t_off = clock(); // timer when func returns
+
+ printf("AdNoteTest: %f seconds for %d Samples to be generated.\n",
+ (static_cast<float>(t_off - t_on)) / CLOCKS_PER_SEC, samps);
+ }
+#endif
+};
+
+int main()
+{
+ tap_quiet = 1;
+ AdNoteTest test;
+ test.setUp();
+ test.testDefaults();
+ test.tearDown();
+ return test_summary();
+}
diff --git a/src/Tests/AdNoteTest.h b/src/Tests/AdNoteTest.h
@@ -1,248 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
- AdNoteTest.h - CxxTest for Synth/ADnote
- Copyright (C) 2009-2011 Mark McCurry
- Copyright (C) 2009 Harald Hvaal
- Authors: Mark McCurry, Harald Hvaal
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-
-
-#include <cxxtest/TestSuite.h>
-#include <iostream>
-#include <fstream>
-#include <ctime>
-#include <string>
-#include "../Misc/Master.h"
-#include "../Misc/Util.h"
-#include "../Misc/Allocator.h"
-#include "../Synth/ADnote.h"
-#include "../Params/Presets.h"
-#include "../DSP/FFTwrapper.h"
-#include "../Synth/LFO.h"
-#include "../Params/LFOParams.h"
-#include "../globals.h"
-#include <rtosc/thread-link.h>
-
-using namespace std;
-using namespace zyn;
-
-SYNTH_T *synth;
-
-
-class AdNoteTest:public CxxTest::TestSuite
-{
- public:
- rtosc::ThreadLink *tr;
- ADnote *note;
- AbsTime *time;
- FFTwrapper *fft;
- ADnoteParameters *defaultPreset;
- Controller *controller;
- Alloc memory;
- float test_freq_log2;
- WatchManager *w;
- float *outR, *outL;
-
- LFO *lfo;
- LFOParams *lfop;
- int randval(int min, int max)
- {
- int ret = rand()%(1+max-min)+min;
- //printf("ret = %d (%d..%d)\n",ret, min,max);
- return ret;
- }
-
- void randomize_params(void) {
- lfop->Pintensity = randval(0,255);
- lfop->Pstartphase = randval(0,255);
- lfop->Pcutoff = randval(0,127);
- lfop->PLFOtype = randval(0,6);
- lfop->Prandomness = randval(0,255);
- lfop->Pfreqrand = randval(0,255);
- lfop->Pcontinous = randval(0,1);
- lfop->Pstretch = randval(0,255);
- lfop->fel = (consumer_location_type_t) randval(1,2);
-
- }
-
- void run_lfo_randomtest(void)
- {
- lfo = new LFO(*lfop, 440.0f, *time);
- for(int i=0; i<100; ++i) {
- float out = lfo->lfoout();
- switch(lfop->fel)
- {
- case consumer_location_type_t::amp:
- TS_ASSERT((-2.0f < out && out < 2.0f));
- break;
- case consumer_location_type_t::filter:
- TS_ASSERT((-8.0f < out && out < 8.0f));
- break;
- case consumer_location_type_t::freq:
- case consumer_location_type_t::unspecified:
- default:
- break;
- }
- }
- }
-
-
-
- void setUp() {
- //First the sensible settings and variables that have to be set:
- synth = new SYNTH_T;
- synth->buffersize = 256;
- //synth->alias();
- time = new AbsTime(*synth);
-
- outL = new float[synth->buffersize];
- for(int i = 0; i < synth->buffersize; ++i)
- *(outL + i) = 0;
- outR = new float[synth->buffersize];
- for(int i = 0; i < synth->buffersize; ++i)
- *(outR + i) = 0;
-
- tr = new rtosc::ThreadLink(1024,3);
- w = new WatchManager(tr);
-
- fft = new FFTwrapper(synth->oscilsize);
- //prepare the default settings
- defaultPreset = new ADnoteParameters(*synth, fft, time);
-
- //Assert defaults
- TS_ASSERT(!defaultPreset->VoicePar[1].Enabled);
-
- XMLwrapper wrap;
- cout << string(SOURCE_DIR) + string("/guitar-adnote.xmz")
- << endl;
- wrap.loadXMLfile(string(SOURCE_DIR)
- + string("/guitar-adnote.xmz"));
- TS_ASSERT(wrap.enterbranch("MASTER"));
- TS_ASSERT(wrap.enterbranch("PART", 0));
- TS_ASSERT(wrap.enterbranch("INSTRUMENT"));
- TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT"));
- TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT_ITEM", 0));
- TS_ASSERT(wrap.enterbranch("ADD_SYNTH_PARAMETERS"));
- defaultPreset->getfromXML(wrap);
- //defaultPreset->defaults();
-
- //verify xml was loaded
- TS_ASSERT(defaultPreset->VoicePar[1].Enabled);
-
-
-
- controller = new Controller(*synth, time);
-
- //lets go with.... 50! as a nice note
- test_freq_log2 = log2f(440.0f) + (50.0 - 69.0f) / 12.0f;
- SynthParams pars{memory, *controller, *synth, *time, 120, 0, test_freq_log2, false, prng()};
-
- note = new ADnote(defaultPreset, pars,w);
-
- }
-
- void tearDown() {
- delete note;
- delete controller;
- delete defaultPreset;
- delete fft;
- delete [] outL;
- delete [] outR;
- FFT_cleanup();
- delete synth;
- }
-
- void testDefaults() {
- int sampleCount = 0;
-
-//#define WRITE_OUTPUT
-
-#ifdef WRITE_OUTPUT
- ofstream file("adnoteout", ios::out);
-#endif
- note->noteout(outL, outR);
-#ifdef WRITE_OUTPUT
- for(int i = 0; i < synth->buffersize; ++i)
- file << outL[i] << std::endl;
-
-#endif
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], 0.1924f, 0.0001f);
- note->releasekey();
-
- TS_ASSERT(!tr->hasNext());
- w->add_watch("noteout/be4_mix");
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], -0.4717f, 0.0001f);
- w->tick();
- TS_ASSERT(tr->hasNext());
-
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- w->tick();
- TS_ASSERT_DELTA(outL[255], 0.0646f, 0.0001f);
-
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], 0.1183f, 0.0001f);
- w->tick();
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], -0.1169f, 0.0001f);
- w->tick();
-
- TS_ASSERT(tr->hasNext());
- TS_ASSERT_EQUALS(string("noteout/be4_mix"), tr->read());
- TS_ASSERT(!tr->hasNext());
-
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
-
-
- while(!note->finished()) {
- note->noteout(outL, outR);
-#ifdef WRITE_OUTPUT
- for(int i = 0; i < synth->buffersize; ++i)
- file << outL[i] << std::endl;
-
-#endif
- sampleCount += synth->buffersize;
- }
-#ifdef WRITE_OUTPUT
- file.close();
-#endif
-
- TS_ASSERT_EQUALS(sampleCount, 30208);
-
- lfop = new LFOParams();
- lfop->fel = zyn::consumer_location_type_t::amp;
- lfop->freq = 2.0f;
- lfop->delay = 0.0f;
- for(int i=0; i<10000; ++i) {
- randomize_params();
- run_lfo_randomtest();
- }
-
-
- }
-
-#define OUTPUT_PROFILE
-#ifdef OUTPUT_PROFILE
- void testSpeed() {
- const int samps = 15000;
-
- int t_on = clock(); // timer before calling func
- for(int i = 0; i < samps; ++i)
- note->noteout(outL, outR);
- int t_off = clock(); // timer when func returns
-
- printf("AdNoteTest: %f seconds for %d Samples to be generated.\n",
- (static_cast<float>(t_off - t_on)) / CLOCKS_PER_SEC, samps);
- }
-#endif
-};
diff --git a/src/Tests/AllocatorTest.cpp b/src/Tests/AllocatorTest.cpp
@@ -0,0 +1,116 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ AllocatorTest.h - CxxTest for RT Memory Allocator
+ Copyright (C) 2014-2014 Mark McCurry
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+
+
+#include "test-suite.h"
+#include <iostream>
+#include <fstream>
+#include <ctime>
+#include <cstring>
+#include <string>
+#include <vector>
+#include "../Misc/Allocator.h"
+//using namespace std;
+using std::vector;
+using namespace zyn;
+
+class AllocatorTest
+{
+ public:
+ Allocator *memory_;
+ vector<void*> data;
+
+ void setUp() {
+ memory_ = new AllocatorClass();
+ }
+
+ void tearDown() {
+ delete memory_;
+ }
+
+ void testBasic() {
+ Allocator &memory = *memory_;
+ char *d = (char*)memory.alloc_mem(128);
+ TS_NON_NULL(d);
+ d[0] = 0;
+ d[127] = 0;
+ memory.dealloc_mem(d);
+ }
+
+ void testTooBig() {
+ Allocator &memory = *memory_;
+ //Try to allocate a gig
+ char *d = (char*)memory.alloc_mem(1024*1024*1024);
+ TS_ASSERT(d==nullptr);
+ }
+
+ void testEnlarge()
+ {
+ Allocator &memory = *memory_;
+ //Additional Buffers
+ size_t N = 50*1024*1024;
+ char *bufA = (char*)malloc(N);
+ char *bufB = (char*)malloc(N);
+ memset(bufA,0xff, N);
+ memset(bufB,0xff, N);
+
+
+ //By default 25MBi is too large
+ //Therefore this allocation should fail
+ bool low = memory.lowMemory(5,5*1024*1024);
+ TS_ASSERT(low);
+ TS_ASSERT(memory.memPools() == 1);
+
+
+ //Try to add a buffer
+ //This provides enough for the low memory check to pass
+ memory.addMemory(bufA, N);
+ TS_ASSERT(memory.memPools() == 2);
+ TS_ASSERT(memory.memFree(bufA));
+ bool low2 = memory.lowMemory(5,5*1024*1024);
+ TS_ASSERT(!low2);
+ TS_ASSERT(memory.memFree(bufA));
+
+ //We should be able to see that a chunk enters and exits the free
+ //state
+ char *mem2 = (char*)memory.alloc_mem(10*1024*1024);
+ TS_NON_NULL(mem2);
+ TS_ASSERT(!memory.memFree(bufA));
+ memory.dealloc_mem(mem2);
+ TS_ASSERT(memory.memFree(bufA));
+ mem2 = (char*)memory.alloc_mem(10*1024*1024);
+ char *mem3 = (char*)memory.alloc_mem(10*1024*1024);
+ TS_NON_NULL(mem3);
+ memory.dealloc_mem(mem2);
+ TS_ASSERT(!memory.memFree(bufA));
+ TS_ASSERT(memory.freePools() == 0);
+ memory.dealloc_mem(mem3);
+ TS_ASSERT(memory.memFree(bufA));
+ TS_ASSERT(memory.freePools() == 1);
+
+ //Observe that adding another pool superficially works
+ memory.addMemory(bufB, N);
+ TS_ASSERT(memory.freePools() == 2);
+
+ //delete [] bufA;
+ //delete [] bufB;
+ }
+
+};
+
+int main()
+{
+ AllocatorTest test;
+ RUN_TEST(testBasic);
+ RUN_TEST(testTooBig);
+ RUN_TEST(testEnlarge);
+}
diff --git a/src/Tests/AllocatorTest.h b/src/Tests/AllocatorTest.h
@@ -1,108 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- AllocatorTest.h - CxxTest for RT Memory Allocator
- Copyright (C) 2014-2014 Mark McCurry
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-
-
-#include <cxxtest/TestSuite.h>
-#include <iostream>
-#include <fstream>
-#include <ctime>
-#include <cstring>
-#include <string>
-#include <vector>
-#include "../Misc/Allocator.h"
-//using namespace std;
-using std::vector;
-using namespace zyn;
-
-class AllocatorTest:public CxxTest::TestSuite
-{
- public:
- Allocator *memory_;
- vector<void*> data;
-
- void setUp() {
- memory_ = new AllocatorClass();
- }
-
- void tearDown() {
- delete memory_;
- }
-
- void testBasic() {
- Allocator &memory = *memory_;
- char *d = (char*)memory.alloc_mem(128);
- TS_ASSERT(d);
- d[0] = 0;
- d[127] = 0;
- memory.dealloc_mem(d);
- }
-
- void testTooBig() {
- Allocator &memory = *memory_;
- //Try to allocate a gig
- char *d = (char*)memory.alloc_mem(1024*1024*1024);
- TS_ASSERT(d==nullptr);
- }
-
- void testEnlarge()
- {
- Allocator &memory = *memory_;
- //Additional Buffers
- size_t N = 50*1024*1024;
- char *bufA = (char*)malloc(N);
- char *bufB = (char*)malloc(N);
- memset(bufA,0xff, N);
- memset(bufB,0xff, N);
-
-
- //By default 25MBi is too large
- //Therefore this allocation should fail
- bool low = memory.lowMemory(5,5*1024*1024);
- TS_ASSERT(low);
- TS_ASSERT(memory.memPools() == 1);
-
-
- //Try to add a buffer
- //This provides enough for the low memory check to pass
- memory.addMemory(bufA, N);
- TS_ASSERT(memory.memPools() == 2);
- TS_ASSERT(memory.memFree(bufA));
- bool low2 = memory.lowMemory(5,5*1024*1024);
- TS_ASSERT(!low2);
- TS_ASSERT(memory.memFree(bufA));
-
- //We should be able to see that a chunk enters and exits the free
- //state
- char *mem2 = (char*)memory.alloc_mem(10*1024*1024);
- TS_ASSERT(mem2);
- TS_ASSERT(!memory.memFree(bufA));
- memory.dealloc_mem(mem2);
- TS_ASSERT(memory.memFree(bufA));
- mem2 = (char*)memory.alloc_mem(10*1024*1024);
- char *mem3 = (char*)memory.alloc_mem(10*1024*1024);
- TS_ASSERT(mem3);
- memory.dealloc_mem(mem2);
- TS_ASSERT(!memory.memFree(bufA));
- TS_ASSERT(memory.freePools() == 0);
- memory.dealloc_mem(mem3);
- TS_ASSERT(memory.memFree(bufA));
- TS_ASSERT(memory.freePools() == 1);
-
- //Observe that adding another pool superficially works
- memory.addMemory(bufB, N);
- TS_ASSERT(memory.freePools() == 2);
-
- //delete [] bufA;
- //delete [] bufB;
- }
-
-};
diff --git a/src/Tests/CMakeLists.txt b/src/Tests/CMakeLists.txt
@@ -3,72 +3,51 @@ function(cp_script script_name)
${CMAKE_CURRENT_BINARY_DIR}/${script_name} COPYONLY)
endfunction()
+function(quick_test test_name link)
+ add_executable(${test_name} "${test_name}.cpp")
+ add_test(NAME ${test_name}
+ COMMAND ${test_name})
+ target_link_libraries(${test_name} ${link} ${ARGN})
+endfunction()
+
#for tests looking for files stored in the source dir
add_definitions(-DSOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
-CXXTEST_ADD_TEST(ControllerTest ControllerTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ControllerTest.h)
-CXXTEST_ADD_TEST(EchoTest EchoTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/EchoTest.h)
-#CXXTEST_ADD_TEST(SampleTest SampleTest.h)
-CXXTEST_ADD_TEST(MicrotonalTest MicrotonalTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MicrotonalTest.h)
-CXXTEST_ADD_TEST(XMLwrapperTest XMLwrapper.cpp ${CMAKE_CURRENT_SOURCE_DIR}/XMLwrapperTest.h)
-CXXTEST_ADD_TEST(ADnoteTest AdNoteTest.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/AdNoteTest.h)
-CXXTEST_ADD_TEST(SUBnoteTest SubNoteTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/SubNoteTest.h)
-CXXTEST_ADD_TEST(OscilGenTest OscilGenTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/OscilGenTest.h)
-CXXTEST_ADD_TEST(RandTest RandTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RandTest.h)
-CXXTEST_ADD_TEST(PADnoteTest PadNoteTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PadNoteTest.h)
-CXXTEST_ADD_TEST(PluginTest PluginTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/PluginTest.h)
-CXXTEST_ADD_TEST(MsgParseTest MsgParseTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MsgParseTest.h)
-CXXTEST_ADD_TEST(MiddlewareTest MiddlewareTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareTest.h)
-CXXTEST_ADD_TEST(MessageTest MessageTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MessageTest.h)
-CXXTEST_ADD_TEST(UnisonTest UnisonTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/UnisonTest.h)
-CXXTEST_ADD_TEST(MqTest MqTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/MqTest.h)
-CXXTEST_ADD_TEST(WatchTest WatchTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/WatchTest.h)
-#CXXTEST_ADD_TEST(RtAllocTest RtAllocTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RtAllocTest.h)
-CXXTEST_ADD_TEST(AllocatorTest AllocatorTest.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/AllocatorTest.h)
-CXXTEST_ADD_TEST(EffectTest EffectTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/EffectTest.h)
-CXXTEST_ADD_TEST(KitTest KitTest.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/KitTest.h)
-CXXTEST_ADD_TEST(MemoryStressTest MemoryStressTest.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/MemoryStressTest.h)
-CXXTEST_ADD_TEST(TriggerTest TriggerTest.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/TriggerTest.h)
-
#Extra libraries added to make test and full compilation use the same library
#links for quirky compilers
set(test_lib zynaddsubfx_core ${GUI_LIBRARIES} ${ZLIB_LIBRARY} ${FFTW_LIBRARIES}
${MXML_LIBRARIES} pthread "-Wl,--no-as-needed -lpthread")
message(STATUS "Linking tests with: ${test_lib}")
-target_link_libraries(ADnoteTest ${test_lib})
-target_link_libraries(SUBnoteTest ${test_lib})
-target_link_libraries(ControllerTest ${test_lib})
-target_link_libraries(EchoTest ${test_lib})
-target_link_libraries(MicrotonalTest ${test_lib})
-target_link_libraries(OscilGenTest ${test_lib})
-target_link_libraries(XMLwrapperTest ${test_lib})
-target_link_libraries(RandTest ${test_lib})
-target_link_libraries(PADnoteTest ${test_lib})
-target_link_libraries(MqTest ${test_lib})
-target_link_libraries(WatchTest ${test_lib})
-target_link_libraries(TriggerTest ${test_lib})
-target_link_libraries(PluginTest zynaddsubfx_core zynaddsubfx_nio
- zynaddsubfx_gui_bridge
- ${GUI_LIBRARIES} ${NIO_LIBRARIES} ${AUDIO_LIBRARIES})
-target_link_libraries(MsgParseTest ${test_lib})
-target_link_libraries(MiddlewareTest zynaddsubfx_core zynaddsubfx_nio
- zynaddsubfx_gui_bridge
- ${GUI_LIBRARIES} ${NIO_LIBRARIES} ${AUDIO_LIBRARIES})
-target_link_libraries(MessageTest zynaddsubfx_core zynaddsubfx_nio
- zynaddsubfx_gui_bridge
- ${GUI_LIBRARIES} ${NIO_LIBRARIES} ${AUDIO_LIBRARIES})
-target_link_libraries(UnisonTest ${test_lib})
-#target_link_libraries(RtAllocTest ${test_lib})
-target_link_libraries(AllocatorTest ${test_lib})
-target_link_libraries(KitTest ${test_lib})
-target_link_libraries(MemoryStressTest ${test_lib})
-target_link_libraries(EffectTest ${test_lib})
+
+quick_test(AdNoteTest ${test_lib})
+quick_test(AllocatorTest ${test_lib})
+quick_test(ControllerTest ${test_lib})
+quick_test(EchoTest ${test_lib})
+quick_test(EffectTest ${test_lib})
+quick_test(KitTest ${test_lib})
+quick_test(MemoryStressTest ${test_lib})
+quick_test(MicrotonalTest ${test_lib})
+quick_test(MsgParseTest ${test_lib})
+quick_test(MqTest ${test_lib})
+quick_test(OscilGenTest ${test_lib})
+quick_test(PadNoteTest ${test_lib})
+quick_test(RandTest ${test_lib})
+quick_test(SubNoteTest ${test_lib})
+quick_test(TriggerTest ${test_lib})
+quick_test(UnisonTest ${test_lib})
+quick_test(WatchTest ${test_lib})
+quick_test(XMLwrapperTest ${test_lib})
+
+quick_test(PluginTest zynaddsubfx_core zynaddsubfx_nio
+ zynaddsubfx_gui_bridge
+ ${GUI_LIBRARIES} ${NIO_LIBRARIES} ${AUDIO_LIBRARIES})
+quick_test(MiddlewareTest zynaddsubfx_core zynaddsubfx_nio
+ zynaddsubfx_gui_bridge
+ ${GUI_LIBRARIES} ${NIO_LIBRARIES} ${AUDIO_LIBRARIES})
+quick_test(MessageTest zynaddsubfx_core zynaddsubfx_nio
+ zynaddsubfx_gui_bridge
+ ${GUI_LIBRARIES} ${NIO_LIBRARIES} ${AUDIO_LIBRARIES})
#Testbed app
add_executable(ins-test InstrumentStats.cpp)
@@ -86,6 +65,3 @@ target_link_libraries(save-osc
${GUI_LIBRARIES} ${NIO_LIBRARIES} ${AUDIO_LIBRARIES})
#this will be replaced with a for loop when the code will get more stable:
add_test(SaveOsc save-osc ${CMAKE_CURRENT_SOURCE_DIR}/../../instruments/examples/Arpeggio\ 1.xmz)
-
-#message(STATUS "Plugin Test ${GUI_LIBRARIES} ${NIO_LIBRARIES} ${AUDIO_LIBRARIES}")
-
diff --git a/src/Tests/ControllerTest.cpp b/src/Tests/ControllerTest.cpp
@@ -0,0 +1,79 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ ControllerTest.h - CxxTest for Params/Controller
+ Copyright (C) 2009-2011 Mark McCurry
+ Author: Mark McCurry
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+#include "test-suite.h"
+#include <cmath>
+#include <iostream>
+#include "../Params/Controller.h"
+#include "../globals.h"
+#include "../Misc/Time.h"
+using namespace zyn;
+
+SYNTH_T *synth;
+
+class ControllerTest
+{
+ public:
+ void setUp() {
+ synth = new SYNTH_T;
+ AbsTime time(*synth);
+ testCtl = new Controller(*synth, &time);
+ }
+
+ void tearDown() {
+ delete testCtl;
+ delete synth;
+ }
+
+
+ void testPortamentoRange() {
+ //Initialize portamento
+ testCtl->setportamento(127);
+ testCtl->portamento.time = 127;
+ testCtl->initportamento(log2f(40.0f), log2f(400.0f), false);
+ //Bounds Check
+ while(testCtl->portamento.used) {
+ TS_ASSERT((0.0f <= testCtl->portamento.x)
+ && (testCtl->portamento.x <= 1.0f));
+ TS_ASSERT((log2f(0.1f) <= testCtl->portamento.freqdelta_log2)
+ && (testCtl->portamento.freqdelta_log2 <= log2f(1.0f)));
+ testCtl->updateportamento();
+ }
+ TS_ASSERT((0.0f <= testCtl->portamento.x)
+ && (testCtl->portamento.x <= 1.0f));
+ TS_ASSERT((log2f(0.1f) <= testCtl->portamento.freqdelta_log2)
+ && (testCtl->portamento.freqdelta_log2 <= log2f(1.0f)));
+ }
+
+ void testPortamentoValue() {
+ testCtl->setportamento(127);
+ testCtl->portamento.time = 127;
+ testCtl->initportamento(log2f(40.0f), log2f(400.0f), false);
+ int i;
+ for(i = 0; i < 10; ++i)
+ testCtl->updateportamento();
+ //Assert that the numbers are the same as they were at release
+ TS_ASSERT_DELTA(testCtl->portamento.x, 0.0290249f, 0.000001f);
+ TS_ASSERT_DELTA(testCtl->portamento.freqdelta_log2, -3.2255092, 0.000001f);
+ }
+
+ private:
+ Controller *testCtl;
+};
+
+int main()
+{
+ ControllerTest test;
+ RUN_TEST(testPortamentoRange);
+ RUN_TEST(testPortamentoValue);
+ return test_summary();
+}
diff --git a/src/Tests/ControllerTest.h b/src/Tests/ControllerTest.h
@@ -1,70 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- ControllerTest.h - CxxTest for Params/Controller
- Copyright (C) 2009-2011 Mark McCurry
- Author: Mark McCurry
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-#include <cxxtest/TestSuite.h>
-#include <iostream>
-#include "../Params/Controller.h"
-#include "../globals.h"
-#include "../Misc/Time.h"
-using namespace zyn;
-
-SYNTH_T *synth;
-
-class ControllerTest:public CxxTest::TestSuite
-{
- public:
- void setUp() {
- synth = new SYNTH_T;
- AbsTime time(*synth);
- testCtl = new Controller(*synth, &time);
- }
-
- void tearDown() {
- delete testCtl;
- delete synth;
- }
-
-
- void testPortamentoRange() {
- //Initialize portamento
- testCtl->setportamento(127);
- testCtl->portamento.time = 127;
- testCtl->initportamento(log2f(40.0f), log2f(400.0f), false);
- //Bounds Check
- while(testCtl->portamento.used) {
- TS_ASSERT((0.0f <= testCtl->portamento.x)
- && (testCtl->portamento.x <= 1.0f));
- TS_ASSERT((log2f(0.1f) <= testCtl->portamento.freqdelta_log2)
- && (testCtl->portamento.freqdelta_log2 <= log2f(1.0f)));
- testCtl->updateportamento();
- }
- TS_ASSERT((0.0f <= testCtl->portamento.x)
- && (testCtl->portamento.x <= 1.0f));
- TS_ASSERT((log2f(0.1f) <= testCtl->portamento.freqdelta_log2)
- && (testCtl->portamento.freqdelta_log2 <= log2f(1.0f)));
- }
-
- void testPortamentoValue() {
- testCtl->setportamento(127);
- testCtl->portamento.time = 127;
- testCtl->initportamento(log2f(40.0f), log2f(400.0f), false);
- int i;
- for(i = 0; i < 10; ++i)
- testCtl->updateportamento();
- //Assert that the numbers are the same as they were at release
- TS_ASSERT_DELTA(testCtl->portamento.x, 0.0290249f, 0.000001f)
- TS_ASSERT_DELTA(testCtl->portamento.freqdelta_log2, -3.2255092, 0.000001f)
- }
-
- private:
- Controller *testCtl;
-};
diff --git a/src/Tests/EchoTest.cpp b/src/Tests/EchoTest.cpp
@@ -0,0 +1,132 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ EchoTest.h - CxxTest for Effect/Echo
+ Copyright (C) 2009-2011 Mark McCurry
+ Copyright (C) 2009 Harald Hvaal
+ Authors: Mark McCurry, Harald Hvaal
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+#include "test-suite.h"
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+#include "../Effects/Echo.h"
+#include "../Misc/Allocator.h"
+#include "../globals.h"
+
+using namespace std;
+using namespace zyn;
+
+SYNTH_T *synth;
+
+class EchoTest
+{
+ public:
+ void setUp() {
+ synth = new SYNTH_T;
+ outL = new float[synth->buffersize];
+ for(int i = 0; i < synth->buffersize; ++i)
+ outL[i] = 0.0f;
+ outR = new float[synth->buffersize];
+ for(int i = 0; i < synth->buffersize; ++i)
+ outR[i] = 0.0f;
+ input = new Stereo<float *>(new float[synth->buffersize],
+ new float[synth->buffersize]);
+ for(int i = 0; i < synth->buffersize; ++i)
+ input->l[i] = input->r[i] = 0.0f;
+ EffectParams pars{alloc,true, outL, outR, 0, 44100, 256, nullptr};
+ testFX = new Echo(pars);
+ }
+
+ void tearDown() {
+ delete[] input->r;
+ delete[] input->l;
+ delete input;
+ delete[] outL;
+ delete[] outR;
+ delete testFX;
+ delete synth;
+ }
+
+
+ void testInit() {
+ //Make sure that the output will be zero at start
+ //(given a zero input)
+ testFX->out(*input);
+ for(int i = 0; i < synth->buffersize; ++i) {
+ TS_ASSERT_DELTA(outL[i], 0.0f, 0.0001f);
+ TS_ASSERT_DELTA(outR[i], 0.0f, 0.0001f);
+ }
+ }
+
+ void testClear() {
+ char DELAY = 2;
+ testFX->changepar(DELAY, 127);
+
+ //flood with high input
+ for(int i = 0; i < synth->buffersize; ++i)
+ input->r[i] = input->l[i] = 1.0f;
+
+ for(int i = 0; i < 500; ++i)
+ testFX->out(*input);
+ for(int i = 0; i < synth->buffersize; ++i) {
+ TS_ASSERT(outL[i] != 0.0f);
+ TS_ASSERT(outR[i] != 0.0f);
+ }
+ //After making sure the internal buffer has a nonzero value
+ //cleanup
+ //Then get the next output, which should be zereoed out if DELAY
+ //is large enough
+ testFX->cleanup();
+ testFX->out(*input);
+ for(int i = 0; i < synth->buffersize; ++i) {
+ TS_ASSERT_DELTA(outL[i], 0.0f, 0.0001f);
+ TS_ASSERT_DELTA(outR[i], 0.0f, 0.0001f);
+ }
+ }
+ //Insures that the proper decay occurs with high feedback
+ void testDecaywFb() {
+ //flood with high input
+ for(int i = 0; i < synth->buffersize; ++i)
+ input->r[i] = input->l[i] = 1.0f;
+ char FEEDBACK = 5;
+ testFX->changepar(FEEDBACK, 127);
+ for(int i = 0; i < 100; ++i)
+ testFX->out(*input);
+ for(int i = 0; i < synth->buffersize; ++i) {
+ TS_ASSERT(outL[i] != 0.0f);
+ TS_ASSERT(outR[i] != 0.0f);
+ }
+ float amp = abs(outL[0] + outR[0]) / 2;
+ //reset input to zero
+ for(int i = 0; i < synth->buffersize; ++i)
+ input->r[i] = input->l[i] = 0.0f;
+
+ //give the echo time to fade based upon zero input and high feedback
+ for(int i = 0; i < 50; ++i)
+ testFX->out(*input);
+ TS_ASSERT(abs(outL[0] + outR[0]) / 2 <= amp);
+ }
+
+
+ private:
+ Stereo<float *> *input;
+ float *outR, *outL;
+ Echo *testFX;
+ Alloc alloc;
+};
+
+int main()
+{
+ tap_quiet = 1;
+ EchoTest test;
+ RUN_TEST(testInit);
+ RUN_TEST(testClear);
+ RUN_TEST(testDecaywFb);
+ return test_summary();
+}
diff --git a/src/Tests/EchoTest.h b/src/Tests/EchoTest.h
@@ -1,122 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- EchoTest.h - CxxTest for Effect/Echo
- Copyright (C) 2009-2011 Mark McCurry
- Copyright (C) 2009 Harald Hvaal
- Authors: Mark McCurry, Harald Hvaal
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-#include <cxxtest/TestSuite.h>
-#include <cmath>
-#include <cstdlib>
-#include <iostream>
-#include "../Effects/Echo.h"
-#include "../Misc/Allocator.h"
-#include "../globals.h"
-
-using namespace std;
-using namespace zyn;
-
-SYNTH_T *synth;
-
-class EchoTest:public CxxTest::TestSuite
-{
- public:
- void setUp() {
- synth = new SYNTH_T;
- outL = new float[synth->buffersize];
- for(int i = 0; i < synth->buffersize; ++i)
- outL[i] = 0.0f;
- outR = new float[synth->buffersize];
- for(int i = 0; i < synth->buffersize; ++i)
- outR[i] = 0.0f;
- input = new Stereo<float *>(new float[synth->buffersize],
- new float[synth->buffersize]);
- for(int i = 0; i < synth->buffersize; ++i)
- input->l[i] = input->r[i] = 0.0f;
- EffectParams pars{alloc,true, outL, outR, 0, 44100, 256, nullptr};
- testFX = new Echo(pars);
- }
-
- void tearDown() {
- delete[] input->r;
- delete[] input->l;
- delete input;
- delete[] outL;
- delete[] outR;
- delete testFX;
- delete synth;
- }
-
-
- void testInit() {
- //Make sure that the output will be zero at start
- //(given a zero input)
- testFX->out(*input);
- for(int i = 0; i < synth->buffersize; ++i) {
- TS_ASSERT_DELTA(outL[i], 0.0f, 0.0001f);
- TS_ASSERT_DELTA(outR[i], 0.0f, 0.0001f);
- }
- }
-
- void testClear() {
- char DELAY = 2;
- testFX->changepar(DELAY, 127);
-
- //flood with high input
- for(int i = 0; i < synth->buffersize; ++i)
- input->r[i] = input->l[i] = 1.0f;
-
- for(int i = 0; i < 500; ++i)
- testFX->out(*input);
- for(int i = 0; i < synth->buffersize; ++i) {
- TS_ASSERT_DIFFERS(outL[i], 0.0f);
- TS_ASSERT_DIFFERS(outR[i], 0.0f)
- }
- //After making sure the internal buffer has a nonzero value
- //cleanup
- //Then get the next output, which should be zereoed out if DELAY
- //is large enough
- testFX->cleanup();
- testFX->out(*input);
- for(int i = 0; i < synth->buffersize; ++i) {
- TS_ASSERT_DELTA(outL[i], 0.0f, 0.0001f);
- TS_ASSERT_DELTA(outR[i], 0.0f, 0.0001f);
- }
- }
- //Insures that the proper decay occurs with high feedback
- void testDecaywFb() {
- //flood with high input
- for(int i = 0; i < synth->buffersize; ++i)
- input->r[i] = input->l[i] = 1.0f;
- char FEEDBACK = 5;
- testFX->changepar(FEEDBACK, 127);
- for(int i = 0; i < 100; ++i)
- testFX->out(*input);
- for(int i = 0; i < synth->buffersize; ++i) {
- TS_ASSERT_DIFFERS(outL[i], 0.0f);
- TS_ASSERT_DIFFERS(outR[i], 0.0f)
- }
- float amp = abs(outL[0] + outR[0]) / 2;
- //reset input to zero
- for(int i = 0; i < synth->buffersize; ++i)
- input->r[i] = input->l[i] = 0.0f;
-
- //give the echo time to fade based upon zero input and high feedback
- for(int i = 0; i < 50; ++i)
- testFX->out(*input);
- TS_ASSERT_LESS_THAN_EQUALS(abs(outL[0] + outR[0]) / 2, amp);
- }
-
-
- private:
- Stereo<float *> *input;
- float *outR, *outL;
- Echo *testFX;
- Alloc alloc;
-};
diff --git a/src/Tests/EffectTest.cpp b/src/Tests/EffectTest.cpp
@@ -0,0 +1,95 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ EffectTest.h - CxxTest for General Effect Stuff
+ Copyright (C) 2015 Mark McCurry
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+#include "test-suite.h"
+#include <cmath>
+#include <cstdio>
+#include "../Misc/Allocator.h"
+#include "../Misc/Stereo.h"
+#include "../Effects/EffectMgr.h"
+#include "../Effects/Reverb.h"
+#include "../Effects/Echo.h"
+#include "../globals.h"
+using namespace zyn;
+
+SYNTH_T *synth;
+
+class EffectTest
+{
+ public:
+ void setUp() {
+ synth = new SYNTH_T;
+ alloc = new AllocatorClass;
+ mgr = new EffectMgr(*alloc, *synth, true);
+ }
+
+ void tearDown() {
+ delete mgr;
+ delete alloc;
+ delete synth;
+ }
+
+ void testInit() {
+ TS_ASSERT_EQUAL_INT(mgr->nefx, 0);
+ mgr->changeeffect(1);
+ TS_ASSERT_EQUAL_INT(mgr->nefx, 1);
+ assert_ptr_eq(mgr->efx, nullptr,
+ "nothing before init", __LINE__);
+ mgr->init();
+ TS_NON_NULL(mgr->efx);
+ }
+
+ void testClear() {
+ mgr->changeeffect(1);
+ mgr->init();
+ TS_NON_NULL(mgr->efx);
+ mgr->changeeffect(0);
+ mgr->init();
+ assert_ptr_eq(mgr->efx, nullptr,
+ "nothing after clearing", __LINE__);
+ }
+
+ void testSwap() {
+ //Initially the effect is NULL
+ assert_ptr_eq(mgr->efx, nullptr,
+ "initially null", __LINE__);
+
+ //A Reverb is selected
+ mgr->changeeffect(1);
+ mgr->init();
+ TS_NON_NULL(dynamic_cast<Reverb*>(mgr->efx));
+ assert_ptr_eq(dynamic_cast<Echo*>(mgr->efx),
+ nullptr,
+ "not an echo", __LINE__);
+
+ //An Echo is selected
+ mgr->changeeffect(2);
+ mgr->init();
+ assert_ptr_eq(dynamic_cast<Reverb*>(mgr->efx),
+ nullptr,
+ "not a reverb", __LINE__);
+ TS_NON_NULL(dynamic_cast<Echo*>(mgr->efx));
+ }
+
+ private:
+ EffectMgr *mgr;
+ Allocator *alloc;
+ SYNTH_T *synth;
+};
+
+int main()
+{
+ EffectTest test;
+ RUN_TEST(testInit);
+ RUN_TEST(testClear);
+ RUN_TEST(testSwap);
+ return test_summary();
+}
diff --git a/src/Tests/EffectTest.h b/src/Tests/EffectTest.h
@@ -1,79 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- EffectTest.h - CxxTest for General Effect Stuff
- Copyright (C) 2015 Mark McCurry
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-#include <cxxtest/TestSuite.h>
-#include <cmath>
-#include <cstdio>
-#include "../Misc/Allocator.h"
-#include "../Misc/Stereo.h"
-#include "../Effects/EffectMgr.h"
-#include "../Effects/Reverb.h"
-#include "../Effects/Echo.h"
-#include "../globals.h"
-using namespace zyn;
-
-SYNTH_T *synth;
-
-class EchoTest:public CxxTest::TestSuite
-{
- public:
- void setUp() {
- synth = new SYNTH_T;
- alloc = new AllocatorClass;
- mgr = new EffectMgr(*alloc, *synth, true);
- }
-
- void tearDown() {
- delete mgr;
- delete alloc;
- delete synth;
- }
-
- void testInit() {
- TS_ASSERT_EQUALS(mgr->nefx, 0);
- mgr->changeeffect(1);
- TS_ASSERT_EQUALS(mgr->nefx, 1);
- TS_ASSERT_EQUALS(mgr->efx, nullptr);
- mgr->init();
- TS_ASSERT_DIFFERS(mgr->efx, nullptr);
- }
-
- void testClear() {
- mgr->changeeffect(1);
- mgr->init();
- TS_ASSERT_DIFFERS(mgr->efx, nullptr);
- mgr->changeeffect(0);
- mgr->init();
- TS_ASSERT_EQUALS(mgr->efx, nullptr);
- }
-
- void testSwap() {
- //Initially the effect is NULL
- TS_ASSERT_EQUALS(mgr->efx, nullptr);
-
- //A Reverb is selected
- mgr->changeeffect(1);
- mgr->init();
- TS_ASSERT_DIFFERS(dynamic_cast<Reverb*>(mgr->efx), nullptr);
- TS_ASSERT_EQUALS(dynamic_cast<Echo*>(mgr->efx), nullptr);
-
- //An Echo is selected
- mgr->changeeffect(2);
- mgr->init();
- TS_ASSERT_EQUALS(dynamic_cast<Reverb*>(mgr->efx), nullptr);
- TS_ASSERT_DIFFERS(dynamic_cast<Echo*>(mgr->efx), nullptr);
- }
-
- private:
- EffectMgr *mgr;
- Allocator *alloc;
- SYNTH_T *synth;
-};
diff --git a/src/Tests/KitTest.cpp b/src/Tests/KitTest.cpp
@@ -0,0 +1,795 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ KitTest.h - Test For Note Allocation Under Kits
+ Copyright (C) 2016 Mark McCurry
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+#include "test-suite.h"
+#include <cmath>
+#include <cstring>
+#include <cstdlib>
+#include <iostream>
+#include "../Misc/Time.h"
+#include "../Misc/Allocator.h"
+#include "../DSP/FFTwrapper.h"
+#include "../Misc/Microtonal.h"
+#define private public
+#define protected public
+#include "../Synth/SynthNote.h"
+#include "../Misc/Part.h"
+#include "../globals.h"
+
+using namespace std;
+using namespace zyn;
+
+SYNTH_T *synth;
+int dummy=0;
+
+#define SUSTAIN_BIT 0x04
+enum PrivateNoteStatus {
+ KEY_OFF = 0x00,
+ KEY_PLAYING = 0x01,
+ KEY_RELEASED_AND_SUSTAINED = 0x02,
+ KEY_RELEASED = 0x03
+};
+
+
+class KitTest
+{
+ private:
+ Alloc alloc;
+ FFTwrapper fft;
+ Microtonal microtonal;
+ Part *part;
+ AbsTime *time;
+ float *outL, *outR;
+ public:
+ KitTest()
+ :fft(512), microtonal(dummy)
+ {}
+ void setUp() {
+ synth = new SYNTH_T;
+ time = new AbsTime(*synth);
+ outL = new float[synth->buffersize];
+ outR = new float[synth->buffersize];
+ memset(outL, 0, synth->bufferbytes);
+ memset(outR, 0, synth->bufferbytes);
+
+
+ part = new Part(alloc, *synth, *time, dummy, dummy, µtonal, &fft);
+ }
+
+ //Standard poly mode with sustain
+ void testSustainCase1() {
+ //enable sustain
+ part->ctl.setsustain(127);
+
+ part->NoteOn(64, 127, 0);
+ part->NoteOn(64, 127, 0);
+ part->NoteOff(64);
+
+ //first note has moved to release state
+ //second note has moved to sustain state
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[0],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=64,
+ .sendto=0,
+ .size=1,
+ .status=KEY_RELEASED|SUSTAIN_BIT,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[1],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=64,
+ .sendto=0,
+ .size=1,
+ .status=KEY_RELEASED_AND_SUSTAINED,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[2],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=0,
+ .sendto=0,
+ .size=0,
+ .status=0,
+ .legatoMirror=false}));
+ }
+
+ void testSustainCase2() {
+ //enable sustain
+ part->ctl.setsustain(127);
+
+ part->NoteOn(64, 127, 0);
+ part->NoteOff(64);
+ part->NoteOn(64, 127, 0);
+
+ //first note has moved to release state
+ //second note has stayed in playing state
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[0],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=64,
+ .sendto=0,
+ .size=1,
+ .status=KEY_RELEASED|SUSTAIN_BIT,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[1],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=64,
+ .sendto=0,
+ .size=1,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[2],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=0,
+ .sendto=0,
+ .size=0,
+ .status=0,
+ .legatoMirror=false}));
+ }
+
+ void testMonoSustain() {
+ //enable sustain
+ part->ctl.setsustain(127);
+ part->Ppolymode = false;
+
+ part->NoteOn(64, 127, 0);
+ part->NoteOff(64);
+ part->NoteOn(65, 127, 0);
+
+ part->notePool.dump();
+
+ //first note has moved to release state
+ //second note has stayed in playing state
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[0],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=64,
+ .sendto=0,
+ .size=1,
+ .status=KEY_RELEASED,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[1],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=65,
+ .sendto=0,
+ .size=1,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[2],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=0,
+ .sendto=0,
+ .size=0,
+ .status=0,
+ .legatoMirror=false}));
+ }
+
+ //Enumerate cases of:
+ //Legato = {disabled,enabled}
+ //Mono = {disabled, enabled}
+ //Kit = {off, normal, single}
+ //ignore legato=enabled, mono=enabled
+
+ //No Kit
+ void testNoKitNoLegatoNoMono() {
+ part->NoteOn(64, 127, 0);
+ part->NoteOn(65, 127, 0);
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[0],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=64,
+ .sendto=0,
+ .size=1,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[1],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=65,
+ .sendto=0,
+ .size=1,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[2],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=0,
+ .sendto=0,
+ .size=0,
+ .status=0,
+ .legatoMirror=false}));
+ }
+
+ void testNoKitYesLegatoNoMono() {
+ part->Ppolymode = false;
+ part->Plegatomode = true;
+ part->NoteOn(64, 127, 0);
+ part->NoteOn(65, 127, 0);
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[0],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=65,
+ .sendto=0,
+ .size=1,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[1],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=65,
+ .sendto=0,
+ .size=1,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[2],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=0,
+ .sendto=0,
+ .size=0,
+ .status=0,
+ .legatoMirror=false}));
+
+ TS_NON_NULL(part->notePool.sdesc[0].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].kit, 0);
+
+ TS_NON_NULL(part->notePool.sdesc[1].note);
+ if(part->notePool.sdesc[1].note)
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].note->legato.silent, true);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].kit, 0);
+ }
+
+ void testNoKitNoLegatoYesMono() {
+ part->Ppolymode = false;
+ part->Plegatomode = false;
+ part->NoteOn(64, 127, 0);
+ part->NoteOn(65, 127, 0);
+
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[0],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=64,
+ .sendto=0,
+ .size=1,
+ .status=KEY_RELEASED,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[1],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=65,
+ .sendto=0,
+ .size=1,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[2],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=0,
+ .sendto=0,
+ .size=0,
+ .status=0,
+ .legatoMirror=false}));
+
+ TS_NON_NULL(part->notePool.sdesc[0].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].kit, 0);
+
+ TS_NON_NULL(part->notePool.sdesc[1].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].kit, 0);
+ }
+
+ //Normal Kit
+ //Three patches that overlap give an overlapping response
+ void testYesKitNoLegatoNoMono() {
+ part->setkititemstatus(1, true);
+ part->setkititemstatus(2, true);
+ part->kit[1].Padenabled = true;
+ part->kit[2].Padenabled = true;
+ part->kit[2].Pmaxkey = 32;
+ part->Pkitmode = 1;
+ part->NoteOn(64, 127, 0);
+ part->NoteOn(65, 127, 0);
+
+ part->notePool.dump();
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[0],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=64,
+ .sendto=0,
+ .size=2,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[1],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=65,
+ .sendto=0,
+ .size=2,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[2],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=0,
+ .sendto=0,
+ .size=0,
+ .status=0,
+ .legatoMirror=false}));
+
+ TS_NON_NULL(part->notePool.sdesc[0].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].kit, 0);
+
+ TS_NON_NULL(part->notePool.sdesc[1].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].kit, 1);
+
+ TS_NON_NULL(part->notePool.sdesc[2].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[2].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[2].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[2].kit, 0);
+
+ TS_NON_NULL(part->notePool.sdesc[3].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[3].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[3].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[3].kit, 1);
+
+ assert_ptr_eq(part->notePool.sdesc[4].note,
+ nullptr,
+ "note free", __LINE__);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[4].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[4].kit, 0);
+ }
+
+ void testYesKitYesLegatoNoMono() {
+ part->setkititemstatus(1, true);
+ part->setkititemstatus(2, true);
+ part->kit[1].Padenabled = true;
+ part->kit[2].Padenabled = true;
+ part->kit[2].Pmaxkey = 32;
+ part->Pkitmode = 1;
+ part->Ppolymode = false;
+ part->Plegatomode = true;
+ part->NoteOn(64, 127, 0);
+ part->NoteOn(65, 127, 0);
+
+ part->notePool.dump();
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[0],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=65,
+ .sendto=0,
+ .size=2,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[1],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=65,
+ .sendto=0,
+ .size=2,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[2],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=0,
+ .sendto=0,
+ .size=0,
+ .status=0,
+ .legatoMirror=false}));
+
+ TS_NON_NULL(part->notePool.sdesc[0].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].kit, 0);
+
+ TS_NON_NULL(part->notePool.sdesc[1].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].kit, 1);
+
+ TS_NON_NULL(part->notePool.sdesc[2].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[2].note->legato.silent, true);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[2].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[2].kit, 0);
+
+ TS_NON_NULL(part->notePool.sdesc[3].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[3].note->legato.silent, true);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[3].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[3].kit, 1);
+
+ assert_ptr_eq(part->notePool.sdesc[4].note,
+ nullptr,
+ "note free", __LINE__);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[4].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[4].kit, 0);
+ }
+
+ void testYesKitNoLegatoYesMono() {
+ part->setkititemstatus(1, true);
+ part->setkititemstatus(2, true);
+ part->kit[1].Padenabled = true;
+ part->kit[2].Padenabled = true;
+ part->kit[2].Pmaxkey = 32;
+ part->Pkitmode = 1;
+ part->Ppolymode = false;
+ part->Plegatomode = false;
+ part->NoteOn(64, 127, 0);
+ part->NoteOn(65, 127, 0);
+
+ part->notePool.dump();
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[0],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=64,
+ .sendto=0,
+ .size=2,
+ .status=KEY_RELEASED,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[1],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=65,
+ .sendto=0,
+ .size=2,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[2],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=0,
+ .sendto=0,
+ .size=0,
+ .status=0,
+ .legatoMirror=false}));
+
+ TS_NON_NULL(part->notePool.sdesc[0].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].kit, 0);
+
+ TS_NON_NULL(part->notePool.sdesc[1].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].kit, 1);
+
+ TS_NON_NULL(part->notePool.sdesc[2].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[2].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[2].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[2].kit, 0);
+
+ TS_NON_NULL(part->notePool.sdesc[3].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[3].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[3].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[3].kit, 1);
+
+ assert_ptr_eq(part->notePool.sdesc[4].note,
+ nullptr,
+ "note free", __LINE__);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[4].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[4].kit, 0);
+ }
+
+ //Single Kit
+ void testSingleKitNoLegatoNoMono() {
+ part->setkititemstatus(1, true);
+ part->setkititemstatus(2, true);
+ part->kit[1].Padenabled = true;
+ part->kit[2].Padenabled = true;
+ part->kit[2].Pmaxkey = 32;
+ part->Pkitmode = 2;
+ part->NoteOn(64, 127, 0);
+ part->NoteOn(65, 127, 0);
+
+ part->notePool.dump();
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[0],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=64,
+ .sendto=0,
+ .size=1,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[1],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=65,
+ .sendto=0,
+ .size=1,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[2],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=0,
+ .sendto=0,
+ .size=0,
+ .status=0,
+ .legatoMirror=false}));
+
+ TS_NON_NULL(part->notePool.sdesc[0].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].kit, 0);
+
+ TS_NON_NULL(part->notePool.sdesc[1].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].kit, 0);
+
+ assert_ptr_eq(part->notePool.sdesc[2].note,
+ nullptr,
+ "note free", __LINE__);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[2].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[2].kit, 0);
+ }
+
+ void testSingleKitYesLegatoNoMono() {
+ part->setkititemstatus(1, true);
+ part->setkititemstatus(2, true);
+ part->kit[1].Padenabled = true;
+ part->kit[2].Padenabled = true;
+ part->kit[2].Pmaxkey = 32;
+ part->Pkitmode = 2;
+ part->Ppolymode = false;
+ part->Plegatomode = true;
+ part->NoteOn(64, 127, 0);
+ part->NoteOn(65, 127, 0);
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[0],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=65,
+ .sendto=0,
+ .size=1,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[1],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=65,
+ .sendto=0,
+ .size=1,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[2],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=0,
+ .sendto=0,
+ .size=0,
+ .status=0,
+ .legatoMirror=false}));
+
+ TS_NON_NULL(part->notePool.sdesc[0].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].kit, 0);
+
+ TS_NON_NULL(part->notePool.sdesc[1].note);
+ if(part->notePool.sdesc[1].note)
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].note->legato.silent, true);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].kit, 0);
+ }
+
+ void testSingleKitNoLegatoYesMono() {
+ part->setkititemstatus(1, true);
+ part->setkititemstatus(2, true);
+ part->kit[1].Padenabled = true;
+ part->kit[2].Padenabled = true;
+ part->kit[2].Pmaxkey = 32;
+ part->Pkitmode = 2;
+ part->Ppolymode = false;
+ part->Plegatomode = false;
+ part->NoteOn(64, 127, 0);
+ part->NoteOn(65, 127, 0);
+
+
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[0],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=64,
+ .sendto=0,
+ .size=1,
+ .status=KEY_RELEASED,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[1],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=65,
+ .sendto=0,
+ .size=1,
+ .status=KEY_PLAYING,
+ .legatoMirror=false}));
+
+ TS_ASSERT_EQUAL_CPP(part->notePool.ndesc[2],
+ (NotePool::NoteDescriptor{
+ .age=0,
+ .note=0,
+ .sendto=0,
+ .size=0,
+ .status=0,
+ .legatoMirror=false}));
+
+ TS_NON_NULL(part->notePool.sdesc[0].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[0].kit, 0);
+
+ TS_NON_NULL(part->notePool.sdesc[1].note);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].note->legato.silent, false);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].type, 0);
+ TS_ASSERT_EQUAL_INT(part->notePool.sdesc[1].kit, 0);
+ }
+
+ void testKeyLimit(void)
+ {
+ auto &pool = part->notePool;
+ //Verify that without a key limit, several notes can be run
+ part->NoteOn(64, 127, 0);
+ part->NoteOn(65, 127, 0);
+ part->NoteOn(66, 127, 0);
+ part->NoteOn(67, 127, 0);
+ part->NoteOn(68, 127, 0);
+
+ //Verify that notes are spawned as expected
+ TS_ASSERT_EQUAL_INT(pool.usedNoteDesc(), 5);
+ TS_ASSERT_EQUAL_INT(pool.usedSynthDesc(), 5);
+
+ //Reset the part
+ part->monomemClear();
+ pool.killAllNotes();
+
+ //Verify that notes are despawned
+ TS_ASSERT_EQUAL_INT(pool.usedNoteDesc(), 0);
+ TS_ASSERT_EQUAL_INT(pool.usedSynthDesc(), 0);
+
+ //Enable keylimit
+ part->setkeylimit(3);
+
+ //Replay notes
+ part->NoteOn(64, 127, 0);
+ part->NoteOn(65, 127, 0);
+ part->NoteOn(66, 127, 0);
+ part->NoteOn(67, 127, 0);
+ part->NoteOn(68, 127, 0);
+
+ //Verify that notes are spawned as expected with limit
+ TS_ASSERT_EQUAL_INT(pool.getRunningNotes(), 3);//2 entombed
+ TS_ASSERT_EQUAL_INT(pool.usedNoteDesc(), 5);
+ TS_ASSERT_EQUAL_INT(pool.usedSynthDesc(), 5);
+
+ //Reset the part
+ part->monomemClear();
+ pool.killAllNotes();
+
+ //Verify that notes are despawned
+ TS_ASSERT_EQUAL_INT(pool.usedNoteDesc(), 0);
+ TS_ASSERT_EQUAL_INT(pool.usedSynthDesc(), 0);
+
+ //Now to test note stealing
+
+ //Replay notes
+ part->NoteOn(64, 127, 0);
+ part->NoteOn(65, 127, 0);
+ part->NoteOn(66, 127, 0);
+
+ //Verify that note pool is full
+ TS_ASSERT_EQUAL_INT(pool.usedNoteDesc(), 3);
+ TS_ASSERT_EQUAL_INT(pool.usedSynthDesc(), 3);
+
+ //Age the notes
+ pool.ndesc[1].age = 50;
+ pool.ndesc[2].age = 500;
+
+ printf("-------------------------------------\n");
+
+ //Inject two more notes which should steal the note
+ //descriptors for #66 and #65
+ part->NoteOn(67, 127, 0);
+ pool.cleanup();
+ TS_ASSERT_EQUAL_INT(pool.ndesc[0].note, 64);
+ TS_ASSERT_EQUAL_INT(pool.ndesc[1].note, 65);
+ TS_ASSERT_EQUAL_INT(pool.ndesc[2].note, 66);
+ TS_ASSERT_EQUAL_INT(pool.ndesc[2].status, KEY_RELEASED);
+ TS_ASSERT_EQUAL_INT(pool.ndesc[3].note, 67);
+
+ part->NoteOn(68, 127, 0);
+
+ //Verify that note pool is still full and entombed
+ TS_ASSERT_EQUAL_INT(pool.usedNoteDesc(), 5);
+ TS_ASSERT_EQUAL_INT(pool.usedSynthDesc(), 5);
+
+ //Check that the result is {64, 68, 67}
+ TS_ASSERT_EQUAL_INT(pool.ndesc[0].note, 64);
+ TS_ASSERT_EQUAL_INT(pool.ndesc[1].note, 65);
+ TS_ASSERT_EQUAL_INT(pool.ndesc[1].status, KEY_RELEASED);
+ TS_ASSERT_EQUAL_INT(pool.ndesc[2].note, 66);
+ TS_ASSERT_EQUAL_INT(pool.ndesc[2].status, KEY_RELEASED);
+ TS_ASSERT_EQUAL_INT(pool.ndesc[3].note, 67);
+ TS_ASSERT_EQUAL_INT(pool.ndesc[4].note, 68);
+ }
+
+ void tearDown() {
+ delete part;
+ delete[] outL;
+ delete[] outR;
+ delete time;
+ delete synth;
+ }
+};
+
+int main()
+{
+ KitTest test;
+ RUN_TEST(testSustainCase1);
+ RUN_TEST(testSustainCase2);
+ RUN_TEST(testMonoSustain);
+ RUN_TEST(testNoKitNoLegatoNoMono);
+ RUN_TEST(testNoKitYesLegatoNoMono);
+ RUN_TEST(testNoKitNoLegatoYesMono);
+ RUN_TEST(testYesKitNoLegatoNoMono);
+ RUN_TEST(testYesKitYesLegatoNoMono);
+ RUN_TEST(testYesKitNoLegatoYesMono);
+ RUN_TEST(testSingleKitNoLegatoNoMono);
+ RUN_TEST(testSingleKitYesLegatoNoMono);
+ RUN_TEST(testSingleKitNoLegatoYesMono);
+ RUN_TEST(testKeyLimit);
+ return test_summary();
+}
diff --git a/src/Tests/KitTest.h b/src/Tests/KitTest.h
@@ -1,768 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- KitTest.h - Test For Note Allocation Under Kits
- Copyright (C) 2016 Mark McCurry
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-#include <cxxtest/TestSuite.h>
-#include <cmath>
-#include <cstring>
-#include <cstdlib>
-#include <iostream>
-#include "../Misc/Time.h"
-#include "../Misc/Allocator.h"
-#include "../DSP/FFTwrapper.h"
-#include "../Misc/Microtonal.h"
-#define private public
-#define protected public
-#include "../Synth/SynthNote.h"
-#include "../Misc/Part.h"
-#include "../globals.h"
-
-using namespace std;
-using namespace zyn;
-
-SYNTH_T *synth;
-int dummy=0;
-
-#define SUSTAIN_BIT 0x04
-enum PrivateNoteStatus {
- KEY_OFF = 0x00,
- KEY_PLAYING = 0x01,
- KEY_RELEASED_AND_SUSTAINED = 0x02,
- KEY_RELEASED = 0x03
-};
-
-
-class KitTest:public CxxTest::TestSuite
-{
- private:
- Alloc alloc;
- FFTwrapper fft;
- Microtonal microtonal;
- Part *part;
- AbsTime *time;
- float *outL, *outR;
- public:
- KitTest()
- :fft(512), microtonal(dummy)
- {}
- void setUp() {
- synth = new SYNTH_T;
- time = new AbsTime(*synth);
- outL = new float[synth->buffersize];
- outR = new float[synth->buffersize];
- memset(outL, 0, synth->bufferbytes);
- memset(outR, 0, synth->bufferbytes);
-
-
- part = new Part(alloc, *synth, *time, dummy, dummy, µtonal, &fft);
- }
-
- //Standard poly mode with sustain
- void testSustainCase1() {
- //enable sustain
- part->ctl.setsustain(127);
-
- part->NoteOn(64, 127, 0);
- part->NoteOn(64, 127, 0);
- part->NoteOff(64);
-
- //first note has moved to release state
- //second note has moved to sustain state
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[0],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=64,
- .sendto=0,
- .size=1,
- .status=KEY_RELEASED|SUSTAIN_BIT,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[1],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=64,
- .sendto=0,
- .size=1,
- .status=KEY_RELEASED_AND_SUSTAINED,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[2],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=0,
- .sendto=0,
- .size=0,
- .status=0,
- .legatoMirror=false}));
- }
-
- void testSustainCase2() {
- //enable sustain
- part->ctl.setsustain(127);
-
- part->NoteOn(64, 127, 0);
- part->NoteOff(64);
- part->NoteOn(64, 127, 0);
-
- //first note has moved to release state
- //second note has stayed in playing state
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[0],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=64,
- .sendto=0,
- .size=1,
- .status=KEY_RELEASED|SUSTAIN_BIT,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[1],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=64,
- .sendto=0,
- .size=1,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[2],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=0,
- .sendto=0,
- .size=0,
- .status=0,
- .legatoMirror=false}));
- }
-
- void testMonoSustain() {
- //enable sustain
- part->ctl.setsustain(127);
- part->Ppolymode = false;
-
- part->NoteOn(64, 127, 0);
- part->NoteOff(64);
- part->NoteOn(65, 127, 0);
-
- part->notePool.dump();
-
- //first note has moved to release state
- //second note has stayed in playing state
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[0],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=64,
- .sendto=0,
- .size=1,
- .status=KEY_RELEASED,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[1],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=65,
- .sendto=0,
- .size=1,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[2],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=0,
- .sendto=0,
- .size=0,
- .status=0,
- .legatoMirror=false}));
- }
-
- //Enumerate cases of:
- //Legato = {disabled,enabled}
- //Mono = {disabled, enabled}
- //Kit = {off, normal, single}
- //ignore legato=enabled, mono=enabled
-
- //No Kit
- void testNoKitNoLegatoNoMono() {
- part->NoteOn(64, 127, 0);
- part->NoteOn(65, 127, 0);
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[0],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=64,
- .sendto=0,
- .size=1,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[1],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=65,
- .sendto=0,
- .size=1,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[2],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=0,
- .sendto=0,
- .size=0,
- .status=0,
- .legatoMirror=false}));
- }
-
- void testNoKitYesLegatoNoMono() {
- part->Ppolymode = false;
- part->Plegatomode = true;
- part->NoteOn(64, 127, 0);
- part->NoteOn(65, 127, 0);
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[0],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=65,
- .sendto=0,
- .size=1,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[1],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=65,
- .sendto=0,
- .size=1,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[2],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=0,
- .sendto=0,
- .size=0,
- .status=0,
- .legatoMirror=false}));
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[0].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].kit, 0)
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[1].note, nullptr);
- if(part->notePool.sdesc[1].note)
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].note->legato.silent, true);
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].kit, 0)
- }
-
- void testNoKitNoLegatoYesMono() {
- part->Ppolymode = false;
- part->Plegatomode = false;
- part->NoteOn(64, 127, 0);
- part->NoteOn(65, 127, 0);
-
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[0],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=64,
- .sendto=0,
- .size=1,
- .status=KEY_RELEASED,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[1],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=65,
- .sendto=0,
- .size=1,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[2],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=0,
- .sendto=0,
- .size=0,
- .status=0,
- .legatoMirror=false}));
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[0].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].kit, 0)
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[1].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].kit, 0)
- }
-
- //Normal Kit
- //Three patches that overlap give an overlapping response
- void testYesKitNoLegatoNoMono() {
- part->setkititemstatus(1, true);
- part->setkititemstatus(2, true);
- part->kit[1].Padenabled = true;
- part->kit[2].Padenabled = true;
- part->kit[2].Pmaxkey = 32;
- part->Pkitmode = 1;
- part->NoteOn(64, 127, 0);
- part->NoteOn(65, 127, 0);
-
- part->notePool.dump();
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[0],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=64,
- .sendto=0,
- .size=2,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[1],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=65,
- .sendto=0,
- .size=2,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[2],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=0,
- .sendto=0,
- .size=0,
- .status=0,
- .legatoMirror=false}));
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[0].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].kit, 0)
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[1].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].kit, 1)
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[2].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[2].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[2].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[2].kit, 0)
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[3].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[3].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[3].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[3].kit, 1)
-
- TS_ASSERT_EQUALS(part->notePool.sdesc[4].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[4].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[4].kit, 0)
- }
-
- void testYesKitYesLegatoNoMono() {
- part->setkititemstatus(1, true);
- part->setkititemstatus(2, true);
- part->kit[1].Padenabled = true;
- part->kit[2].Padenabled = true;
- part->kit[2].Pmaxkey = 32;
- part->Pkitmode = 1;
- part->Ppolymode = false;
- part->Plegatomode = true;
- part->NoteOn(64, 127, 0);
- part->NoteOn(65, 127, 0);
-
- part->notePool.dump();
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[0],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=65,
- .sendto=0,
- .size=2,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[1],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=65,
- .sendto=0,
- .size=2,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[2],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=0,
- .sendto=0,
- .size=0,
- .status=0,
- .legatoMirror=false}));
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[0].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].kit, 0)
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[1].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].kit, 1)
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[2].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[2].note->legato.silent, true);
- TS_ASSERT_EQUALS(part->notePool.sdesc[2].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[2].kit, 0)
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[3].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[3].note->legato.silent, true);
- TS_ASSERT_EQUALS(part->notePool.sdesc[3].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[3].kit, 1)
-
- TS_ASSERT_EQUALS(part->notePool.sdesc[4].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[4].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[4].kit, 0)
- }
-
- void testYesKitNoLegatoYesMono() {
- part->setkititemstatus(1, true);
- part->setkititemstatus(2, true);
- part->kit[1].Padenabled = true;
- part->kit[2].Padenabled = true;
- part->kit[2].Pmaxkey = 32;
- part->Pkitmode = 1;
- part->Ppolymode = false;
- part->Plegatomode = false;
- part->NoteOn(64, 127, 0);
- part->NoteOn(65, 127, 0);
-
- part->notePool.dump();
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[0],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=64,
- .sendto=0,
- .size=2,
- .status=KEY_RELEASED,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[1],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=65,
- .sendto=0,
- .size=2,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[2],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=0,
- .sendto=0,
- .size=0,
- .status=0,
- .legatoMirror=false}));
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[0].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].kit, 0)
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[1].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].kit, 1)
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[2].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[2].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[2].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[2].kit, 0)
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[3].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[3].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[3].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[3].kit, 1)
-
- TS_ASSERT_EQUALS(part->notePool.sdesc[4].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[4].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[4].kit, 0)
- }
-
- //Single Kit
- void testSingleKitNoLegatoNoMono() {
- part->setkititemstatus(1, true);
- part->setkititemstatus(2, true);
- part->kit[1].Padenabled = true;
- part->kit[2].Padenabled = true;
- part->kit[2].Pmaxkey = 32;
- part->Pkitmode = 2;
- part->NoteOn(64, 127, 0);
- part->NoteOn(65, 127, 0);
-
- part->notePool.dump();
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[0],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=64,
- .sendto=0,
- .size=1,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[1],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=65,
- .sendto=0,
- .size=1,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[2],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=0,
- .sendto=0,
- .size=0,
- .status=0,
- .legatoMirror=false}));
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[0].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].kit, 0)
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[1].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].kit, 0)
-
- TS_ASSERT_EQUALS(part->notePool.sdesc[2].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[2].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[2].kit, 0)
- }
-
- void testSingleKitYesLegatoNoMono() {
- part->setkititemstatus(1, true);
- part->setkititemstatus(2, true);
- part->kit[1].Padenabled = true;
- part->kit[2].Padenabled = true;
- part->kit[2].Pmaxkey = 32;
- part->Pkitmode = 2;
- part->Ppolymode = false;
- part->Plegatomode = true;
- part->NoteOn(64, 127, 0);
- part->NoteOn(65, 127, 0);
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[0],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=65,
- .sendto=0,
- .size=1,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[1],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=65,
- .sendto=0,
- .size=1,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[2],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=0,
- .sendto=0,
- .size=0,
- .status=0,
- .legatoMirror=false}));
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[0].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].kit, 0)
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[1].note, nullptr);
- if(part->notePool.sdesc[1].note)
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].note->legato.silent, true);
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].kit, 0)
- }
-
- void testSingleKitNoLegatoYesMono() {
- part->setkititemstatus(1, true);
- part->setkititemstatus(2, true);
- part->kit[1].Padenabled = true;
- part->kit[2].Padenabled = true;
- part->kit[2].Pmaxkey = 32;
- part->Pkitmode = 2;
- part->Ppolymode = false;
- part->Plegatomode = false;
- part->NoteOn(64, 127, 0);
- part->NoteOn(65, 127, 0);
-
-
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[0],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=64,
- .sendto=0,
- .size=1,
- .status=KEY_RELEASED,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[1],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=65,
- .sendto=0,
- .size=1,
- .status=KEY_PLAYING,
- .legatoMirror=false}));
-
- TS_ASSERT_EQUALS(part->notePool.ndesc[2],
- (NotePool::NoteDescriptor{
- .age=0,
- .note=0,
- .sendto=0,
- .size=0,
- .status=0,
- .legatoMirror=false}));
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[0].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[0].kit, 0)
-
- TS_ASSERT_DIFFERS(part->notePool.sdesc[1].note, nullptr);
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].note->legato.silent, false);
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].type, 0)
- TS_ASSERT_EQUALS(part->notePool.sdesc[1].kit, 0)
- }
-
- void testKeyLimit(void)
- {
- auto &pool = part->notePool;
- //Verify that without a key limit, several notes can be run
- part->NoteOn(64, 127, 0);
- part->NoteOn(65, 127, 0);
- part->NoteOn(66, 127, 0);
- part->NoteOn(67, 127, 0);
- part->NoteOn(68, 127, 0);
-
- //Verify that notes are spawned as expected
- TS_ASSERT_EQUALS(pool.usedNoteDesc(), 5);
- TS_ASSERT_EQUALS(pool.usedSynthDesc(), 5);
-
- //Reset the part
- part->monomemClear();
- pool.killAllNotes();
-
- //Verify that notes are despawned
- TS_ASSERT_EQUALS(pool.usedNoteDesc(), 0);
- TS_ASSERT_EQUALS(pool.usedSynthDesc(), 0);
-
- //Enable keylimit
- part->setkeylimit(3);
-
- //Replay notes
- part->NoteOn(64, 127, 0);
- part->NoteOn(65, 127, 0);
- part->NoteOn(66, 127, 0);
- part->NoteOn(67, 127, 0);
- part->NoteOn(68, 127, 0);
-
- //Verify that notes are spawned as expected with limit
- TS_ASSERT_EQUALS(pool.getRunningNotes(), 3);//2 entombed
- TS_ASSERT_EQUALS(pool.usedNoteDesc(), 5);
- TS_ASSERT_EQUALS(pool.usedSynthDesc(), 5);
-
- //Reset the part
- part->monomemClear();
- pool.killAllNotes();
-
- //Verify that notes are despawned
- TS_ASSERT_EQUALS(pool.usedNoteDesc(), 0);
- TS_ASSERT_EQUALS(pool.usedSynthDesc(), 0);
-
- //Now to test note stealing
-
- //Replay notes
- part->NoteOn(64, 127, 0);
- part->NoteOn(65, 127, 0);
- part->NoteOn(66, 127, 0);
-
- //Verify that note pool is full
- TS_ASSERT_EQUALS(pool.usedNoteDesc(), 3);
- TS_ASSERT_EQUALS(pool.usedSynthDesc(), 3);
-
- //Age the notes
- pool.ndesc[1].age = 50;
- pool.ndesc[2].age = 500;
-
- printf("-------------------------------------\n");
-
- //Inject two more notes which should steal the note
- //descriptors for #66 and #65
- part->NoteOn(67, 127, 0);
- pool.cleanup();
- TS_ASSERT_EQUALS(pool.ndesc[0].note, 64);
- TS_ASSERT_EQUALS(pool.ndesc[1].note, 65);
- TS_ASSERT_EQUALS(pool.ndesc[2].note, 66);
- TS_ASSERT_EQUALS(pool.ndesc[2].status, KEY_RELEASED);
- TS_ASSERT_EQUALS(pool.ndesc[3].note, 67);
-
- part->NoteOn(68, 127, 0);
-
- //Verify that note pool is still full and entombed
- TS_ASSERT_EQUALS(pool.usedNoteDesc(), 5);
- TS_ASSERT_EQUALS(pool.usedSynthDesc(), 5);
-
- //Check that the result is {64, 68, 67}
- TS_ASSERT_EQUALS(pool.ndesc[0].note, 64);
- TS_ASSERT_EQUALS(pool.ndesc[1].note, 65);
- TS_ASSERT_EQUALS(pool.ndesc[1].status, KEY_RELEASED);
- TS_ASSERT_EQUALS(pool.ndesc[2].note, 66);
- TS_ASSERT_EQUALS(pool.ndesc[2].status, KEY_RELEASED);
- TS_ASSERT_EQUALS(pool.ndesc[3].note, 67);
- TS_ASSERT_EQUALS(pool.ndesc[4].note, 68);
- }
-
- void tearDown() {
- delete part;
- delete[] outL;
- delete[] outR;
- delete time;
- delete synth;
- }
-};
diff --git a/src/Tests/MemoryStressTest.cpp b/src/Tests/MemoryStressTest.cpp
@@ -0,0 +1,116 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ AdNoteTest.h - CxxTest for Synth/ADnote
+ Copyright (C) 2009-2011 Mark McCurry
+ Copyright (C) 2009 Harald Hvaal
+ Authors: Mark McCurry, Harald Hvaal
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+
+
+#include "test-suite.h"
+#include <iostream>
+#include <fstream>
+#include <ctime>
+#include <string>
+#include "../Misc/Master.h"
+#include "../Misc/Util.h"
+#include "../Misc/Allocator.h"
+#include "../Synth/ADnote.h"
+#include "../Params/Presets.h"
+#include "../DSP/FFTwrapper.h"
+#include "../globals.h"
+using namespace zyn;
+
+SYNTH_T *synth;
+
+class MemoryStressTest
+{
+ public:
+ AbsTime *time;
+ FFTwrapper *fft;
+ ADnoteParameters *defaultPreset;
+ Controller *controller;
+ Alloc memory;
+
+ void setUp() {
+ //First the sensible settings and variables that have to be set:
+ synth = new SYNTH_T;
+ synth->buffersize = 256;
+ //synth->alias();
+ time = new AbsTime(*synth);
+
+ fft = new FFTwrapper(synth->oscilsize);
+ //prepare the default settings
+ defaultPreset = new ADnoteParameters(*synth, fft, time);
+
+ //Assert defaults
+ TS_ASSERT(!defaultPreset->VoicePar[1].Enabled);
+
+ std::string instrument_filename = std::string(SOURCE_DIR) + "/guitar-adnote.xmz";
+ std::cout << instrument_filename << std::endl;
+
+ XMLwrapper wrap;
+ wrap.loadXMLfile(instrument_filename);
+ TS_ASSERT(wrap.enterbranch("MASTER"));
+ TS_ASSERT(wrap.enterbranch("PART", 0));
+ TS_ASSERT(wrap.enterbranch("INSTRUMENT"));
+ TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT"));
+ TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT_ITEM", 0));
+ TS_ASSERT(wrap.enterbranch("ADD_SYNTH_PARAMETERS"));
+ defaultPreset->getfromXML(wrap);
+
+ //verify xml was loaded
+ TS_ASSERT(defaultPreset->VoicePar[1].Enabled);
+
+ controller = new Controller(*synth, time);
+
+ }
+
+ void tearDown() {
+ delete controller;
+ delete defaultPreset;
+ delete fft;
+ FFT_cleanup();
+ delete synth;
+ }
+
+ void testManySimultaneousNotes() {
+
+ unsigned char testnote = 42;
+ SynthParams pars{memory, *controller, *synth, *time, 120, 0, testnote / 12.0f, false, prng()};
+
+ std::vector<ADnote*> notes;
+
+ for ( size_t note_idx = 0; note_idx < 1000; ++ note_idx ) {
+ try {
+ notes.push_back(new ADnote(defaultPreset, pars));
+ } catch (std::exception & e) {
+#if defined(DEBUG)
+ std::cerr << "couldn't push note #" << note_idx << std::endl;
+#endif
+ }
+ }
+
+ // If we made it that far, we managed to create many ADnotewithout sigsev
+
+ for (auto note_ptr: notes) {
+ delete note_ptr;
+ }
+
+
+ }
+
+};
+
+int main()
+{
+ MemoryStressTest test;
+ RUN_TEST(testManySimultaneousNotes);
+ return test_summary();
+}
diff --git a/src/Tests/MemoryStressTest.h b/src/Tests/MemoryStressTest.h
@@ -1,111 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- AdNoteTest.h - CxxTest for Synth/ADnote
- Copyright (C) 2009-2011 Mark McCurry
- Copyright (C) 2009 Harald Hvaal
- Authors: Mark McCurry, Harald Hvaal
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-
-
-#include <cxxtest/TestSuite.h>
-#include <iostream>
-#include <fstream>
-#include <ctime>
-#include <string>
-#include "../Misc/Master.h"
-#include "../Misc/Util.h"
-#include "../Misc/Allocator.h"
-#include "../Synth/ADnote.h"
-#include "../Params/Presets.h"
-#include "../DSP/FFTwrapper.h"
-#include "../globals.h"
-using namespace zyn;
-
-SYNTH_T *synth;
-
-class AdNoteTest:public CxxTest::TestSuite
-{
- public:
- ADnote *note;
- AbsTime *time;
- FFTwrapper *fft;
- ADnoteParameters *defaultPreset;
- Controller *controller;
- Alloc memory;
-
- void setUp() {
- //First the sensible settings and variables that have to be set:
- synth = new SYNTH_T;
- synth->buffersize = 256;
- //synth->alias();
- time = new AbsTime(*synth);
-
- fft = new FFTwrapper(synth->oscilsize);
- //prepare the default settings
- defaultPreset = new ADnoteParameters(*synth, fft, time);
-
- //Assert defaults
- TS_ASSERT(!defaultPreset->VoicePar[1].Enabled);
-
- std::string instrument_filename = std::string(SOURCE_DIR) + "/guitar-adnote.xmz";
- std::cout << instrument_filename << std::endl;
-
- XMLwrapper wrap;
- wrap.loadXMLfile(instrument_filename);
- TS_ASSERT(wrap.enterbranch("MASTER"));
- TS_ASSERT(wrap.enterbranch("PART", 0));
- TS_ASSERT(wrap.enterbranch("INSTRUMENT"));
- TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT"));
- TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT_ITEM", 0));
- TS_ASSERT(wrap.enterbranch("ADD_SYNTH_PARAMETERS"));
- defaultPreset->getfromXML(wrap);
-
- //verify xml was loaded
- TS_ASSERT(defaultPreset->VoicePar[1].Enabled);
-
- controller = new Controller(*synth, time);
-
- }
-
- void tearDown() {
- delete note;
- delete controller;
- delete defaultPreset;
- delete fft;
- FFT_cleanup();
- delete synth;
- }
-
- void testManySimultaneousNotes() {
-
- unsigned char testnote = 42;
- SynthParams pars{memory, *controller, *synth, *time, 120, 0, testnote / 12.0f, false, prng()};
-
- std::vector<ADnote*> notes;
-
- for ( size_t note_idx = 0; note_idx < 1000; ++ note_idx ) {
- try {
- notes.push_back(new ADnote(defaultPreset, pars));
- } catch (std::exception & e) {
-#if defined(DEBUG)
- std::cerr << "couldn't push note #" << note_idx << std::endl;
-#endif
- }
- }
-
- // If we made it that far, we managed to create many ADnotewithout sigsev
-
- for (auto note_ptr: notes) {
- delete note_ptr;
- }
-
-
- }
-
-};
diff --git a/src/Tests/MessageTest.cpp b/src/Tests/MessageTest.cpp
@@ -0,0 +1,367 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ PluginTest.h - CxxTest for embedding zyn
+ Copyright (C) 2013-2013 Mark McCurry
+ Authors: Mark McCurry
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+#include "test-suite.h"
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <thread>
+#include <rtosc/thread-link.h>
+#include <unistd.h>
+#include "../Misc/MiddleWare.h"
+#include "../Misc/Master.h"
+#include "../Misc/Part.h"
+#include "../Misc/PresetExtractor.h"
+#include "../Misc/PresetExtractor.cpp"
+#include "../Misc/Util.h"
+#include "../globals.h"
+#include "../UI/NSM.H"
+using namespace std;
+using namespace zyn;
+
+class NSM_Client *nsm = 0;
+MiddleWare *middleware = 0;
+
+char *instance_name=(char*)"";
+
+#define NUM_MIDDLEWARE 3
+
+class MessageTest
+{
+ public:
+ Config config;
+ void setUp() {
+ synth = new SYNTH_T;
+ mw = new MiddleWare(std::move(*synth), &config);
+ ms = mw->spawnMaster();
+ realtime = NULL;
+ }
+
+ void tearDown() {
+ delete mw;
+ delete synth;
+ }
+
+ void testKitEnable(void)
+ {
+ const char *msg = NULL;
+ mw->transmitMsg("/part0/kit0/Psubenabled", "T");
+ TS_ASSERT(ms->uToB->hasNext());
+ msg = ms->uToB->read();
+ TS_ASSERT_EQUAL_STR("/part0/kit0/subpars-data", msg);
+ TS_ASSERT(ms->uToB->hasNext());
+ msg = ms->uToB->read();
+ TS_ASSERT_EQUAL_STR("/part0/kit0/Psubenabled", msg);
+ }
+
+ void testBankCapture(void)
+ {
+ mw->transmitMsg("/bank/slot23", "");
+ TS_ASSERT(!ms->uToB->hasNext());
+ mw->transmitMsg("/bank/fake", "");
+ TS_ASSERT(ms->uToB->hasNext());
+ const char *msg = ms->uToB->read();
+ TS_ASSERT_EQUAL_STR("/bank/fake", msg);
+ }
+
+ void testOscCopyPaste(void)
+ {
+ //Enable pad synth
+ mw->transmitMsg("/part0/kit0/Ppadenabled", "T");
+
+ TS_ASSERT(ms->uToB->hasNext());
+ ms->applyOscEvent(ms->uToB->read());
+ TS_ASSERT(ms->uToB->hasNext());
+ ms->applyOscEvent(ms->uToB->read());
+ TS_ASSERT(!ms->uToB->hasNext());
+
+ auto &osc_src = *ms->part[0]->kit[0].adpars->VoicePar[0].FmGn;
+ auto &osc_dst = *ms->part[0]->kit[0].padpars->oscilgen;
+ auto &osc_oth = *ms->part[0]->kit[0].adpars->VoicePar[1].OscilGn;
+
+ TS_ASSERT_EQUAL_INT(osc_src.Pbasefuncpar, 64);
+ osc_src.Pbasefuncpar = 32;
+ TS_ASSERT_EQUAL_INT(osc_src.Pbasefuncpar, 32);
+
+ //Copy From ADsynth modulator
+ printf("====Copy From ADsynth modulator\n");
+ start_realtime();
+ mw->transmitMsg("/presets/copy", "s", "/part0/kit0/adpars/VoicePar0/FMSmp/");
+
+ TS_ASSERT_EQUAL_STR("Poscilgen", mw->getPresetsStore().clipboard.type.c_str());
+ // a regex would be better here...
+ // hopefully, mxml will not change its whitespace behavior
+ assert_non_null(strstr(mw->getPresetsStore().clipboard.data.c_str(), "<par name=\"base_function_par\" value=\"32\" />"),
+ "base_function_par at right value", __LINE__);
+
+ /* // better test this without string comparison:
+ {
+ XMLwrapper xml;
+ bool couldPutXml = xml.putXMLdata(mw->getPresetsStore().clipboard.data.c_str());
+ TS_ASSERT(couldPutXml);
+ unsigned char copiedBasefuncPar = xml.getpar127("base_function_par", 0);
+ TS_ASSERT_EQUALS(copiedBasefuncPar, 32);
+ }*/
+
+ //printf("clipboard type: %s\n",mw->getPresetsStore().clipboard.type.c_str());
+ //printf("clipboard data:\n%s\n",mw->getPresetsStore().clipboard.data.c_str());
+
+ TS_ASSERT_EQUAL_INT(osc_dst.Pbasefuncpar, 64);
+ TS_ASSERT_EQUAL_INT(osc_oth.Pbasefuncpar, 64);
+
+ //Paste to PADsynth
+ printf("====Paste to PADsynth\n");
+ mw->transmitMsg("/presets/paste", "s", "/part0/kit0/padpars/oscilgen/");
+
+ printf("====Paste to ADsynth\n");
+ mw->transmitMsg("/presets/paste", "s", "/part0/kit0/adpars/VoicePar1/OscilSmp/");
+
+ stop_realtime();
+ TS_ASSERT_EQUAL_INT(osc_dst.Pbasefuncpar, 32);
+ TS_ASSERT_EQUAL_INT(osc_oth.Pbasefuncpar, 32);
+ }
+
+
+ void start_realtime(void)
+ {
+ do_exit = false;
+ realtime = new std::thread([this](){
+ int tries = 0;
+ while(tries < 10000) {
+ if(!ms->uToB->hasNext()) {
+ if(do_exit)
+ break;
+
+ usleep(500);
+ continue;
+ }
+ const char *msg = ms->uToB->read();
+ printf("RT: handling <%s>\n", msg);
+ ms->applyOscEvent(msg);
+ }});
+ }
+
+ void stop_realtime(void)
+ {
+ do_exit = true;
+ realtime->join();
+ delete realtime;
+ realtime = NULL;
+ }
+
+ void run_realtime(void)
+ {
+ start_realtime();
+ stop_realtime();
+ }
+
+ void testMidiLearn(void)
+ {
+ mw->transmitMsg("/learn", "s", "/Pkeyshift");
+ mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 108);
+ TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 64);
+
+ //Perform a learning operation
+
+ run_realtime(); //1. runs learning and identifies a CC to bind
+ mw->tick(); //2. produces new binding table
+ run_realtime(); //3. applies new binding table
+
+
+ //Verify that the learning actually worked
+ mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 13);
+ run_realtime();
+ TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 13);
+
+ mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 2);
+ run_realtime();
+ TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 2);
+
+ mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 0);
+ run_realtime();
+ TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 0);
+
+ mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 127);
+ run_realtime();
+ TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 127);
+ }
+
+ void testMidiLearnSave(void)
+ {
+ mw->transmitMsg("/learn", "s", "/Pkeyshift");
+ mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 108);
+
+ //param is at default until rt-thread is run
+ TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 64);
+
+
+ //Perform a learning operation
+ run_realtime();
+
+ //Verify binding affects control
+ TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 108);
+
+
+ printf("# Trying to save automations\n");
+ start_realtime();
+ mw->transmitMsg("/save_xlz", "s", "test-midi-learn.xlz");
+ stop_realtime();
+
+ //Verify that some file exists
+ printf("# Verifying file exists\n");
+ FILE *f = fopen("test-midi-learn.xlz", "r");
+ assert_non_null(f, "test file exists", __LINE__);
+
+ if(f)
+ fclose(f);
+
+ printf("# Clearing automation\n");
+ //Clear out state
+ mw->transmitMsg("/clear_xlz", "");
+ //Send dummy message
+ mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 27);
+ run_realtime();
+
+ //Verify automation table is clear
+ TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 108);
+
+ printf("# Loading automation\n");
+ mw->transmitMsg("/load_xlz", "s", "test-midi-learn.xlz");
+ //Send message
+ mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 28);
+ run_realtime();
+
+ //Verify automation table is restored
+ TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 28);
+ }
+
+ void testLfoPaste(void)
+ {
+ start_realtime();
+ ms->part[0]->kit[0].adpars->GlobalPar.FreqLfo->Pfreqrand = 32;
+ TS_ASSERT_EQUAL_INT(ms->part[0]->kit[0].adpars->GlobalPar.FreqLfo->Pfreqrand, 32);
+
+ //Copy
+ mw->transmitMsg("/presets/copy", "s", "/part0/kit0/adpars/GlobalPar/FreqLfo/");
+
+ ms->part[0]->kit[0].adpars->GlobalPar.FreqLfo->Pfreqrand = 99;
+ TS_ASSERT_EQUAL_INT(ms->part[0]->kit[0].adpars->GlobalPar.FreqLfo->Pfreqrand, 99);
+
+ //Paste
+ mw->transmitMsg("/presets/paste", "s", "/part0/kit0/adpars/GlobalPar/FreqLfo/");
+ stop_realtime();
+
+ TS_ASSERT_EQUAL_INT(ms->part[0]->kit[0].adpars->GlobalPar.FreqLfo->Pfreqrand, 32);
+ }
+
+ void testPadPaste(void)
+ {
+ mw->transmitMsg("/part0/kit0/Ppadenabled", "T");
+ run_realtime();
+
+ start_realtime();
+
+ auto &field1 = ms->part[0]->kit[0].padpars->PVolume;
+ auto &field2 = ms->part[0]->kit[0].padpars->oscilgen->Pfilterpar1;
+ field1 = 32;
+ TS_ASSERT_EQUAL_INT(field1, 32);
+ field2 = 35;
+ TS_ASSERT_EQUAL_INT(field2, 35);
+
+ //Copy
+ mw->transmitMsg("/presets/copy", "s", "/part0/kit0/padpars/");
+
+ field1 = 99;
+ TS_ASSERT_EQUAL_INT(field1, 99);
+ field2 = 95;
+ TS_ASSERT_EQUAL_INT(field2, 95);
+
+ //Paste
+ mw->transmitMsg("/presets/paste", "s", "/part0/kit0/padpars/");
+ stop_realtime();
+
+ TS_ASSERT_EQUAL_INT(field1, 32);
+ TS_ASSERT_EQUAL_INT(field2, 35);
+ }
+
+ void testFilterDepricated(void)
+ {
+ vector<string> v = {"Pfreq", "Pfreqtrack", "Pgain", "Pq"};
+ for(size_t i=0; i<v.size(); ++i) {
+ string path = "/part0/kit0/adpars/GlobalPar/GlobalFilter/"+v[i];
+ for(int j=0; j<128; ++j) {
+ mw->transmitMsg(path.c_str(), "i", j); //Set
+ mw->transmitMsg(path.c_str(), ""); //Get
+ }
+
+ }
+ while(ms->uToB->hasNext()) {
+ const char *msg = ms->uToB->read();
+ //printf("RT: handling <%s>\n", msg);
+ ms->applyOscEvent(msg);
+ }
+
+ int id = 0;
+ int state = 0;
+ int value = 0;
+ // 0 - broadcast
+ // 1 - true value (set)
+ // 2 - expected value (get)
+ while(ms->bToU->hasNext()) {
+ const char *msg = ms->bToU->read();
+ if(state == 0) {
+ TS_ASSERT_EQUAL_INT(rtosc_narguments(msg), 0U);
+ state = 1;
+ } else if(state == 1) {
+ TS_ASSERT_EQUAL_INT(rtosc_narguments(msg), 1U);
+ value = rtosc_argument(msg, 0).i;
+ state = 2;
+ } else if(state == 2) {
+ int val = rtosc_argument(msg, 0).i;
+ if(value != val) {
+ printf("%s - %d should equal %d\n", msg, value, val);
+ TS_ASSERT(0);
+ }
+ state = 0;
+ }
+
+ (void) id;
+ //printf("Message #%d %s:%s\n", id++, msg, rtosc_argument_string(msg));
+ //if(rtosc_narguments(msg))
+ // printf(" %d\n", rtosc_argument(msg, 0).i);
+ }
+ }
+
+
+ private:
+ SYNTH_T *synth;
+ MiddleWare *mw;
+ Master *ms;
+ std::thread *realtime;
+ bool do_exit;
+};
+
+int main()
+{
+ MessageTest test;
+ RUN_TEST(testKitEnable);
+ RUN_TEST(testBankCapture);
+ RUN_TEST(testOscCopyPaste);
+ RUN_TEST(testMidiLearn);
+ RUN_TEST(testMidiLearnSave);
+ RUN_TEST(testLfoPaste);
+ RUN_TEST(testPadPaste);
+ RUN_TEST(testFilterDepricated);
+ return test_summary();
+}
diff --git a/src/Tests/MessageTest.h b/src/Tests/MessageTest.h
@@ -1,352 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- PluginTest.h - CxxTest for embedding zyn
- Copyright (C) 2013-2013 Mark McCurry
- Authors: Mark McCurry
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-#include <cxxtest/TestSuite.h>
-#include <cmath>
-#include <cstdlib>
-#include <iostream>
-#include <fstream>
-#include <string>
-#include <thread>
-#include <rtosc/thread-link.h>
-#include <unistd.h>
-#include "../Misc/MiddleWare.h"
-#include "../Misc/Master.h"
-#include "../Misc/Part.h"
-#include "../Misc/PresetExtractor.h"
-#include "../Misc/PresetExtractor.cpp"
-#include "../Misc/Util.h"
-#include "../globals.h"
-#include "../UI/NSM.H"
-using namespace std;
-using namespace zyn;
-
-class NSM_Client *nsm = 0;
-MiddleWare *middleware = 0;
-
-char *instance_name=(char*)"";
-
-#define NUM_MIDDLEWARE 3
-
-class MessageTest:public CxxTest::TestSuite
-{
- public:
- Config config;
- void setUp() {
- synth = new SYNTH_T;
- mw = new MiddleWare(std::move(*synth), &config);
- ms = mw->spawnMaster();
- realtime = NULL;
- }
-
- void tearDown() {
- delete mw;
- delete synth;
- }
-
- void testKitEnable(void)
- {
- const char *msg = NULL;
- mw->transmitMsg("/part0/kit0/Psubenabled", "T");
- TS_ASSERT(ms->uToB->hasNext());
- msg = ms->uToB->read();
- TS_ASSERT_EQUALS(string("/part0/kit0/subpars-data"), msg);
- TS_ASSERT(ms->uToB->hasNext());
- msg = ms->uToB->read();
- TS_ASSERT_EQUALS(string("/part0/kit0/Psubenabled"), msg);
- }
-
- void testBankCapture(void)
- {
- mw->transmitMsg("/bank/slot23", "");
- TS_ASSERT(!ms->uToB->hasNext());
- mw->transmitMsg("/bank/fake", "");
- TS_ASSERT(ms->uToB->hasNext());
- const char *msg = ms->uToB->read();
- TS_ASSERT_EQUALS(string("/bank/fake"), msg);
- }
-
- void testOscCopyPaste(void)
- {
- //Enable pad synth
- mw->transmitMsg("/part0/kit0/Ppadenabled", "T");
-
- TS_ASSERT(ms->uToB->hasNext());
- ms->applyOscEvent(ms->uToB->read());
- TS_ASSERT(ms->uToB->hasNext());
- ms->applyOscEvent(ms->uToB->read());
- TS_ASSERT(!ms->uToB->hasNext());
-
- auto &osc_src = *ms->part[0]->kit[0].adpars->VoicePar[0].FmGn;
- auto &osc_dst = *ms->part[0]->kit[0].padpars->oscilgen;
- auto &osc_oth = *ms->part[0]->kit[0].adpars->VoicePar[1].OscilGn;
-
- TS_ASSERT_EQUALS(osc_src.Pbasefuncpar, 64);
- osc_src.Pbasefuncpar = 32;
- TS_ASSERT_EQUALS(osc_src.Pbasefuncpar, 32);
-
- //Copy From ADsynth modulator
- printf("====Copy From ADsynth modulator\n");
- start_realtime();
- mw->transmitMsg("/presets/copy", "s", "/part0/kit0/adpars/VoicePar0/FMSmp/");
-
- TS_ASSERT_EQUALS(mw->getPresetsStore().clipboard.type.c_str(), string("Poscilgen"));
- // a regex would be better here...
- // hopefully, mxml will not change its whitespace behavior
- TS_ASSERT(strstr(mw->getPresetsStore().clipboard.data.c_str(), "<par name=\"base_function_par\" value=\"32\" />"));
-
- /* // better test this without string comparison:
- {
- XMLwrapper xml;
- bool couldPutXml = xml.putXMLdata(mw->getPresetsStore().clipboard.data.c_str());
- TS_ASSERT(couldPutXml);
- unsigned char copiedBasefuncPar = xml.getpar127("base_function_par", 0);
- TS_ASSERT_EQUALS(copiedBasefuncPar, 32);
- }*/
-
- //printf("clipboard type: %s\n",mw->getPresetsStore().clipboard.type.c_str());
- //printf("clipboard data:\n%s\n",mw->getPresetsStore().clipboard.data.c_str());
-
- TS_ASSERT_EQUALS(osc_dst.Pbasefuncpar, 64);
- TS_ASSERT_EQUALS(osc_oth.Pbasefuncpar, 64);
-
- //Paste to PADsynth
- printf("====Paste to PADsynth\n");
- mw->transmitMsg("/presets/paste", "s", "/part0/kit0/padpars/oscilgen/");
-
- printf("====Paste to ADsynth\n");
- mw->transmitMsg("/presets/paste", "s", "/part0/kit0/adpars/VoicePar1/OscilSmp/");
-
- stop_realtime();
- TS_ASSERT_EQUALS(osc_dst.Pbasefuncpar, 32);
- TS_ASSERT_EQUALS(osc_oth.Pbasefuncpar, 32);
- }
-
-
- void start_realtime(void)
- {
- do_exit = false;
- realtime = new std::thread([this](){
- int tries = 0;
- while(tries < 10000) {
- if(!ms->uToB->hasNext()) {
- if(do_exit)
- break;
-
- usleep(500);
- continue;
- }
- const char *msg = ms->uToB->read();
- printf("RT: handling <%s>\n", msg);
- ms->applyOscEvent(msg);
- }});
- }
-
- void stop_realtime(void)
- {
- do_exit = true;
- realtime->join();
- delete realtime;
- realtime = NULL;
- }
-
- void run_realtime(void)
- {
- start_realtime();
- stop_realtime();
- }
-
- void testMidiLearn(void)
- {
- mw->transmitMsg("/learn", "s", "/Pkeyshift");
- mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 108);
- TS_ASSERT_EQUALS(ms->Pkeyshift, 64);
-
- //Perform a learning operation
-
- run_realtime(); //1. runs learning and identifies a CC to bind
- mw->tick(); //2. produces new binding table
- run_realtime(); //3. applies new binding table
-
-
- //Verify that the learning actually worked
- mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 13);
- run_realtime();
- TS_ASSERT_EQUALS(ms->Pkeyshift, 13);
-
- mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 2);
- run_realtime();
- TS_ASSERT_EQUALS(ms->Pkeyshift, 2);
-
- mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 0);
- run_realtime();
- TS_ASSERT_EQUALS(ms->Pkeyshift, 0);
-
- mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 127);
- run_realtime();
- TS_ASSERT_EQUALS(ms->Pkeyshift, 127);
- }
-
- void testMidiLearnSave(void)
- {
- mw->transmitMsg("/learn", "s", "/Pkeyshift");
- mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 108);
-
- //param is at default until rt-thread is run
- TS_ASSERT_EQUALS(ms->Pkeyshift, 64);
-
-
- //Perform a learning operation
- run_realtime();
-
- //Verify binding affects control
- TS_ASSERT_EQUALS(ms->Pkeyshift, 108);
-
-
- printf("# Trying to save automations\n");
- start_realtime();
- mw->transmitMsg("/save_xlz", "s", "test-midi-learn.xlz");
- stop_realtime();
-
- //Verify that some file exists
- printf("# Verifying file exists\n");
- FILE *f = fopen("test-midi-learn.xlz", "r");
- TS_ASSERT(f);
-
- if(f)
- fclose(f);
-
- printf("# Clearing automation\n");
- //Clear out state
- mw->transmitMsg("/clear_xlz", "");
- //Send dummy message
- mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 27);
- run_realtime();
-
- //Verify automation table is clear
- TS_ASSERT_EQUALS(ms->Pkeyshift, 108);
-
- printf("# Loading automation\n");
- mw->transmitMsg("/load_xlz", "s", "test-midi-learn.xlz");
- //Send message
- mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 28);
- run_realtime();
-
- //Verify automation table is restored
- TS_ASSERT_EQUALS(ms->Pkeyshift, 28);
- }
-
- void testLfoPaste(void)
- {
- start_realtime();
- ms->part[0]->kit[0].adpars->GlobalPar.FreqLfo->Pfreqrand = 32;
- TS_ASSERT_EQUALS(ms->part[0]->kit[0].adpars->GlobalPar.FreqLfo->Pfreqrand, 32);
-
- //Copy
- mw->transmitMsg("/presets/copy", "s", "/part0/kit0/adpars/GlobalPar/FreqLfo/");
-
- ms->part[0]->kit[0].adpars->GlobalPar.FreqLfo->Pfreqrand = 99;
- TS_ASSERT_EQUALS(ms->part[0]->kit[0].adpars->GlobalPar.FreqLfo->Pfreqrand, 99);
-
- //Paste
- mw->transmitMsg("/presets/paste", "s", "/part0/kit0/adpars/GlobalPar/FreqLfo/");
- stop_realtime();
-
- TS_ASSERT_EQUALS(ms->part[0]->kit[0].adpars->GlobalPar.FreqLfo->Pfreqrand, 32);
- }
-
- void testPadPaste(void)
- {
- mw->transmitMsg("/part0/kit0/Ppadenabled", "T");
- run_realtime();
-
- start_realtime();
-
- auto &field1 = ms->part[0]->kit[0].padpars->PVolume;
- auto &field2 = ms->part[0]->kit[0].padpars->oscilgen->Pfilterpar1;
- field1 = 32;
- TS_ASSERT_EQUALS(field1, 32);
- field2 = 35;
- TS_ASSERT_EQUALS(field2, 35);
-
- //Copy
- mw->transmitMsg("/presets/copy", "s", "/part0/kit0/padpars/");
-
- field1 = 99;
- TS_ASSERT_EQUALS(field1, 99);
- field2 = 95;
- TS_ASSERT_EQUALS(field2, 95);
-
- //Paste
- mw->transmitMsg("/presets/paste", "s", "/part0/kit0/padpars/");
- stop_realtime();
-
- TS_ASSERT_EQUALS(field1, 32);
- TS_ASSERT_EQUALS(field2, 35);
- }
-
- void testFilterDepricated(void)
- {
- vector<string> v = {"Pfreq", "Pfreqtrack", "Pgain", "Pq"};
- for(size_t i=0; i<v.size(); ++i) {
- string path = "/part0/kit0/adpars/GlobalPar/GlobalFilter/"+v[i];
- for(int j=0; j<128; ++j) {
- mw->transmitMsg(path.c_str(), "i", j); //Set
- mw->transmitMsg(path.c_str(), ""); //Get
- }
-
- }
- while(ms->uToB->hasNext()) {
- const char *msg = ms->uToB->read();
- //printf("RT: handling <%s>\n", msg);
- ms->applyOscEvent(msg);
- }
-
- int id = 0;
- int state = 0;
- int value = 0;
- // 0 - broadcast
- // 1 - true value (set)
- // 2 - expected value (get)
- while(ms->bToU->hasNext()) {
- const char *msg = ms->bToU->read();
- if(state == 0) {
- TS_ASSERT_EQUALS(rtosc_narguments(msg), 0U);
- state = 1;
- } else if(state == 1) {
- TS_ASSERT_EQUALS(rtosc_narguments(msg), 1U);
- value = rtosc_argument(msg, 0).i;
- state = 2;
- } else if(state == 2) {
- int val = rtosc_argument(msg, 0).i;
- if(value != val) {
- printf("%s - %d should equal %d\n", msg, value, val);
- TS_ASSERT(0);
- }
- state = 0;
- }
-
- (void) id;
- //printf("Message #%d %s:%s\n", id++, msg, rtosc_argument_string(msg));
- //if(rtosc_narguments(msg))
- // printf(" %d\n", rtosc_argument(msg, 0).i);
- }
- }
-
-
- private:
- SYNTH_T *synth;
- MiddleWare *mw;
- Master *ms;
- std::thread *realtime;
- bool do_exit;
-};
diff --git a/src/Tests/MicrotonalTest.cpp b/src/Tests/MicrotonalTest.cpp
@@ -0,0 +1,138 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ MicrotonalTest.h - CxxTest for Misc/Microtonal
+ Copyright (C) 2009-2012 Mark McCurry
+ Author: Mark McCurry
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+#include "test-suite.h"
+#include <iostream>
+#include "../Misc/Microtonal.h"
+#include "../Misc/XMLwrapper.h"
+#include <cstring>
+#include <string>
+#include <cstdio>
+#include "../globals.h"
+using namespace std;
+using namespace zyn;
+
+SYNTH_T *synth;
+
+class MicrotonalTest
+{
+ public:
+ int compression;
+ void setUp() {
+ compression = 0;
+ synth = new SYNTH_T;
+ testMicro = new Microtonal(compression);
+ }
+
+ void tearDown() {
+ delete testMicro;
+ delete synth;
+ }
+
+ //Verifies that the object is initialized correctly
+ void testinit() {
+ TS_ASSERT_EQUAL_INT(testMicro->Pinvertupdown, 0);
+ TS_ASSERT_EQUAL_INT(testMicro->Pinvertupdowncenter, 60);
+ TS_ASSERT_EQUAL_INT(testMicro->getoctavesize(), 12);
+ TS_ASSERT_EQUAL_INT(testMicro->Penabled, 0);
+ TS_ASSERT_EQUAL_INT(testMicro->PAnote, 69);
+ TS_ASSERT_EQUAL_INT(testMicro->PAfreq, 440.0f);
+ TS_ASSERT_EQUAL_INT(testMicro->Pscaleshift, 64);
+ TS_ASSERT_EQUAL_INT(testMicro->Pfirstkey, 0);
+ TS_ASSERT_EQUAL_INT(testMicro->Plastkey, 127);
+ TS_ASSERT_EQUAL_INT(testMicro->Pmiddlenote, 60);
+ TS_ASSERT_EQUAL_INT(testMicro->Pmapsize, 12);
+ TS_ASSERT_EQUAL_INT(testMicro->Pmappingenabled, 0);
+ TS_ASSERT_EQUAL_INT(testMicro->Pglobalfinedetune, 64);
+
+ TS_ASSERT_EQUAL_STR("12tET", (const char *)testMicro->Pname);
+ TS_ASSERT_EQUAL_STR("Equal Temperament 12 notes per octave",
+ testMicro->Pcomment);
+
+ for(int i = 0; i < 128; ++i)
+ TS_ASSERT_EQUAL_INT(i, testMicro->Pmapping[i]);
+
+ TS_ASSERT_DELTA(testMicro->getnotefreq(19 / 12.0f, 0), 24.4997f, 0.0001f);
+ }
+
+ //Tests saving/loading to XML
+ void testXML() {
+ //Gah, the XMLwrapper is a twisted maze
+ testMicro->Penabled = 1;
+ XMLwrapper xml;
+ xml.beginbranch("Dummy"); //this should not be needed, but odd behavior
+ //seems to exist from MICROTONAL being on the
+ //top of the stack
+ xml.beginbranch("MICROTONAL");
+ testMicro->add2XML(xml);
+ xml.endbranch();
+ xml.endbranch();
+
+ char *tmp = xml.getXMLdata();
+ Microtonal other(compression);
+
+ other.Penabled = 1;
+ strcpy((char *)other.Pname, "Myname"); //will be nicer with strings
+
+ TS_ASSERT(*testMicro != other); //sanity check
+
+ TS_ASSERT(xml.enterbranch("Dummy"));
+ TS_ASSERT(xml.enterbranch("MICROTONAL"));
+
+ other.getfromXML(xml);
+ xml.exitbranch();
+ xml.exitbranch();
+ char *tmpo = xml.getXMLdata();
+
+ TS_ASSERT(!strcmp(tmp, tmpo));
+ free(tmp);
+ free(tmpo);
+ }
+
+#if 0
+ /**\todo Test Saving/loading from file*/
+
+ //Test texttomapping TODO finish
+ void _testTextToMapping() {
+ //the mapping is from old documentation for "Intense Diatonic" scale
+ const char *mapping[12] =
+ {"0", "x", "1", "x", "2", "3", "x", "4", "x", "5", "x", "6"};
+ //for(int i=0;i<20;++i)
+ // cout << i << ':' << testMicro->getnotefreq(i,0) << endl;
+ //
+ // octave size == 7
+ // find dead notes
+ }
+ //Test texttotunings TODO finish
+ void _testTextToTunings() {
+ //the tuning is from old documentation for "Intense Diatonic" scale
+ const char *tuning[7] =
+ {"9/8", "5/4", "4/3", "3/2", "5/3", "15/8", "2/1"};
+ const int numTunings = 7;
+ //for(int i=0;i<20;++i)
+ // cout << i << ':' << testMicro->getnotefreq(i,0) << endl;
+ // go to middle key and verify the proportions
+ }
+ /**\TODO test loading from scl and kbm files*/
+#endif
+
+ private:
+ Microtonal *testMicro;
+};
+
+int main()
+{
+ MicrotonalTest test;
+ RUN_TEST(testinit);
+ RUN_TEST(testXML);
+ return test_summary();
+}
diff --git a/src/Tests/MicrotonalTest.h b/src/Tests/MicrotonalTest.h
@@ -1,131 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- MicrotonalTest.h - CxxTest for Misc/Microtonal
- Copyright (C) 2009-2012 Mark McCurry
- Author: Mark McCurry
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-#include <cxxtest/TestSuite.h>
-#include <iostream>
-#include "../Misc/Microtonal.h"
-#include "../Misc/XMLwrapper.h"
-#include <cstring>
-#include <string>
-#include <cstdio>
-#include "../globals.h"
-using namespace std;
-using namespace zyn;
-
-SYNTH_T *synth;
-
-class MicrotonalTest:public CxxTest::TestSuite
-{
- public:
- int compression;
- void setUp() {
- compression = 0;
- synth = new SYNTH_T;
- testMicro = new Microtonal(compression);
- }
-
- void tearDown() {
- delete testMicro;
- delete synth;
- }
-
- //Verifies that the object is initialized correctly
- void testinit() {
- TS_ASSERT_EQUALS(testMicro->Pinvertupdown, 0);
- TS_ASSERT_EQUALS(testMicro->Pinvertupdowncenter, 60);
- TS_ASSERT_EQUALS(testMicro->getoctavesize(), 12);
- TS_ASSERT_EQUALS(testMicro->Penabled, 0);
- TS_ASSERT_EQUALS(testMicro->PAnote, 69);
- TS_ASSERT_EQUALS(testMicro->PAfreq, 440.0f);
- TS_ASSERT_EQUALS(testMicro->Pscaleshift, 64);
- TS_ASSERT_EQUALS(testMicro->Pfirstkey, 0);
- TS_ASSERT_EQUALS(testMicro->Plastkey, 127);
- TS_ASSERT_EQUALS(testMicro->Pmiddlenote, 60);
- TS_ASSERT_EQUALS(testMicro->Pmapsize, 12);
- TS_ASSERT_EQUALS(testMicro->Pmappingenabled, 0);
- TS_ASSERT_EQUALS(testMicro->Pglobalfinedetune, 64);
-
- TS_ASSERT_EQUALS(string((const char *)testMicro->Pname), "12tET");
- TS_ASSERT_EQUALS(string(
- (const char *)testMicro->Pcomment),
- "Equal Temperament 12 notes per octave");
-
- for(int i = 0; i < 128; ++i)
- TS_ASSERT_EQUALS(testMicro->Pmapping[i], i);
-
- TS_ASSERT_DELTA(testMicro->getnotefreq(19 / 12.0f, 0), 24.4997f, 0.0001f);
- }
-
- //Tests saving/loading to XML
- void testXML() {
- //Gah, the XMLwrapper is a twisted maze
- testMicro->Penabled = 1;
- XMLwrapper xml;
- xml.beginbranch("Dummy"); //this should not be needed, but odd behavior
- //seems to exist from MICROTONAL being on the
- //top of the stack
- xml.beginbranch("MICROTONAL");
- testMicro->add2XML(xml);
- xml.endbranch();
- xml.endbranch();
-
- char *tmp = xml.getXMLdata();
- Microtonal other(compression);
-
- other.Penabled = 1;
- strcpy((char *)other.Pname, "Myname"); //will be nicer with strings
-
- TS_ASSERT(*testMicro != other); //sanity check
-
- TS_ASSERT(xml.enterbranch("Dummy"));
- TS_ASSERT(xml.enterbranch("MICROTONAL"));
-
- other.getfromXML(xml);
- xml.exitbranch();
- xml.exitbranch();
- char *tmpo = xml.getXMLdata();
-
- TS_ASSERT(!strcmp(tmp, tmpo));
- free(tmp);
- free(tmpo);
- }
-
-#if 0
- /**\todo Test Saving/loading from file*/
-
- //Test texttomapping TODO finish
- void _testTextToMapping() {
- //the mapping is from old documentation for "Intense Diatonic" scale
- const char *mapping[12] =
- {"0", "x", "1", "x", "2", "3", "x", "4", "x", "5", "x", "6"};
- //for(int i=0;i<20;++i)
- // cout << i << ':' << testMicro->getnotefreq(i,0) << endl;
- //
- // octave size == 7
- // find dead notes
- }
- //Test texttotunings TODO finish
- void _testTextToTunings() {
- //the tuning is from old documentation for "Intense Diatonic" scale
- const char *tuning[7] =
- {"9/8", "5/4", "4/3", "3/2", "5/3", "15/8", "2/1"};
- const int numTunings = 7;
- //for(int i=0;i<20;++i)
- // cout << i << ':' << testMicro->getnotefreq(i,0) << endl;
- // go to middle key and verify the proportions
- }
- /**\TODO test loading from scl and kbm files*/
-#endif
-
- private:
- Microtonal *testMicro;
-};
diff --git a/src/Tests/MiddlewareTest.cpp b/src/Tests/MiddlewareTest.cpp
@@ -0,0 +1,156 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ PluginTest.h - CxxTest for embedding zyn
+ Copyright (C) 2013-2013 Mark McCurry
+ Authors: Mark McCurry
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+#include "test-suite.h"
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include "../Misc/MiddleWare.h"
+#include "../Misc/Master.h"
+#include "../Misc/PresetExtractor.h"
+#include "../Misc/PresetExtractor.cpp"
+#include "../Misc/Util.h"
+#include "../globals.h"
+#include "../UI/NSM.H"
+using namespace std;
+using namespace zyn;
+
+NSM_Client *nsm = 0;
+MiddleWare *middleware = 0;
+
+char *instance_name=(char*)"";
+
+#define NUM_MIDDLEWARE 3
+
+class PluginTest
+{
+ public:
+ Config config;
+ void setUp() {
+ synth = new SYNTH_T;
+ synth->buffersize = 256;
+ synth->samplerate = 48000;
+ //synth->alias();
+
+ outL = new float[1024];
+ for(int i = 0; i < synth->buffersize; ++i)
+ outL[i] = 0.0f;
+ outR = new float[1024];
+ for(int i = 0; i < synth->buffersize; ++i)
+ outR[i] = 0.0f;
+
+ delete synth;
+ synth = NULL;
+ for(int i = 0; i < NUM_MIDDLEWARE; ++i) {
+ synth = new SYNTH_T;
+ synth->buffersize = 256;
+ synth->samplerate = 48000;
+ //synth->alias();
+ middleware[i] = new MiddleWare(std::move(*synth), &config);
+ master[i] = middleware[i]->spawnMaster();
+ //printf("Octave size = %d\n", master[i]->microtonal.getoctavesize());
+ }
+ }
+
+ void tearDown() {
+ for(int i = 0; i < NUM_MIDDLEWARE; ++i)
+ delete middleware[i];
+
+ delete[] outL;
+ delete[] outR;
+ delete synth;
+ }
+
+
+ void testInit() {
+
+ for(int x=0; x<100; ++x) {
+ for(int i=0; i<NUM_MIDDLEWARE; ++i) {
+ middleware[i]->tick();
+ master[i]->GetAudioOutSamples(rand()%1025,
+ synth->samplerate, outL, outR);
+ }
+ }
+ }
+
+ void testPanic()
+ {
+ master[0]->setController(0, 0x64, 0);
+ master[0]->noteOn(0,64,64);
+ master[0]->AudioOut(outL, outR);
+
+ float sum = 0.0f;
+ for(int i = 0; i < synth->buffersize; ++i)
+ sum += fabsf(outL[i]);
+
+ TS_ASSERT(0.1f < sum);
+ }
+
+ string loadfile(string fname) const
+ {
+ std::ifstream t(fname.c_str());
+ std::string str((std::istreambuf_iterator<char>(t)),
+ std::istreambuf_iterator<char>());
+ return str;
+ }
+
+ void testLoad(void)
+ {
+ for(int i=0; i<NUM_MIDDLEWARE; ++i) {
+ middleware[i]->transmitMsg("/load-part", "is", 0, (string(SOURCE_DIR) + "/../../instruments/banks/Organ/0037-Church Organ 1.xiz").c_str());
+ middleware[i]->tick();
+ master[i]->GetAudioOutSamples(synth->buffersize, synth->samplerate, outL, outR);
+ middleware[i]->tick();
+ master[i]->GetAudioOutSamples(synth->buffersize, synth->samplerate, outL, outR);
+ middleware[i]->tick();
+ master[i]->GetAudioOutSamples(synth->buffersize, synth->samplerate, outL, outR);
+ middleware[i]->tick();
+ master[i]->GetAudioOutSamples(synth->buffersize, synth->samplerate, outL, outR);
+ middleware[i]->tick();
+ }
+ //const string fname = string(SOURCE_DIR) + "/../../instruments/banks/Organ/0037-Church Organ 1.xiz";
+ //const string fdata = loadfile(fname);
+ }
+
+ void testChangeToOutOfRangeProgram()
+ {
+ middleware[0]->transmitMsg("/bank/msb", "i", 0);
+ middleware[0]->tick();
+ middleware[0]->transmitMsg("/bank/lsb", "i", 1);
+ middleware[0]->tick();
+ middleware[0]->pendingSetProgram(0, 32);
+ middleware[0]->tick();
+ master[0]->GetAudioOutSamples(synth->buffersize, synth->samplerate, outL, outR);
+ // We should ideally be checking to verify that the part change
+ // didn't happen, but it's not clear how to do that. We're
+ // currently relying on the assert(filename) in loadPart() failing
+ // if this logic gets broken.
+ }
+
+ private:
+ SYNTH_T *synth;
+ float *outR, *outL;
+ MiddleWare *middleware[NUM_MIDDLEWARE];
+ Master *master[NUM_MIDDLEWARE];
+};
+
+int main()
+{
+ PluginTest test;
+ RUN_TEST(testInit);
+ RUN_TEST(testPanic);
+ RUN_TEST(testLoad);
+ RUN_TEST(testChangeToOutOfRangeProgram);
+ return test_summary();
+}
diff --git a/src/Tests/MiddlewareTest.h b/src/Tests/MiddlewareTest.h
@@ -1,146 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- PluginTest.h - CxxTest for embedding zyn
- Copyright (C) 2013-2013 Mark McCurry
- Authors: Mark McCurry
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-#include <cxxtest/TestSuite.h>
-#include <cmath>
-#include <cstdlib>
-#include <iostream>
-#include <fstream>
-#include <string>
-#include "../Misc/MiddleWare.h"
-#include "../Misc/Master.h"
-#include "../Misc/PresetExtractor.h"
-#include "../Misc/PresetExtractor.cpp"
-#include "../Misc/Util.h"
-#include "../globals.h"
-#include "../UI/NSM.H"
-using namespace std;
-using namespace zyn;
-
-NSM_Client *nsm = 0;
-MiddleWare *middleware = 0;
-
-char *instance_name=(char*)"";
-
-#define NUM_MIDDLEWARE 3
-
-class PluginTest:public CxxTest::TestSuite
-{
- public:
- Config config;
- void setUp() {
- synth = new SYNTH_T;
- synth->buffersize = 256;
- synth->samplerate = 48000;
- //synth->alias();
-
- outL = new float[1024];
- for(int i = 0; i < synth->buffersize; ++i)
- outL[i] = 0.0f;
- outR = new float[1024];
- for(int i = 0; i < synth->buffersize; ++i)
- outR[i] = 0.0f;
-
- delete synth;
- synth = NULL;
- for(int i = 0; i < NUM_MIDDLEWARE; ++i) {
- synth = new SYNTH_T;
- synth->buffersize = 256;
- synth->samplerate = 48000;
- //synth->alias();
- middleware[i] = new MiddleWare(std::move(*synth), &config);
- master[i] = middleware[i]->spawnMaster();
- //printf("Octave size = %d\n", master[i]->microtonal.getoctavesize());
- }
- }
-
- void tearDown() {
- for(int i = 0; i < NUM_MIDDLEWARE; ++i)
- delete middleware[i];
-
- delete[] outL;
- delete[] outR;
- delete synth;
- }
-
-
- void testInit() {
-
- for(int x=0; x<100; ++x) {
- for(int i=0; i<NUM_MIDDLEWARE; ++i) {
- middleware[i]->tick();
- master[i]->GetAudioOutSamples(rand()%1025,
- synth->samplerate, outL, outR);
- }
- }
- }
-
- void testPanic()
- {
- master[0]->setController(0, 0x64, 0);
- master[0]->noteOn(0,64,64);
- master[0]->AudioOut(outL, outR);
-
- float sum = 0.0f;
- for(int i = 0; i < synth->buffersize; ++i)
- sum += fabsf(outL[i]);
-
- TS_ASSERT_LESS_THAN(0.1f, sum);
- }
-
- string loadfile(string fname) const
- {
- std::ifstream t(fname.c_str());
- std::string str((std::istreambuf_iterator<char>(t)),
- std::istreambuf_iterator<char>());
- return str;
- }
-
- void testLoad(void)
- {
- for(int i=0; i<NUM_MIDDLEWARE; ++i) {
- middleware[i]->transmitMsg("/load-part", "is", 0, (string(SOURCE_DIR) + "/../../instruments/banks/Organ/0037-Church Organ 1.xiz").c_str());
- middleware[i]->tick();
- master[i]->GetAudioOutSamples(synth->buffersize, synth->samplerate, outL, outR);
- middleware[i]->tick();
- master[i]->GetAudioOutSamples(synth->buffersize, synth->samplerate, outL, outR);
- middleware[i]->tick();
- master[i]->GetAudioOutSamples(synth->buffersize, synth->samplerate, outL, outR);
- middleware[i]->tick();
- master[i]->GetAudioOutSamples(synth->buffersize, synth->samplerate, outL, outR);
- middleware[i]->tick();
- }
- //const string fname = string(SOURCE_DIR) + "/../../instruments/banks/Organ/0037-Church Organ 1.xiz";
- //const string fdata = loadfile(fname);
- }
-
- void testChangeToOutOfRangeProgram()
- {
- middleware[0]->transmitMsg("/bank/msb", "i", 0);
- middleware[0]->tick();
- middleware[0]->transmitMsg("/bank/lsb", "i", 1);
- middleware[0]->tick();
- middleware[0]->pendingSetProgram(0, 32);
- middleware[0]->tick();
- master[0]->GetAudioOutSamples(synth->buffersize, synth->samplerate, outL, outR);
- // We should ideally be checking to verify that the part change
- // didn't happen, but it's not clear how to do that. We're
- // currently relying on the assert(filename) in loadPart() failing
- // if this logic gets broken.
- }
-
- private:
- SYNTH_T *synth;
- float *outR, *outL;
- MiddleWare *middleware[NUM_MIDDLEWARE];
- Master *master[NUM_MIDDLEWARE];
-};
diff --git a/src/Tests/MqTest.cpp b/src/Tests/MqTest.cpp
@@ -0,0 +1,135 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ PluginTest.h - CxxTest for embedding zyn
+ Copyright (C) 2013-2013 Mark McCurry
+ Authors: Mark McCurry
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+#include "test-suite.h"
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <thread>
+#include <rtosc/thread-link.h>
+#include <unistd.h>
+#include "../Containers/MultiPseudoStack.h"
+using namespace std;
+using namespace zyn;
+
+char *instance_name=(char*)"";
+
+class MessageTest
+{
+ public:
+ MultiQueue *s;
+ void setUp() {
+ s = new MultiQueue;
+ }
+
+ void tearDown() {
+ delete s;
+ }
+
+ void testBasic(void)
+ {
+ auto *mem = s->alloc();
+ TS_NON_NULL(mem);
+ TS_NON_NULL(mem->memory);
+ TS_ASSERT(!s->read());
+ s->write(mem);
+ auto *mem2 = s->read();
+ assert_ptr_eq(mem, mem2,
+ "both locations are the same", __LINE__);
+ s->free(mem2);
+ }
+ void testMed(void)
+ {
+ for(int i=0; i<100; ++i) {
+ auto *mem = s->alloc();
+ TS_NON_NULL(mem);
+ TS_NON_NULL(mem->memory);
+ TS_ASSERT(!s->read());
+ s->write(mem);
+ auto *mem2 = s->read();
+ assert_ptr_eq(mem, mem2,
+ "both locations are the same", __LINE__);
+ s->free(mem2);
+ }
+ }
+
+#define OPS 1000
+#define THREADS 8
+ void testThreads(void)
+ {
+ uint8_t messages[OPS*THREADS];
+ memset(messages, 0, sizeof(messages));
+ std::thread *t[THREADS];
+ for(int i=0; i<THREADS; ++i) {
+ t[i] = new std::thread([this,i,&messages](){
+ int op=0;
+ while(op<OPS) {
+ int read = rand()%2;
+ if(read) {
+ auto *mem = s->read();
+ if(mem) {
+ //printf("r%d",i%10);
+ //printf("got: <%s>\n", mem->memory);
+ messages[atoi(mem->memory)]++;
+ }
+ s->free(mem);
+ } else {
+ auto *mem = s->alloc();
+ if(mem) {
+ sprintf(mem->memory,"%d written by %d@op%d", i*OPS+op,i,op);
+ //printf("w%d",i%10);
+ op++;
+ }
+ s->write(mem);
+ }
+ }
+ });
+ }
+
+ printf("thread started...\n");
+ for(int i=0; i<THREADS; ++i) {
+ t[i]->join();
+ delete t[i];
+ }
+ printf("thread stopped...\n");
+ //read the last few
+ while(1) {
+ auto *mem = s->read();
+ if(mem) {
+ printf("got: <%s>\n", mem->memory);
+ messages[atoi(mem->memory)]++;
+ } else
+ break;
+ s->free(mem);
+ }
+
+ int good = 1;
+ for(int i=0; i<OPS*THREADS; ++i) {
+ if(messages[i] != 1) {
+ assert(false);
+ good = 0;
+ }
+ }
+ TS_ASSERT(good);
+ }
+};
+
+int main()
+{
+ MessageTest test;
+ RUN_TEST(testBasic);
+ RUN_TEST(testMed);
+ RUN_TEST(testThreads);
+ return test_summary();
+}
diff --git a/src/Tests/MqTest.h b/src/Tests/MqTest.h
@@ -1,124 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- PluginTest.h - CxxTest for embedding zyn
- Copyright (C) 2013-2013 Mark McCurry
- Authors: Mark McCurry
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-#include <cxxtest/TestSuite.h>
-#include <cmath>
-#include <cstdlib>
-#include <iostream>
-#include <fstream>
-#include <string>
-#include <thread>
-#include <rtosc/thread-link.h>
-#include <unistd.h>
-#include "../Containers/MultiPseudoStack.h"
-using namespace std;
-using namespace zyn;
-
-char *instance_name=(char*)"";
-
-class MessageTest:public CxxTest::TestSuite
-{
- public:
- MultiQueue *s;
- void setUp() {
- s = new MultiQueue;
- }
-
- void tearDown() {
- delete s;
- }
-
- void testBasic(void)
- {
- auto *mem = s->alloc();
- TS_ASSERT(mem);
- TS_ASSERT(mem->memory);
- TS_ASSERT(!s->read());
- s->write(mem);
- auto *mem2 = s->read();
- TS_ASSERT_EQUALS(mem, mem2);
- s->free(mem2);
- }
- void testMed(void)
- {
- for(int i=0; i<100; ++i) {
- auto *mem = s->alloc();
- TS_ASSERT(mem);
- TS_ASSERT(mem->memory);
- TS_ASSERT(!s->read());
- s->write(mem);
- auto *mem2 = s->read();
- TS_ASSERT_EQUALS(mem, mem2);
- s->free(mem2);
- }
- }
-
-#define OPS 1000
-#define THREADS 8
- void testThreads(void)
- {
- uint8_t messages[OPS*THREADS];
- memset(messages, 0, sizeof(messages));
- std::thread *t[THREADS];
- for(int i=0; i<THREADS; ++i) {
- t[i] = new std::thread([this,i,&messages](){
- int op=0;
- while(op<OPS) {
- int read = rand()%2;
- if(read) {
- auto *mem = s->read();
- if(mem) {
- //printf("r%d",i%10);
- //printf("got: <%s>\n", mem->memory);
- messages[atoi(mem->memory)]++;
- }
- s->free(mem);
- } else {
- auto *mem = s->alloc();
- if(mem) {
- sprintf(mem->memory,"%d written by %d@op%d", i*OPS+op,i,op);
- //printf("w%d",i%10);
- op++;
- }
- s->write(mem);
- }
- }
- });
- }
-
- printf("thread started...\n");
- for(int i=0; i<THREADS; ++i) {
- t[i]->join();
- delete t[i];
- }
- printf("thread stopped...\n");
- //read the last few
- while(1) {
- auto *mem = s->read();
- if(mem) {
- printf("got: <%s>\n", mem->memory);
- messages[atoi(mem->memory)]++;
- } else
- break;
- s->free(mem);
- }
-
- int good = 1;
- for(int i=0; i<OPS*THREADS; ++i) {
- if(messages[i] != 1) {
- assert(false);
- good = 0;
- }
- }
- TS_ASSERT(good);
- }
-};
diff --git a/src/Tests/MsgParseTest.cpp b/src/Tests/MsgParseTest.cpp
@@ -0,0 +1,61 @@
+#include "test-suite.h"
+#include "../Misc/MsgParsing.h"
+
+class PluginTest
+{
+ public:
+ void setUp() {}
+
+ void tearDown() {}
+
+ void testExtracting() {
+ std::size_t res;
+ int part, kit, vc;
+ bool isFm;
+
+ // test a full string with OscilSmp
+ res = zyn::idsFromMsg("/part1/kit2/adpars/VoicePar3/OscilSmp", &part, &kit, &vc, &isFm);
+ TS_ASSERT(res);
+ TS_ASSERT_EQUAL_INT(part, 1);
+ TS_ASSERT_EQUAL_INT(kit, 2);
+ TS_ASSERT_EQUAL_INT(vc, 3);
+ TS_ASSERT(!isFm);
+ // translate back into string
+ std::string str = zyn::buildVoiceParMsg(&part, &kit, &vc, &isFm);
+ TS_ASSERT_EQUAL_STR("/part1/kit2/adpars/VoicePar3/OscilSmp", str.c_str());
+
+ // same with FMSmp
+ res = zyn::idsFromMsg("/part11/kit12/adpars/VoicePar13/FMSmp", &part, &kit, &vc, &isFm);
+ TS_ASSERT(res);
+ TS_ASSERT_EQUAL_INT(part, 11);
+ TS_ASSERT_EQUAL_INT(kit, 12);
+ TS_ASSERT_EQUAL_INT(vc, 13);
+ TS_ASSERT(isFm);
+ // translate back into string
+ str = zyn::buildVoiceParMsg(&part, &kit, &vc, &isFm);
+ TS_ASSERT_EQUAL_STR("/part11/kit12/adpars/VoicePar13/FMSmp", str.c_str());
+
+ // check return values
+ TS_ASSERT(!zyn::idsFromMsg("/part", &part, &kit, nullptr));
+ TS_ASSERT(!zyn::idsFromMsg("/part1", &part, &kit, nullptr));
+ TS_ASSERT(!zyn::idsFromMsg("/part1/kit", &part, &kit, nullptr));
+ TS_ASSERT(zyn::idsFromMsg("/part1/kit2", &part, &kit, nullptr));
+ TS_ASSERT(!zyn::idsFromMsg("/part1/kit2", &part, &kit, &vc));
+ TS_ASSERT(!zyn::idsFromMsg("/part1/kit2/adpars/", &part, &kit, &vc));
+ TS_ASSERT(!zyn::idsFromMsg("/part1/kit2/adpars/", &part, &kit, &vc));
+ TS_ASSERT(!zyn::idsFromMsg("/part1/kit2/adpars/VoicePar", &part, &kit, &vc));
+ TS_ASSERT(!zyn::idsFromMsg("/part1/kit2/adpars/VoicePar/", &part, &kit, &vc));
+ TS_ASSERT(zyn::idsFromMsg("/part1/kit2/adpars/VoicePar0/", &part, &kit, &vc));
+ TS_ASSERT(zyn::idsFromMsg("/part1/kit2/adpars/VoicePar0/XXX", &part, &kit, &vc));
+ TS_ASSERT(!zyn::idsFromMsg("/part1/kit2/adpars/VoicePar0/XXX", &part, &kit, &vc, &isFm));
+ TS_ASSERT(zyn::idsFromMsg("/part1/kit2/adpars/VoicePar0/OscilSmp", &part, &kit, &vc, &isFm));
+ TS_ASSERT(zyn::idsFromMsg("/part1/kit2/adpars/VoicePar0/FMSmp", &part, &kit, &vc, &isFm));
+ }
+};
+
+int main()
+{
+ PluginTest test;
+ RUN_TEST(testExtracting);
+ return test_summary();
+}
diff --git a/src/Tests/MsgParseTest.h b/src/Tests/MsgParseTest.h
@@ -1,59 +0,0 @@
-#ifndef MSGPARSETEST_H
-#define MSGPARSETEST_H
-
-#include <cxxtest/TestSuite.h>
-#include "../Misc/MsgParsing.h"
-
-class PluginTest:public CxxTest::TestSuite
-{
- public:
- void setUp() {}
-
- void tearDown() {}
-
- void testExtracting() {
- std::size_t res;
- int part, kit, vc;
- bool isFm;
-
- // test a full string with OscilSmp
- res = zyn::idsFromMsg("/part1/kit2/adpars/VoicePar3/OscilSmp", &part, &kit, &vc, &isFm);
- TS_ASSERT(res);
- TS_ASSERT_EQUALS(part, 1);
- TS_ASSERT_EQUALS(kit, 2);
- TS_ASSERT_EQUALS(vc, 3);
- TS_ASSERT(!isFm);
- // translate back into string
- std::string str = zyn::buildVoiceParMsg(&part, &kit, &vc, &isFm);
- TS_ASSERT_EQUALS(str, "/part1/kit2/adpars/VoicePar3/OscilSmp");
-
- // same with FMSmp
- res = zyn::idsFromMsg("/part11/kit12/adpars/VoicePar13/FMSmp", &part, &kit, &vc, &isFm);
- TS_ASSERT(res);
- TS_ASSERT_EQUALS(part, 11);
- TS_ASSERT_EQUALS(kit, 12);
- TS_ASSERT_EQUALS(vc, 13);
- TS_ASSERT(isFm);
- // translate back into string
- str = zyn::buildVoiceParMsg(&part, &kit, &vc, &isFm);
- TS_ASSERT_EQUALS(str, "/part11/kit12/adpars/VoicePar13/FMSmp");
-
- // check return values
- TS_ASSERT(!zyn::idsFromMsg("/part", &part, &kit, nullptr));
- TS_ASSERT(!zyn::idsFromMsg("/part1", &part, &kit, nullptr));
- TS_ASSERT(!zyn::idsFromMsg("/part1/kit", &part, &kit, nullptr));
- TS_ASSERT(zyn::idsFromMsg("/part1/kit2", &part, &kit, nullptr));
- TS_ASSERT(!zyn::idsFromMsg("/part1/kit2", &part, &kit, &vc));
- TS_ASSERT(!zyn::idsFromMsg("/part1/kit2/adpars/", &part, &kit, &vc));
- TS_ASSERT(!zyn::idsFromMsg("/part1/kit2/adpars/", &part, &kit, &vc));
- TS_ASSERT(!zyn::idsFromMsg("/part1/kit2/adpars/VoicePar", &part, &kit, &vc));
- TS_ASSERT(!zyn::idsFromMsg("/part1/kit2/adpars/VoicePar/", &part, &kit, &vc));
- TS_ASSERT(zyn::idsFromMsg("/part1/kit2/adpars/VoicePar0/", &part, &kit, &vc));
- TS_ASSERT(zyn::idsFromMsg("/part1/kit2/adpars/VoicePar0/XXX", &part, &kit, &vc));
- TS_ASSERT(!zyn::idsFromMsg("/part1/kit2/adpars/VoicePar0/XXX", &part, &kit, &vc, &isFm));
- TS_ASSERT(zyn::idsFromMsg("/part1/kit2/adpars/VoicePar0/OscilSmp", &part, &kit, &vc, &isFm));
- TS_ASSERT(zyn::idsFromMsg("/part1/kit2/adpars/VoicePar0/FMSmp", &part, &kit, &vc, &isFm));
- }
-};
-
-#endif // MSGPARSETEST_H
diff --git a/src/Tests/OscilGenTest.cpp b/src/Tests/OscilGenTest.cpp
@@ -0,0 +1,138 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ AdNoteTest.h - CxxTest for Synth/OscilGen
+ Copyright (C) 20011-2012 Mark McCurry
+ Author: Mark McCurry
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+#include "test-suite.h"
+#include <string>
+#include "../Synth/OscilGen.h"
+#include "../Misc/XMLwrapper.h"
+#include "../DSP/FFTwrapper.h"
+#include "../Misc/Util.h"
+#include "../globals.h"
+using namespace std;
+using namespace zyn;
+
+SYNTH_T *synth;
+
+class OscilGenTest
+{
+ public:
+ float freq;
+ float *outR, *outL;
+ FFTwrapper *fft;
+ OscilGen *oscil;
+
+ void setUp() {
+ synth = new SYNTH_T;
+ //First the sensible settings and variables that have to be set:
+ synth->buffersize = 256;
+ synth->oscilsize = 1024;
+
+ outL = new float[synth->oscilsize];
+ outR = new float[synth->oscilsize];
+ memset(outL, 0, sizeof(float) * synth->oscilsize);
+ memset(outR, 0, sizeof(float) * synth->oscilsize);
+
+ //prepare the default settings
+ fft = new FFTwrapper(synth->oscilsize);
+ oscil = new OscilGen(*synth, fft, NULL);
+
+ //Assert defaults [TODO]
+
+
+ XMLwrapper wrap;
+ wrap.loadXMLfile(string(SOURCE_DIR)
+ + string("/guitar-adnote.xmz"));
+ TS_ASSERT(wrap.enterbranch("MASTER"));
+ TS_ASSERT(wrap.enterbranch("PART", 0));
+ TS_ASSERT(wrap.enterbranch("INSTRUMENT"));
+ TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT"));
+ TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT_ITEM", 0));
+ TS_ASSERT(wrap.enterbranch("ADD_SYNTH_PARAMETERS"));
+ TS_ASSERT(wrap.enterbranch("VOICE", 0));
+ TS_ASSERT(wrap.enterbranch("OSCIL"));
+ oscil->getfromXML(wrap);
+
+ //verify xml was loaded [TODO]
+
+ //lets go with.... 50! as a nice note
+ const char testnote = 50;
+ freq = 440.0f * powf(2.0f, (testnote - 69.0f) / 12.0f);
+ }
+
+ void tearDown() {
+ delete oscil;
+ delete fft;
+ delete[] outL;
+ delete[] outR;
+ FFT_cleanup();
+ delete synth;
+ }
+
+ //verifies that initialization occurs
+ void testInit(void)
+ {
+ oscil->get(outL, freq);
+ }
+
+ void testOutput(void)
+ {
+ oscil->get(outL, freq);
+ TS_ASSERT_DELTA(outL[23], -0.5371f, 0.0001f);
+ TS_ASSERT_DELTA(outL[129], 0.3613f, 0.0001f);
+ TS_ASSERT_DELTA(outL[586], 0.1118f, 0.0001f);
+ TS_ASSERT_DELTA(outL[1023], -0.6889f, 0.0001f);
+ }
+
+ void testSpectrum(void)
+ {
+ oscil->getspectrum(synth->oscilsize / 2, outR, 1);
+ TS_ASSERT_DELTA(outR[1], 350.698059f, 0.0001f);
+ TS_ASSERT_DELTA(outR[2], 228.889267f, 0.0001f);
+ TS_ASSERT_DELTA(outR[3], 62.187931f, 0.0001f);
+ TS_ASSERT_DELTA(outR[4], 22.295225f, 0.0001f);
+ TS_ASSERT_DELTA(outR[5], 6.942001f, 0.0001f);
+ TS_ASSERT_DELTA(outR[27], 0.015110f, 0.0001f);
+ TS_ASSERT_DELTA(outR[48], 0.003425f, 0.0001f);
+ TS_ASSERT_DELTA(outR[66], 0.001293f, 0.0001f);
+ }
+
+ //performance testing
+ void testSpeed() {
+ const int samps = 15000;
+
+ int t_on = clock(); // timer before calling func
+ for(int i = 0; i < samps; ++i)
+ oscil->prepare();
+ int t_off = clock(); // timer when func returns
+
+ printf("OscilGenTest: %f seconds for %d prepares.\n",
+ (static_cast<float>(t_off - t_on)) / CLOCKS_PER_SEC, samps);
+
+ t_on = clock(); // timer before calling func
+ for(int i = 0; i < samps; ++i)
+ oscil->get(outL, freq);
+ t_off = clock(); // timer when func returns
+
+ printf("OscilGenTest: %f seconds for %d gets.\n",
+ (static_cast<float>(t_off - t_on)) / CLOCKS_PER_SEC, samps);
+ }
+};
+
+int main()
+{
+ OscilGenTest test;
+ RUN_TEST(testInit);
+ RUN_TEST(testOutput);
+ RUN_TEST(testSpectrum);
+ RUN_TEST(testSpeed);
+ return test_summary();
+}
diff --git a/src/Tests/OscilGenTest.h b/src/Tests/OscilGenTest.h
@@ -1,128 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- AdNoteTest.h - CxxTest for Synth/OscilGen
- Copyright (C) 20011-2012 Mark McCurry
- Author: Mark McCurry
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-#include <cxxtest/TestSuite.h>
-#include <string>
-#include "../Synth/OscilGen.h"
-#include "../Misc/XMLwrapper.h"
-#include "../DSP/FFTwrapper.h"
-#include "../Misc/Util.h"
-#include "../globals.h"
-using namespace std;
-using namespace zyn;
-
-SYNTH_T *synth;
-
-class OscilGenTest:public CxxTest::TestSuite
-{
- public:
- float freq;
- float *outR, *outL;
- FFTwrapper *fft;
- OscilGen *oscil;
-
- void setUp() {
- synth = new SYNTH_T;
- //First the sensible settings and variables that have to be set:
- synth->buffersize = 256;
- synth->oscilsize = 1024;
-
- outL = new float[synth->oscilsize];
- outR = new float[synth->oscilsize];
- memset(outL, 0, sizeof(float) * synth->oscilsize);
- memset(outR, 0, sizeof(float) * synth->oscilsize);
-
- //prepare the default settings
- fft = new FFTwrapper(synth->oscilsize);
- oscil = new OscilGen(*synth, fft, NULL);
-
- //Assert defaults [TODO]
-
-
- XMLwrapper wrap;
- wrap.loadXMLfile(string(SOURCE_DIR)
- + string("/guitar-adnote.xmz"));
- TS_ASSERT(wrap.enterbranch("MASTER"));
- TS_ASSERT(wrap.enterbranch("PART", 0));
- TS_ASSERT(wrap.enterbranch("INSTRUMENT"));
- TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT"));
- TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT_ITEM", 0));
- TS_ASSERT(wrap.enterbranch("ADD_SYNTH_PARAMETERS"));
- TS_ASSERT(wrap.enterbranch("VOICE", 0));
- TS_ASSERT(wrap.enterbranch("OSCIL"));
- oscil->getfromXML(wrap);
-
- //verify xml was loaded [TODO]
-
- //lets go with.... 50! as a nice note
- const char testnote = 50;
- freq = 440.0f * powf(2.0f, (testnote - 69.0f) / 12.0f);
- }
-
- void tearDown() {
- delete oscil;
- delete fft;
- delete[] outL;
- delete[] outR;
- FFT_cleanup();
- delete synth;
- }
-
- //verifies that initialization occurs
- void testInit(void)
- {
- oscil->get(outL, freq);
- }
-
- void testOutput(void)
- {
- oscil->get(outL, freq);
- TS_ASSERT_DELTA(outL[23], -0.5371f, 0.0001f);
- TS_ASSERT_DELTA(outL[129], 0.3613f, 0.0001f);
- TS_ASSERT_DELTA(outL[586], 0.1118f, 0.0001f);
- TS_ASSERT_DELTA(outL[1023], -0.6889f, 0.0001f);
- }
-
- void testSpectrum(void)
- {
- oscil->getspectrum(synth->oscilsize / 2, outR, 1);
- TS_ASSERT_DELTA(outR[1], 350.698059f, 0.0001f);
- TS_ASSERT_DELTA(outR[2], 228.889267f, 0.0001f);
- TS_ASSERT_DELTA(outR[3], 62.187931f, 0.0001f);
- TS_ASSERT_DELTA(outR[4], 22.295225f, 0.0001f);
- TS_ASSERT_DELTA(outR[5], 6.942001f, 0.0001f);
- TS_ASSERT_DELTA(outR[27], 0.015110f, 0.0001f);
- TS_ASSERT_DELTA(outR[48], 0.003425f, 0.0001f);
- TS_ASSERT_DELTA(outR[66], 0.001293f, 0.0001f);
- }
-
- //performance testing
- void testSpeed() {
- const int samps = 15000;
-
- int t_on = clock(); // timer before calling func
- for(int i = 0; i < samps; ++i)
- oscil->prepare();
- int t_off = clock(); // timer when func returns
-
- printf("OscilGenTest: %f seconds for %d prepares.\n",
- (static_cast<float>(t_off - t_on)) / CLOCKS_PER_SEC, samps);
-
- t_on = clock(); // timer before calling func
- for(int i = 0; i < samps; ++i)
- oscil->get(outL, freq);
- t_off = clock(); // timer when func returns
-
- printf("OscilGenTest: %f seconds for %d gets.\n",
- (static_cast<float>(t_off - t_on)) / CLOCKS_PER_SEC, samps);
- }
-};
diff --git a/src/Tests/PadNoteTest.cpp b/src/Tests/PadNoteTest.cpp
@@ -0,0 +1,299 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ PadNoteTest.h - CxxTest for Synth/PADnote
+ Copyright (C) 20012 zco
+ Author: zco
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+
+
+//Based Upon AdNoteTest.h and SubNoteTest.h
+#include "test-suite.h"
+#include <complex>
+#include <ctime>
+#include <string>
+#define private public
+#include "../Synth/PADnote.h"
+#undef private
+#include "../Misc/Master.h"
+#include "../Misc/Util.h"
+#include "../Misc/Allocator.h"
+#include "../Misc/XMLwrapper.h"
+#include "../Synth/PADnote.h"
+#include "../Synth/OscilGen.h"
+#include "../Params/PADnoteParameters.h"
+#include "../Params/Presets.h"
+#include "../DSP/FFTwrapper.h"
+#include "../globals.h"
+#include <rtosc/thread-link.h>
+using namespace std;
+using namespace zyn;
+
+SYNTH_T *synth;
+
+#ifndef SOURCE_DIR
+#define SOURCE_DIR "BE QUIET COMPILER"
+#endif
+
+class PadNoteTest
+{
+ public:
+ PADnote *note;
+ PADnoteParameters *pars;
+ Master *master;
+ FFTwrapper *fft;
+ Controller *controller;
+ AbsTime *time;
+ float test_freq_log2;
+ Alloc memory;
+ int interpolation;
+ rtosc::ThreadLink *tr;
+ WatchManager *w;
+
+
+ float *outR, *outL;
+
+ void setUp() {
+ interpolation = 0;
+ synth = new SYNTH_T;
+ //First the sensible settings and variables that have to be set:
+ synth->buffersize = 256;
+ time = new AbsTime(*synth);
+
+ outL = new float[synth->buffersize];
+ for(int i = 0; i < synth->buffersize; ++i)
+ *(outL + i) = 0;
+ outR = new float[synth->buffersize];
+ for(int i = 0; i < synth->buffersize; ++i)
+ *(outR + i) = 0;
+
+ tr = new rtosc::ThreadLink(1024,3);
+ w = new WatchManager(tr);
+
+ fft = new FFTwrapper(synth->oscilsize);
+ //prepare the default settings
+ pars = new PADnoteParameters(*synth, fft, time);
+
+
+ //Assert defaults
+ ///TS_ASSERT(!defaultPreset->VoicePar[1].Enabled);
+
+ XMLwrapper wrap;
+ //cout << string(SOURCE_DIR) + string("/guitar-adnote.xmz")
+ // << endl;
+ wrap.loadXMLfile(string(SOURCE_DIR)
+ + string("/guitar-adnote.xmz"));
+ TS_ASSERT(wrap.enterbranch("MASTER"));
+ TS_ASSERT(wrap.enterbranch("PART", 2));
+ TS_ASSERT(wrap.enterbranch("INSTRUMENT"));
+ TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT"));
+ TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT_ITEM", 0));
+ TS_ASSERT(wrap.enterbranch("PAD_SYNTH_PARAMETERS"));
+ pars->getfromXML(wrap);
+
+
+ //defaultPreset->defaults();
+ pars->applyparameters([]{return false;}, 1);
+
+ //verify xml was loaded
+ ///TS_ASSERT(defaultPreset->VoicePar[1].Enabled);
+
+
+
+ controller = new Controller(*synth, time);
+
+ //lets go with.... 50! as a nice note
+ test_freq_log2 = log2f(440.0f) + (50.0 - 69.0f) / 12.0f;
+ SynthParams pars_{memory, *controller, *synth, *time, 120, 0, test_freq_log2, false, prng()};
+
+ note = new PADnote(pars, pars_, interpolation);
+ }
+
+ void tearDown() {
+ delete note;
+ delete controller;
+ delete fft;
+ delete [] outL;
+ delete [] outR;
+ delete pars;
+ FFT_cleanup();
+ delete synth;
+
+ note = NULL;
+ controller = NULL;
+ fft = NULL;
+ outL = NULL;
+ outR = NULL;
+ pars = NULL;
+ synth = NULL;
+ }
+
+
+ void testDefaults() {
+ int sampleCount = 0;
+
+
+//#define WRITE_OUTPUT
+
+#ifdef WRITE_OUTPUT
+ ofstream file("padnoteout", ios::out);
+#endif
+ note->noteout(outL, outR);
+
+#ifdef WRITE_OUTPUT
+ for(int i = 0; i < synth->buffersize; ++i)
+ file << outL[i] << std::endl;
+
+#endif
+ sampleCount += synth->buffersize;
+
+ TS_ASSERT_DELTA(outL[255], 0.3950, 0.0005f);
+
+
+ note->releasekey();
+
+ TS_ASSERT(!tr->hasNext());
+ w->add_watch("noteout");
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], -0.2305f, 0.0005f);
+ w->tick();
+ TS_ASSERT(!tr->hasNext());
+
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], -0.1164f, 0.0005f);
+
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], 0.1079, 0.0005f);
+
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], 0.0841f, 0.0001f);
+
+ while(!note->finished()) {
+ note->noteout(outL, outR);
+
+#ifdef WRITE_OUTPUT
+ for(int i = 0; i < synth->buffersize; ++i)
+ file << outL[i] << std::endl;
+
+#endif
+ sampleCount += synth->buffersize;
+ }
+#ifdef WRITE_OUTPUT
+ file.close();
+#endif
+
+ TS_ASSERT_EQUAL_INT(sampleCount, 5888);
+ }
+
+ void testInitialization() {
+ TS_ASSERT(pars->Pmode == PADnoteParameters::pad_mode::bandwidth);
+
+ TS_ASSERT_EQUAL_INT(pars->PVolume, 90);
+ TS_NON_NULL(pars->oscilgen);
+ TS_NON_NULL(pars->resonance);
+
+ TS_ASSERT_DELTA(note->NoteGlobalPar.Volume, 2.597527f, 0.001f);
+ TS_ASSERT_DELTA(note->NoteGlobalPar.Panning, 0.500000f, 0.01f);
+
+
+ for(int i=0; i<8; ++i)
+ TS_NON_NULL(pars->sample[i].smp);
+ for(int i=8; i<PAD_MAX_SAMPLES; ++i)
+ TS_ASSERT(!pars->sample[i].smp);
+
+ TS_ASSERT_DELTA(pars->sample[0].smp[0], 0.0516f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[1], 0.0845f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[2], 0.1021f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[3], 0.0919f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[4], 0.0708f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[5], 0.0414f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[6], 0.0318f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[7], 0.0217f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[8], 0.0309f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[9], 0.0584f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[10], 0.0266f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[11], 0.0436f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[12], 0.0199f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[13], 0.0505f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[14], 0.0438f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[15], 0.0024f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[16], 0.0052f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[17], -0.0180f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[18], 0.0342f, 0.0005f);
+ TS_ASSERT_DELTA(pars->sample[0].smp[19], 0.0051f, 0.0005f);
+
+
+ //Verify Harmonic Input
+ float harmonics[synth->oscilsize];
+ memset(harmonics, 0, sizeof(float) * synth->oscilsize);
+
+ pars->oscilgen->get(harmonics, 440.0f, false);
+
+ TS_ASSERT_DELTA(harmonics[0] ,0.683947, 0.0005f);
+ TS_ASSERT_DELTA(harmonics[1] ,0.128246, 0.0005f);
+ TS_ASSERT_DELTA(harmonics[2] ,0.003238, 0.0005f);
+ TS_ASSERT_DELTA(harmonics[3] ,0.280945, 0.0005f);
+ TS_ASSERT_DELTA(harmonics[4] ,0.263548, 0.0005f);
+ TS_ASSERT_DELTA(harmonics[5] ,0.357070, 0.0005f);
+ TS_ASSERT_DELTA(harmonics[6] ,0.096287, 0.0005f);
+ TS_ASSERT_DELTA(harmonics[7] ,0.128685, 0.0005f);
+ TS_ASSERT_DELTA(harmonics[8] ,0.003238, 0.0005f);
+ TS_ASSERT_DELTA(harmonics[9] ,0.149376, 0.0005f);
+ TS_ASSERT_DELTA(harmonics[10],0.063892, 0.0005f);
+ TS_ASSERT_DELTA(harmonics[11],0.296716, 0.0005f);
+ TS_ASSERT_DELTA(harmonics[12],0.051057, 0.0005f);
+ TS_ASSERT_DELTA(harmonics[13],0.066310, 0.0005f);
+ TS_ASSERT_DELTA(harmonics[14],0.004006, 0.0005f);
+ TS_ASSERT_DELTA(harmonics[15],0.038662, 0.0005f);
+
+ float sum = 0;
+ for(int i=0; i<synth->oscilsize/2; ++i)
+ sum += harmonics[i];
+ TS_ASSERT_DELTA(sum, 5.863001, 0.0005f);
+
+ TS_ASSERT_DELTA(pars->getNhr(0), 0.000000, 0.0005f);
+ TS_ASSERT_DELTA(pars->getNhr(1), 1.000000, 0.0005f);
+ TS_ASSERT_DELTA(pars->getNhr(2), 2.000000, 0.0005f);
+ TS_ASSERT_DELTA(pars->getNhr(3), 3.000000, 0.0005f);
+ TS_ASSERT_DELTA(pars->getNhr(4), 4.000000, 0.0005f);
+ TS_ASSERT_DELTA(pars->getNhr(5), 5.000000, 0.0005f);
+ TS_ASSERT_DELTA(pars->getNhr(6), 6.000000, 0.0005f);
+ TS_ASSERT_DELTA(pars->getNhr(7), 7.000000, 0.0005f);
+ TS_ASSERT_DELTA(pars->getNhr(8), 8.000000, 0.0005f);
+ TS_ASSERT_DELTA(pars->getNhr(9), 9.000000, 0.0005f);
+
+ }
+
+#define OUTPUT_PROFILE
+#ifdef OUTPUT_PROFILE
+ void testSpeed() {
+ const int samps = 15000;
+
+ int t_on = clock(); // timer before calling func
+ for(int i = 0; i < samps; ++i)
+ note->noteout(outL, outR);
+ int t_off = clock(); // timer when func returns
+
+ printf("PadNoteTest: %f seconds for %d Samples to be generated.\n",
+ (static_cast<float>(t_off - t_on)) / CLOCKS_PER_SEC, samps);
+ }
+#endif
+};
+
+int main()
+{
+ PadNoteTest test;
+ RUN_TEST(testDefaults);
+ RUN_TEST(testInitialization);
+ RUN_TEST(testSpeed);
+ return test_summary();
+}
diff --git a/src/Tests/PadNoteTest.h b/src/Tests/PadNoteTest.h
@@ -1,289 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- PadNoteTest.h - CxxTest for Synth/PADnote
- Copyright (C) 20012 zco
- Author: zco
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-
-
-//Based Upon AdNoteTest.h and SubNoteTest.h
-#include <cxxtest/TestSuite.h>
-#include <iostream>
-#include <fstream>
-#include <ctime>
-#include <string>
-#define private public
-#include "../Misc/Master.h"
-#include "../Misc/Util.h"
-#include "../Misc/Allocator.h"
-#include "../Misc/XMLwrapper.h"
-#include "../Synth/PADnote.h"
-#include "../Synth/OscilGen.h"
-#include "../Params/PADnoteParameters.h"
-#include "../Params/Presets.h"
-#include "../DSP/FFTwrapper.h"
-#include "../globals.h"
-#include <rtosc/thread-link.h>
-using namespace std;
-using namespace zyn;
-
-SYNTH_T *synth;
-
-#ifndef SOURCE_DIR
-#define SOURCE_DIR "BE QUIET COMPILER"
-#endif
-
-class PadNoteTest:public CxxTest::TestSuite
-{
- public:
- PADnote *note;
- PADnoteParameters *pars;
- Master *master;
- FFTwrapper *fft;
- Controller *controller;
- AbsTime *time;
- float test_freq_log2;
- Alloc memory;
- int interpolation;
- rtosc::ThreadLink *tr;
- WatchManager *w;
-
-
- float *outR, *outL;
-
- void setUp() {
- interpolation = 0;
- synth = new SYNTH_T;
- //First the sensible settings and variables that have to be set:
- synth->buffersize = 256;
- time = new AbsTime(*synth);
-
- outL = new float[synth->buffersize];
- for(int i = 0; i < synth->buffersize; ++i)
- *(outL + i) = 0;
- outR = new float[synth->buffersize];
- for(int i = 0; i < synth->buffersize; ++i)
- *(outR + i) = 0;
-
- tr = new rtosc::ThreadLink(1024,3);
- w = new WatchManager(tr);
-
- fft = new FFTwrapper(synth->oscilsize);
- //prepare the default settings
- pars = new PADnoteParameters(*synth, fft, time);
-
-
- //Assert defaults
- ///TS_ASSERT(!defaultPreset->VoicePar[1].Enabled);
-
- XMLwrapper wrap;
- cout << string(SOURCE_DIR) + string("/guitar-adnote.xmz")
- << endl;
- wrap.loadXMLfile(string(SOURCE_DIR)
- + string("/guitar-adnote.xmz"));
- TS_ASSERT(wrap.enterbranch("MASTER"));
- TS_ASSERT(wrap.enterbranch("PART", 2));
- TS_ASSERT(wrap.enterbranch("INSTRUMENT"));
- TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT"));
- TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT_ITEM", 0));
- TS_ASSERT(wrap.enterbranch("PAD_SYNTH_PARAMETERS"));
- pars->getfromXML(wrap);
-
-
- //defaultPreset->defaults();
- pars->applyparameters([]{return false;}, 1);
-
- //verify xml was loaded
- ///TS_ASSERT(defaultPreset->VoicePar[1].Enabled);
-
-
-
- controller = new Controller(*synth, time);
-
- //lets go with.... 50! as a nice note
- test_freq_log2 = log2f(440.0f) + (50.0 - 69.0f) / 12.0f;
- SynthParams pars_{memory, *controller, *synth, *time, 120, 0, test_freq_log2, false, prng()};
-
- note = new PADnote(pars, pars_, interpolation);
- }
-
- void tearDown() {
- delete note;
- delete controller;
- delete fft;
- delete [] outL;
- delete [] outR;
- delete pars;
- FFT_cleanup();
- delete synth;
-
- note = NULL;
- controller = NULL;
- fft = NULL;
- outL = NULL;
- outR = NULL;
- pars = NULL;
- synth = NULL;
- }
-
-
- void testDefaults() {
- int sampleCount = 0;
-
-
-//#define WRITE_OUTPUT
-
-#ifdef WRITE_OUTPUT
- ofstream file("padnoteout", ios::out);
-#endif
- note->noteout(outL, outR);
-
-#ifdef WRITE_OUTPUT
- for(int i = 0; i < synth->buffersize; ++i)
- file << outL[i] << std::endl;
-
-#endif
- sampleCount += synth->buffersize;
-
- TS_ASSERT_DELTA(outL[255], 0.3950, 0.0005f);
-
-
- note->releasekey();
-
- TS_ASSERT(!tr->hasNext());
- w->add_watch("noteout");
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], -0.2305f, 0.0005f);
- w->tick();
- TS_ASSERT(!tr->hasNext());
-
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], -0.1164f, 0.0005f);
-
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], 0.1079, 0.0005f);
-
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], 0.0841f, 0.0001f);
-
- while(!note->finished()) {
- note->noteout(outL, outR);
-
-#ifdef WRITE_OUTPUT
- for(int i = 0; i < synth->buffersize; ++i)
- file << outL[i] << std::endl;
-
-#endif
- sampleCount += synth->buffersize;
- }
-#ifdef WRITE_OUTPUT
- file.close();
-#endif
-
- TS_ASSERT_EQUALS(sampleCount, 5888);
- }
-
- void testInitialization() {
- TS_ASSERT_EQUALS(pars->Pmode, PADnoteParameters::pad_mode::bandwidth);
-
- TS_ASSERT_EQUALS(pars->PVolume, 90);
- TS_ASSERT(pars->oscilgen);
- TS_ASSERT(pars->resonance);
-
- TS_ASSERT_DELTA(note->NoteGlobalPar.Volume, 2.597527f, 0.001f);
- TS_ASSERT_DELTA(note->NoteGlobalPar.Panning, 0.500000f, 0.01f);
-
-
- for(int i=0; i<8; ++i)
- TS_ASSERT(pars->sample[i].smp);
- for(int i=8; i<PAD_MAX_SAMPLES; ++i)
- TS_ASSERT(!pars->sample[i].smp);
-
- TS_ASSERT_DELTA(pars->sample[0].smp[0], 0.0516f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[1], 0.0845f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[2], 0.1021f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[3], 0.0919f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[4], 0.0708f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[5], 0.0414f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[6], 0.0318f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[7], 0.0217f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[8], 0.0309f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[9], 0.0584f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[10], 0.0266f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[11], 0.0436f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[12], 0.0199f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[13], 0.0505f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[14], 0.0438f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[15], 0.0024f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[16], 0.0052f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[17], -0.0180f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[18], 0.0342f, 0.0005f);
- TS_ASSERT_DELTA(pars->sample[0].smp[19], 0.0051f, 0.0005f);
-
-
- //Verify Harmonic Input
- float harmonics[synth->oscilsize];
- memset(harmonics, 0, sizeof(float) * synth->oscilsize);
-
- pars->oscilgen->get(harmonics, 440.0f, false);
-
- TS_ASSERT_DELTA(harmonics[0] ,0.683947, 0.0005f);
- TS_ASSERT_DELTA(harmonics[1] ,0.128246, 0.0005f);
- TS_ASSERT_DELTA(harmonics[2] ,0.003238, 0.0005f);
- TS_ASSERT_DELTA(harmonics[3] ,0.280945, 0.0005f);
- TS_ASSERT_DELTA(harmonics[4] ,0.263548, 0.0005f);
- TS_ASSERT_DELTA(harmonics[5] ,0.357070, 0.0005f);
- TS_ASSERT_DELTA(harmonics[6] ,0.096287, 0.0005f);
- TS_ASSERT_DELTA(harmonics[7] ,0.128685, 0.0005f);
- TS_ASSERT_DELTA(harmonics[8] ,0.003238, 0.0005f);
- TS_ASSERT_DELTA(harmonics[9] ,0.149376, 0.0005f);
- TS_ASSERT_DELTA(harmonics[10],0.063892, 0.0005f);
- TS_ASSERT_DELTA(harmonics[11],0.296716, 0.0005f);
- TS_ASSERT_DELTA(harmonics[12],0.051057, 0.0005f);
- TS_ASSERT_DELTA(harmonics[13],0.066310, 0.0005f);
- TS_ASSERT_DELTA(harmonics[14],0.004006, 0.0005f);
- TS_ASSERT_DELTA(harmonics[15],0.038662, 0.0005f);
-
- float sum = 0;
- for(int i=0; i<synth->oscilsize/2; ++i)
- sum += harmonics[i];
- TS_ASSERT_DELTA(sum, 5.863001, 0.0005f);
-
- TS_ASSERT_DELTA(pars->getNhr(0), 0.000000, 0.0005f);
- TS_ASSERT_DELTA(pars->getNhr(1), 1.000000, 0.0005f);
- TS_ASSERT_DELTA(pars->getNhr(2), 2.000000, 0.0005f);
- TS_ASSERT_DELTA(pars->getNhr(3), 3.000000, 0.0005f);
- TS_ASSERT_DELTA(pars->getNhr(4), 4.000000, 0.0005f);
- TS_ASSERT_DELTA(pars->getNhr(5), 5.000000, 0.0005f);
- TS_ASSERT_DELTA(pars->getNhr(6), 6.000000, 0.0005f);
- TS_ASSERT_DELTA(pars->getNhr(7), 7.000000, 0.0005f);
- TS_ASSERT_DELTA(pars->getNhr(8), 8.000000, 0.0005f);
- TS_ASSERT_DELTA(pars->getNhr(9), 9.000000, 0.0005f);
-
- }
-
-#define OUTPUT_PROFILE
-#ifdef OUTPUT_PROFILE
- void testSpeed() {
- const int samps = 15000;
-
- int t_on = clock(); // timer before calling func
- for(int i = 0; i < samps; ++i)
- note->noteout(outL, outR);
- int t_off = clock(); // timer when func returns
-
- printf("PadNoteTest: %f seconds for %d Samples to be generated.\n",
- (static_cast<float>(t_off - t_on)) / CLOCKS_PER_SEC, samps);
- }
-#endif
-};
diff --git a/src/Tests/PluginTest.cpp b/src/Tests/PluginTest.cpp
@@ -0,0 +1,252 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ PluginTest.h - CxxTest for embedding zyn
+ Copyright (C) 2013-2013 Mark McCurry
+ Authors: Mark McCurry
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+#include "test-suite.h"
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include "../Misc/MiddleWare.h"
+#include "../Misc/Master.h"
+#include "../Misc/PresetExtractor.h"
+#include "../Misc/PresetExtractor.cpp"
+#include "../Misc/Util.h"
+#include "../globals.h"
+#include "../UI/NSM.H"
+
+using namespace std;
+using namespace zyn;
+
+SYNTH_T *synth;
+NSM_Client *nsm = 0;
+
+char *instance_name=(char*)"";
+MiddleWare *middleware;
+
+void fill_vec_with_lines(std::vector<string> &v, string s)
+{
+ std::istringstream stream(s);
+ std::string line;
+ while(std::getline(stream, line))
+ v.push_back(line);
+}
+void print_string_differences(string orig, string next)
+{
+ std::vector<string> a, b;
+ fill_vec_with_lines(a, orig);
+ fill_vec_with_lines(b, next);
+ int N = a.size();
+ int M = b.size();
+ printf("%d vs %d\n", N, M);
+
+ //Original String by New String
+ //Each step is either an insertion, deletion, or match
+ //Match is 0 cost and moves +1 State (if symbols are the same)
+ //Replace is 3 cost and moves +1 State (if symbols are different)
+ //Insertion is 2 cost and moves +2 State (+2 if symbols are different)
+ //Deletion is 1 cost and moves +0 State (+2 if symbols are different)
+ char *transition = new char[N*M];
+ float *cost = new float[N*M];
+
+ const int match = 1;
+ const int insert = 2;
+ const int del = 3;
+ for(int i=0; i<N; ++i) {
+ for(int j=0; j<M; ++j) {
+ transition[i*M + j] = 0;
+ cost[i*M + j] = 0xffff;
+ }
+ }
+
+ //Just assume the -1 line is the same
+ cost[0*M + 0] = (a[0] != b[0])*3;
+ cost[0*M + 1] = (a[1] != b[0])*2 + 2;
+ for(int i=1; i<N; ++i) {
+ for(int j=0; j<M; ++j) {
+ int cost_match = 0xffffff;
+ int cost_ins = 0xffffff;
+ int cost_del = 0xffffff;
+ cost_del = cost[(i-1)*M + j] + 2 + (a[i] != b[j])*2;
+ if(j > 1)
+ cost_ins = cost[(i-1)*M + (j-2)] + 1 + 2*(a[i] != b[j]);
+ if(j > 0)
+ cost_match = cost[(i-1)*M + (j-1)] + 3*(a[i] != b[j]);
+
+ if(cost_match >= 0xffff && cost_ins >= 0xffff && cost_del >= 0xffff) {
+ ;
+ } else if(cost_match < cost_ins && cost_match < cost_del) {
+ cost[i*M+j] = cost_match;
+ transition[i*M+j] = match;
+ } else if(cost_ins < cost_del) {
+ cost[i*M+j] = cost_ins;
+ transition[i*M+j] = insert;
+ } else {
+ cost[i*M+j] = cost_del;
+ transition[i*M+j] = del;
+ }
+ }
+ }
+
+ //int off = 0;
+ //int len = N;
+ //for(int i=off; i<off+len; ++i) {
+ // for(int j=off; j<off+len; ++j) {
+ // printf("%4d ", (int)(cost[i*M+j] > 4000 ? -1 : cost[i*M+j]));
+ // }
+ // printf("\n");
+ //}
+ //for(int i=off; i<off+len; ++i) {
+ // for(int j=off; j<off+len; ++j) {
+ // printf("%d ", transition[i*M+j]);
+ // }
+ // printf("\n");
+ //}
+
+ //for(int i=off; i<off+len; ++i)
+ // printf("%d: %s\n", i, a[i].c_str());
+ //for(int i=off; i<off+len; ++i)
+ // printf("%d: %s\n", i, b[i].c_str());
+ //exit(1);
+
+ int total_cost = cost[(N-1)*M + (M-1)];
+ if(total_cost < 500) {
+ printf("total cost = %f\n", cost[(N-1)*M + (M-1)]);
+
+ int b_pos = b.size()-1;
+ int a_pos = a.size()-1;
+ while(a_pos > 0 && b_pos > 0) {
+ //printf("state = (%d, %d) => %f\n", a_pos, b_pos, cost[a_pos*M+b_pos]);
+ if(transition[a_pos*M+b_pos] == match) {
+ if(a[a_pos] != b[b_pos]) {
+ printf("REF - %s\n", a[a_pos].c_str());
+ printf("NEW + %s\n", b[b_pos].c_str());
+ }
+ //printf("R");
+ a_pos -= 1;
+ b_pos -= 1;
+ } else if(transition[a_pos*M+b_pos] == del) {
+ //printf("D");
+ //if(a[a_pos] != b[b_pos]) {
+ //printf("- %s\n", a[a_pos].c_str());
+ printf("NEW - %s\n", b[b_pos].c_str());
+ //}
+ b_pos -= 1;
+ } else if(transition[a_pos*M+b_pos] == insert) {
+ //if(a[a_pos] != b[b_pos]) {
+ printf("REF - %s\n", a[a_pos].c_str());
+ printf("NEW + %s\n", b[b_pos].c_str());
+ printf("NEW + %s\n", b[b_pos-1].c_str());
+ //}
+ //printf("I");
+ a_pos -= 1;
+ b_pos -= 2;
+ } else {
+ printf("ERROR STATE @(%d, %d)\n", a_pos, b_pos);
+ exit(1);
+ }
+
+ }
+ //printf("%d vs %d\n", N, M);
+ } else {
+ printf("[WARNING] XML File appears to be radically different\n");
+ }
+}
+
+class PluginTest
+{
+ public:
+ Config config;
+ void setUp() {
+ synth = new SYNTH_T;
+ synth->buffersize = 256;
+ synth->samplerate = 48000;
+ synth->alias();
+
+ outL = new float[1024];
+ for(int i = 0; i < synth->buffersize; ++i)
+ outL[i] = 0.0f;
+ outR = new float[1024];
+ for(int i = 0; i < synth->buffersize; ++i)
+ outR[i] = 0.0f;
+
+ for(int i = 0; i < 16; ++i)
+ master[i] = new Master(*synth, &config);
+ }
+
+ void tearDown() {
+ for(int i = 0; i < 16; ++i)
+ delete master[i];
+
+ delete[] outL;
+ delete[] outR;
+ delete synth;
+ }
+
+
+ void testInit() {
+
+ for(int x=0; x<100; ++x)
+ for(int i=0; i<16; ++i)
+ master[i]->GetAudioOutSamples(rand()%1025,
+ synth->samplerate, outL, outR);
+ }
+
+ void testPanic()
+ {
+ master[0]->setController(0, 0x64, 0);
+ master[0]->noteOn(0,64,64);
+ master[0]->AudioOut(outL, outR);
+
+ float sum = 0.0f;
+ for(int i = 0; i < synth->buffersize; ++i)
+ sum += fabsf(outL[i]);
+
+ TS_ASSERT(0.1f < sum);
+ }
+
+ string loadfile(string fname) const
+ {
+ std::ifstream t(fname.c_str());
+ std::string str((std::istreambuf_iterator<char>(t)),
+ std::istreambuf_iterator<char>());
+ return str;
+ }
+
+
+ void testLoadSave(void)
+ {
+ const string fname = string(SOURCE_DIR) + "/guitar-adnote.xmz";
+ const string fdata = loadfile(fname);
+ char *result = NULL;
+ master[0]->putalldata((char*)fdata.c_str());
+ int res = master[0]->getalldata(&result);
+
+ TS_ASSERT_EQUAL_INT((int)(fdata.length()+1), res);
+ TS_ASSERT(fdata == result);
+ if(fdata != result)
+ print_string_differences(fdata, result);
+ }
+
+
+ private:
+ float *outR, *outL;
+ Master *master[16];
+};
+
+int main()
+{
+ PluginTest test;
+ RUN_TEST(testInit);
+ RUN_TEST(testPanic);
+ RUN_TEST(testLoadSave);
+}
diff --git a/src/Tests/PluginTest.h b/src/Tests/PluginTest.h
@@ -1,244 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- PluginTest.h - CxxTest for embedding zyn
- Copyright (C) 2013-2013 Mark McCurry
- Authors: Mark McCurry
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-#include <cxxtest/TestSuite.h>
-#include <cmath>
-#include <cstdlib>
-#include <iostream>
-#include <fstream>
-#include <string>
-#include "../Misc/MiddleWare.h"
-#include "../Misc/Master.h"
-#include "../Misc/PresetExtractor.h"
-#include "../Misc/PresetExtractor.cpp"
-#include "../Misc/Util.h"
-#include "../globals.h"
-#include "../UI/NSM.H"
-
-using namespace std;
-using namespace zyn;
-
-SYNTH_T *synth;
-NSM_Client *nsm = 0;
-
-char *instance_name=(char*)"";
-MiddleWare *middleware;
-
-void fill_vec_with_lines(std::vector<string> &v, string s)
-{
- std::istringstream stream(s);
- std::string line;
- while(std::getline(stream, line))
- v.push_back(line);
-}
-void print_string_differences(string orig, string next)
-{
- std::vector<string> a, b;
- fill_vec_with_lines(a, orig);
- fill_vec_with_lines(b, next);
- int N = a.size();
- int M = b.size();
- printf("%d vs %d\n", N, M);
-
- //Original String by New String
- //Each step is either an insertion, deletion, or match
- //Match is 0 cost and moves +1 State (if symbols are the same)
- //Replace is 3 cost and moves +1 State (if symbols are different)
- //Insertion is 2 cost and moves +2 State (+2 if symbols are different)
- //Deletion is 1 cost and moves +0 State (+2 if symbols are different)
- char *transition = new char[N*M];
- float *cost = new float[N*M];
-
- const int match = 1;
- const int insert = 2;
- const int del = 3;
- for(int i=0; i<N; ++i) {
- for(int j=0; j<M; ++j) {
- transition[i*M + j] = 0;
- cost[i*M + j] = 0xffff;
- }
- }
-
- //Just assume the -1 line is the same
- cost[0*M + 0] = (a[0] != b[0])*3;
- cost[0*M + 1] = (a[1] != b[0])*2 + 2;
- for(int i=1; i<N; ++i) {
- for(int j=0; j<M; ++j) {
- int cost_match = 0xffffff;
- int cost_ins = 0xffffff;
- int cost_del = 0xffffff;
- cost_del = cost[(i-1)*M + j] + 2 + (a[i] != b[j])*2;
- if(j > 1)
- cost_ins = cost[(i-1)*M + (j-2)] + 1 + 2*(a[i] != b[j]);
- if(j > 0)
- cost_match = cost[(i-1)*M + (j-1)] + 3*(a[i] != b[j]);
-
- if(cost_match >= 0xffff && cost_ins >= 0xffff && cost_del >= 0xffff) {
- ;
- } else if(cost_match < cost_ins && cost_match < cost_del) {
- cost[i*M+j] = cost_match;
- transition[i*M+j] = match;
- } else if(cost_ins < cost_del) {
- cost[i*M+j] = cost_ins;
- transition[i*M+j] = insert;
- } else {
- cost[i*M+j] = cost_del;
- transition[i*M+j] = del;
- }
- }
- }
-
- //int off = 0;
- //int len = N;
- //for(int i=off; i<off+len; ++i) {
- // for(int j=off; j<off+len; ++j) {
- // printf("%4d ", (int)(cost[i*M+j] > 4000 ? -1 : cost[i*M+j]));
- // }
- // printf("\n");
- //}
- //for(int i=off; i<off+len; ++i) {
- // for(int j=off; j<off+len; ++j) {
- // printf("%d ", transition[i*M+j]);
- // }
- // printf("\n");
- //}
-
- //for(int i=off; i<off+len; ++i)
- // printf("%d: %s\n", i, a[i].c_str());
- //for(int i=off; i<off+len; ++i)
- // printf("%d: %s\n", i, b[i].c_str());
- //exit(1);
-
- int total_cost = cost[(N-1)*M + (M-1)];
- if(total_cost < 500) {
- printf("total cost = %f\n", cost[(N-1)*M + (M-1)]);
-
- int b_pos = b.size()-1;
- int a_pos = a.size()-1;
- while(a_pos > 0 && b_pos > 0) {
- //printf("state = (%d, %d) => %f\n", a_pos, b_pos, cost[a_pos*M+b_pos]);
- if(transition[a_pos*M+b_pos] == match) {
- if(a[a_pos] != b[b_pos]) {
- printf("REF - %s\n", a[a_pos].c_str());
- printf("NEW + %s\n", b[b_pos].c_str());
- }
- //printf("R");
- a_pos -= 1;
- b_pos -= 1;
- } else if(transition[a_pos*M+b_pos] == del) {
- //printf("D");
- //if(a[a_pos] != b[b_pos]) {
- //printf("- %s\n", a[a_pos].c_str());
- printf("NEW - %s\n", b[b_pos].c_str());
- //}
- b_pos -= 1;
- } else if(transition[a_pos*M+b_pos] == insert) {
- //if(a[a_pos] != b[b_pos]) {
- printf("REF - %s\n", a[a_pos].c_str());
- printf("NEW + %s\n", b[b_pos].c_str());
- printf("NEW + %s\n", b[b_pos-1].c_str());
- //}
- //printf("I");
- a_pos -= 1;
- b_pos -= 2;
- } else {
- printf("ERROR STATE @(%d, %d)\n", a_pos, b_pos);
- exit(1);
- }
-
- }
- //printf("%d vs %d\n", N, M);
- } else {
- printf("[WARNING] XML File appears to be radically different\n");
- }
-}
-
-class PluginTest:public CxxTest::TestSuite
-{
- public:
- Config config;
- void setUp() {
- synth = new SYNTH_T;
- synth->buffersize = 256;
- synth->samplerate = 48000;
- synth->alias();
-
- outL = new float[1024];
- for(int i = 0; i < synth->buffersize; ++i)
- outL[i] = 0.0f;
- outR = new float[1024];
- for(int i = 0; i < synth->buffersize; ++i)
- outR[i] = 0.0f;
-
- for(int i = 0; i < 16; ++i)
- master[i] = new Master(*synth, &config);
- }
-
- void tearDown() {
- for(int i = 0; i < 16; ++i)
- delete master[i];
-
- delete[] outL;
- delete[] outR;
- delete synth;
- }
-
-
- void testInit() {
-
- for(int x=0; x<100; ++x)
- for(int i=0; i<16; ++i)
- master[i]->GetAudioOutSamples(rand()%1025,
- synth->samplerate, outL, outR);
- }
-
- void testPanic()
- {
- master[0]->setController(0, 0x64, 0);
- master[0]->noteOn(0,64,64);
- master[0]->AudioOut(outL, outR);
-
- float sum = 0.0f;
- for(int i = 0; i < synth->buffersize; ++i)
- sum += fabsf(outL[i]);
-
- TS_ASSERT_LESS_THAN(0.1f, sum);
- }
-
- string loadfile(string fname) const
- {
- std::ifstream t(fname.c_str());
- std::string str((std::istreambuf_iterator<char>(t)),
- std::istreambuf_iterator<char>());
- return str;
- }
-
-
- void testLoadSave(void)
- {
- const string fname = string(SOURCE_DIR) + "/guitar-adnote.xmz";
- const string fdata = loadfile(fname);
- char *result = NULL;
- master[0]->putalldata((char*)fdata.c_str());
- int res = master[0]->getalldata(&result);
-
- TS_ASSERT_EQUALS((int)(fdata.length()+1), res);
- TS_ASSERT(fdata == result);
- if(fdata != result)
- print_string_differences(fdata, result);
- }
-
-
- private:
- float *outR, *outL;
- Master *master[16];
-};
diff --git a/src/Tests/RandTest.cpp b/src/Tests/RandTest.cpp
@@ -0,0 +1,26 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ RandTest.h - CxxTest for Pseudo-Random Number Generator
+ Copyright (C) 2009-2009 Mark McCurry
+ Author: Mark McCurry
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+
+#include "../Misc/Util.h"
+#include "test-suite.h"
+using namespace zyn;
+
+int main()
+{
+ TS_ASSERT_DELTA(RND, 0.607781, 0.00001);
+ TS_ASSERT_DELTA(RND, 0.591761, 0.00001);
+ TS_ASSERT_DELTA(RND, 0.186133, 0.00001);
+ TS_ASSERT_DELTA(RND, 0.286319, 0.00001);
+ TS_ASSERT_DELTA(RND, 0.511766, 0.00001);
+ return test_summary();
+};
diff --git a/src/Tests/RandTest.h b/src/Tests/RandTest.h
@@ -1,31 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- RandTest.h - CxxTest for Pseudo-Random Number Generator
- Copyright (C) 2009-2009 Mark McCurry
- Author: Mark McCurry
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-
-#include "../Misc/Util.h"
-#include <cstdlib>
-#include <cstdio>
-#include <cxxtest/TestSuite.h>
-using namespace zyn;
-
-class RandTest:public CxxTest::TestSuite
-{
- public:
- void testPRNG(void) {
- //verify RND returns expected pattern when unseeded
- TS_ASSERT_DELTA(RND, 0.607781, 0.00001);
- TS_ASSERT_DELTA(RND, 0.591761, 0.00001);
- TS_ASSERT_DELTA(RND, 0.186133, 0.00001);
- TS_ASSERT_DELTA(RND, 0.286319, 0.00001);
- TS_ASSERT_DELTA(RND, 0.511766, 0.00001);
- }
-};
diff --git a/src/Tests/RtAllocTest.h b/src/Tests/RtAllocTest.cpp
diff --git a/src/Tests/SubNoteTest.cpp b/src/Tests/SubNoteTest.cpp
@@ -0,0 +1,192 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ AdNoteTest.h - CxxTest for Synth/SUBnote
+ Copyright (C) 2009-2011 Mark McCurry
+ Author: Mark McCurry
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+
+//Based Upon AdNoteTest.h
+#include "test-suite.h"
+#include <iostream>
+#include <fstream>
+#include <ctime>
+#include <string>
+#include "../Misc/Master.h"
+#include "../Misc/Allocator.h"
+#include "../Misc/Util.h"
+#include "../Misc/XMLwrapper.h"
+#include "../Synth/SUBnote.h"
+#include "../Params/SUBnoteParameters.h"
+#include "../Params/Presets.h"
+#include "../globals.h"
+#include <rtosc/thread-link.h>
+
+using namespace std;
+using namespace zyn;
+
+SYNTH_T *synth;
+
+class SubNoteTest
+{
+ public:
+
+ SUBnoteParameters *pars;
+ SUBnote *note;
+ Master *master;
+ AbsTime *time;
+ Controller *controller;
+ float test_freq_log2;
+ Alloc memory;
+ rtosc::ThreadLink *tr;
+ WatchManager *w;
+
+
+ float *outR, *outL;
+
+ void setUp() {
+ synth = new SYNTH_T;
+ //First the sensible settings and variables that have to be set:
+ synth->buffersize = 256;
+ time = new AbsTime(*synth);
+
+ outL = new float[synth->buffersize];
+ for(int i = 0; i < synth->buffersize; ++i)
+ *(outL + i) = 0;
+ outR = new float[synth->buffersize];
+ for(int i = 0; i < synth->buffersize; ++i)
+ *(outR + i) = 0;
+
+ tr = new rtosc::ThreadLink(1024,3);
+ w = new WatchManager(tr);
+
+ //prepare the default settings
+ SUBnoteParameters *defaultPreset = new SUBnoteParameters(time);
+ XMLwrapper wrap;
+ wrap.loadXMLfile(string(SOURCE_DIR)
+ + string("/guitar-adnote.xmz"));
+ TS_ASSERT(wrap.enterbranch("MASTER"));
+ TS_ASSERT(wrap.enterbranch("PART", 1));
+ TS_ASSERT(wrap.enterbranch("INSTRUMENT"));
+ TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT"));
+ TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT_ITEM", 0));
+ TS_ASSERT(wrap.enterbranch("SUB_SYNTH_PARAMETERS"));
+ defaultPreset->getfromXML(wrap);
+
+ controller = new Controller(*synth, time);
+
+ //lets go with.... 50! as a nice note
+ test_freq_log2 = log2f(440.0f) + (50.0 - 69.0f) / 12.0f;
+
+ SynthParams pars{memory, *controller, *synth, *time, 120, 0, test_freq_log2, false, prng()};
+ note = new SUBnote(defaultPreset, pars, w);
+ this->pars = defaultPreset;
+ }
+
+ void tearDown() {
+ delete controller;
+ delete note;
+ delete [] outL;
+ delete [] outR;
+ delete time;
+ delete synth;
+ delete pars;
+ }
+
+ void testDefaults() {
+ //Note: if these tests fail it is due to the relationship between
+ //global.h::RND and SUBnote.cpp
+
+ int sampleCount = 0;
+
+//#define WRITE_OUTPUT
+
+#ifdef WRITE_OUTPUT
+ ofstream file("subnoteout", ios::out);
+#endif
+ note->noteout(outL, outR);
+#ifdef WRITE_OUTPUT
+ for(int i = 0; i < synth->buffersize; ++i)
+ file << outL[i] << std::endl;
+
+#endif
+ sampleCount += synth->buffersize;
+
+ TS_ASSERT_DELTA(outL[255], 0.0010f, 0.0001f);
+
+ note->releasekey();
+
+ TS_ASSERT(!tr->hasNext());
+ w->add_watch("noteout/filter");
+
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], 0.0114f, 0.0001f);
+ w->tick();
+
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], -0.0014f, 0.0001f);
+ w->tick();
+
+ TS_ASSERT(tr->hasNext());
+ TS_ASSERT_EQUAL_STR("noteout/filter", tr->read());
+ TS_ASSERT(!tr->hasNext());
+
+ w->add_watch("noteout/amp_int");
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], -0.0031f, 0.0001f);
+ w->tick();
+
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], -0.0013f, 0.0001f);
+ w->tick();
+ TS_ASSERT(tr->hasNext());
+ TS_ASSERT_EQUAL_STR("noteout/amp_int", tr->read());
+ TS_ASSERT(!tr->hasNext());
+
+ while(!note->finished()) {
+ note->noteout(outL, outR);
+#ifdef WRITE_OUTPUT
+ for(int i = 0; i < synth->buffersize; ++i)
+ file << outL[i] << std::endl;
+
+#endif
+ sampleCount += synth->buffersize;
+ }
+#ifdef WRITE_OUTPUT
+ file.close();
+#endif
+
+ TS_ASSERT_EQUAL_INT(sampleCount, 5888);
+ }
+
+#define OUTPUT_PROFILE
+#ifdef OUTPUT_PROFILE
+ void testSpeed() {
+ const int samps = 15000;
+
+ int t_on = clock(); // timer before calling func
+ for(int i = 0; i < samps; ++i)
+ note->noteout(outL, outR);
+ int t_off = clock(); // timer when func returns
+
+ printf("SubNoteTest: %f seconds for %d Samples to be generated.\n",
+ (static_cast<float>(t_off - t_on)) / CLOCKS_PER_SEC, samps);
+ }
+#endif
+};
+
+int main(void)
+{
+ SubNoteTest test;
+ RUN_TEST(testDefaults);
+ return test_summary();
+}
diff --git a/src/Tests/SubNoteTest.h b/src/Tests/SubNoteTest.h
@@ -1,185 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- AdNoteTest.h - CxxTest for Synth/SUBnote
- Copyright (C) 2009-2011 Mark McCurry
- Author: Mark McCurry
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-
-//Based Upon AdNoteTest.h
-#include <cxxtest/TestSuite.h>
-#include <iostream>
-#include <fstream>
-#include <ctime>
-#include <string>
-#include "../Misc/Master.h"
-#include "../Misc/Allocator.h"
-#include "../Misc/Util.h"
-#include "../Misc/XMLwrapper.h"
-#include "../Synth/SUBnote.h"
-#include "../Params/SUBnoteParameters.h"
-#include "../Params/Presets.h"
-#include "../globals.h"
-#include <rtosc/thread-link.h>
-
-using namespace std;
-using namespace zyn;
-
-SYNTH_T *synth;
-
-class SubNoteTest:public CxxTest::TestSuite
-{
- public:
-
- SUBnoteParameters *pars;
- SUBnote *note;
- Master *master;
- AbsTime *time;
- Controller *controller;
- float test_freq_log2;
- Alloc memory;
- rtosc::ThreadLink *tr;
- WatchManager *w;
-
-
- float *outR, *outL;
-
- void setUp() {
- synth = new SYNTH_T;
- //First the sensible settings and variables that have to be set:
- synth->buffersize = 256;
- time = new AbsTime(*synth);
-
- outL = new float[synth->buffersize];
- for(int i = 0; i < synth->buffersize; ++i)
- *(outL + i) = 0;
- outR = new float[synth->buffersize];
- for(int i = 0; i < synth->buffersize; ++i)
- *(outR + i) = 0;
-
- tr = new rtosc::ThreadLink(1024,3);
- w = new WatchManager(tr);
-
- //prepare the default settings
- SUBnoteParameters *defaultPreset = new SUBnoteParameters(time);
- XMLwrapper wrap;
- wrap.loadXMLfile(string(SOURCE_DIR)
- + string("/guitar-adnote.xmz"));
- TS_ASSERT(wrap.enterbranch("MASTER"));
- TS_ASSERT(wrap.enterbranch("PART", 1));
- TS_ASSERT(wrap.enterbranch("INSTRUMENT"));
- TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT"));
- TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT_ITEM", 0));
- TS_ASSERT(wrap.enterbranch("SUB_SYNTH_PARAMETERS"));
- defaultPreset->getfromXML(wrap);
-
- controller = new Controller(*synth, time);
-
- //lets go with.... 50! as a nice note
- test_freq_log2 = log2f(440.0f) + (50.0 - 69.0f) / 12.0f;
-
- SynthParams pars{memory, *controller, *synth, *time, 120, 0, test_freq_log2, false, prng()};
- note = new SUBnote(defaultPreset, pars, w);
- this->pars = defaultPreset;
- }
-
- void tearDown() {
- delete controller;
- delete note;
- delete [] outL;
- delete [] outR;
- delete time;
- delete synth;
- delete pars;
- }
-
- void testDefaults() {
- //Note: if these tests fail it is due to the relationship between
- //global.h::RND and SUBnote.cpp
-
- int sampleCount = 0;
-
-//#define WRITE_OUTPUT
-
-#ifdef WRITE_OUTPUT
- ofstream file("subnoteout", ios::out);
-#endif
- note->noteout(outL, outR);
-#ifdef WRITE_OUTPUT
- for(int i = 0; i < synth->buffersize; ++i)
- file << outL[i] << std::endl;
-
-#endif
- sampleCount += synth->buffersize;
-
- TS_ASSERT_DELTA(outL[255], 0.0010f, 0.0001f);
-
- note->releasekey();
-
- TS_ASSERT(!tr->hasNext());
- w->add_watch("noteout/filter");
-
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], 0.0114f, 0.0001f);
- w->tick();
-
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], -0.0014f, 0.0001f);
- w->tick();
-
- TS_ASSERT(tr->hasNext());
- TS_ASSERT_EQUALS(string("noteout/filter"), tr->read());
- TS_ASSERT(!tr->hasNext());
-
- w->add_watch("noteout/amp_int");
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], -0.0031f, 0.0001f);
- w->tick();
-
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], -0.0013f, 0.0001f);
- w->tick();
- TS_ASSERT(tr->hasNext());
- TS_ASSERT_EQUALS(string("noteout/amp_int"), tr->read());
- TS_ASSERT(!tr->hasNext());
-
- while(!note->finished()) {
- note->noteout(outL, outR);
-#ifdef WRITE_OUTPUT
- for(int i = 0; i < synth->buffersize; ++i)
- file << outL[i] << std::endl;
-
-#endif
- sampleCount += synth->buffersize;
- }
-#ifdef WRITE_OUTPUT
- file.close();
-#endif
-
- TS_ASSERT_EQUALS(sampleCount, 5888);
- }
-
-#define OUTPUT_PROFILE
-#ifdef OUTPUT_PROFILE
- void testSpeed() {
- const int samps = 15000;
-
- int t_on = clock(); // timer before calling func
- for(int i = 0; i < samps; ++i)
- note->noteout(outL, outR);
- int t_off = clock(); // timer when func returns
-
- printf("SubNoteTest: %f seconds for %d Samples to be generated.\n",
- (static_cast<float>(t_off - t_on)) / CLOCKS_PER_SEC, samps);
- }
-#endif
-};
diff --git a/src/Tests/TriggerTest.cpp b/src/Tests/TriggerTest.cpp
@@ -0,0 +1,265 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ AdNoteTest.h - CxxTest for Synth/SUBnote
+ Copyright (C) 2009-2011 Mark McCurry
+ Author: Mark McCurry
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+
+//Based Upon AdNoteTest.h
+#include "test-suite.h"
+#include <iostream>
+#include <fstream>
+#include <ctime>
+#include <string>
+#include "../Misc/Master.h"
+#include "../Misc/Allocator.h"
+#include "../Misc/Util.h"
+#include "../Misc/XMLwrapper.h"
+#include "../Synth/SUBnote.h"
+#include "../Params/SUBnoteParameters.h"
+#include "../Params/Presets.h"
+#include "../globals.h"
+#include <rtosc/thread-link.h>
+#include <rtosc/rtosc.h>
+
+using namespace std;
+using namespace zyn;
+
+SYNTH_T *synth;
+
+class TriggerTest
+{
+ public:
+
+ SUBnoteParameters *pars;
+ SUBnote *note;
+ Master *master;
+ AbsTime *time;
+ Controller *controller;
+ float test_freq_log2;
+ Alloc memory;
+ rtosc::ThreadLink *tr;
+ WatchManager *w;
+
+
+ float *outR, *outL;
+
+ void setUp() {
+ synth = new SYNTH_T;
+ // //First the sensible settings and variables that have to be set:
+ synth->buffersize = 32;
+ synth->alias(false);
+ outL = new float[synth->buffersize];
+ outR = new float[synth->buffersize];
+ for(int i = 0; i < synth->buffersize; ++i) {
+ outL[i] = 0;
+ outR[i] = 0;
+ }
+
+ time = new AbsTime(*synth);
+
+ tr = new rtosc::ThreadLink(1024,3);
+ w = new WatchManager(tr);
+
+ //prepare the default settings
+ SUBnoteParameters *defaultPreset = new SUBnoteParameters(time);
+ sprng(3543);
+
+ controller = new Controller(*synth, time);
+
+ //lets go with.... 50! as a nice note
+ test_freq_log2 = log2f(440.0f) + (50.0 - 69.0f) / 12.0f;
+
+ SynthParams pars{memory, *controller, *synth, *time, 120, 0, test_freq_log2, false, prng()};
+ note = new SUBnote(defaultPreset, pars, w);
+ this->pars = defaultPreset;
+ }
+
+ void tearDown() {
+ delete controller;
+ delete note;
+ delete [] outL;
+ delete [] outR;
+ delete time;
+ delete synth;
+ delete pars;
+ }
+
+ void dump_samples(const char *s) {
+ puts(s);
+ for(int i=0; i<synth->buffersize; ++i)
+ printf(w->prebuffer[0][i]>0?"+":"-");
+ printf("\n");
+ for(int i=0; i<synth->buffersize; ++i)
+ printf(w->prebuffer[1][i]>0?"+":"-");
+ printf("\n");
+ //for(int i=0; i<synth->buffersize; ++i)
+ // printf("%d->%f\n", i, w->prebuffer[0][i]);
+ //for(int i=0; i<synth->buffersize; ++i)
+ // printf("%d->%f\n", i, w->prebuffer[1][i]);
+ }
+
+ void testSine(void) {
+ //Generate a sine table
+ float data[1024] = {};
+ for(int i=0; i<1024; ++i)
+ data[i] = -sin(2*M_PI*(i/1024.0));
+
+ //Preconditions
+ //
+ //- No pending messages
+ //- No active watch points
+ //
+ TS_ASSERT(!tr->hasNext());
+ TS_ASSERT_EQUAL_STR("", w->active_list[0]);
+ TS_ASSERT_EQUAL_INT(0, w->sample_list[0]);
+ TS_ASSERT(!w->trigger_active("data"));
+
+
+ w->add_watch("noteout/filter");
+ for(int i=0; i<1024; ++i) {
+ w->satisfy("noteout/filter", &data[i], 1);
+ w->tick();
+ }
+ const char *msg1 = tr->read();
+ float buf1[128] = {};
+ assert_non_null(msg1, "valid message", __LINE__);
+ TS_ASSERT_EQUAL_INT(127, rtosc_narguments(msg1));
+
+ printf("msg1 = %s\n", msg1);
+ printf("msg1 = <%s>\n", rtosc_argument_string(msg1));
+ printf("nargs = %d\n", rtosc_narguments(msg1));
+ for(int i=0; i<127; ++i)
+ buf1[i] = rtosc_argument(msg1, i).f;
+
+ w->add_watch("noteout/amp_int");
+ for(int i=0; i<1024/97; ++i) {
+ w->satisfy("noteout/amp_int", &data[i*97], 97);
+ w->tick();
+ }
+ const char *msg2 = tr->read();
+ assert_non_null(msg2, "valid message", __LINE__);
+ TS_ASSERT_EQUAL_INT(127, rtosc_narguments(msg2));
+ float buf2[128] = {};
+ printf("nargs = %d\n", rtosc_narguments(msg2));
+ for(int i=0; i<127; ++i)
+ buf2[i] = rtosc_argument(msg2, i).f;
+ for(int i=0; i<127; ++i){
+ TS_ASSERT_EQUAL_FLT(buf1[i], buf2[i]);
+ TS_ASSERT_EQUAL_FLT(buf1[i],data[450+i]);
+ TS_ASSERT_EQUAL_FLT(buf2[i],data[450+i]);
+ }
+ }
+
+ void testCombinedTrigger() {
+ //Generate a note
+ note->noteout(outL, outR);
+ note->releasekey();
+
+ //Preconditions
+ //
+ //- No pending messages
+ //- No active watch points
+ //
+ TS_ASSERT(!tr->hasNext());
+ TS_ASSERT_EQUAL_STR("", w->active_list[0]);
+ TS_ASSERT_EQUAL_STR("", w->active_list[1]);
+ TS_ASSERT_EQUAL_INT(0, w->sample_list[0]);
+ TS_ASSERT_EQUAL_INT(0, w->sample_list[1]);
+ TS_ASSERT(!w->trigger_active("noteout/filter"));
+ TS_ASSERT(!w->trigger_active("noteout/amp_int"));
+
+ //Setup a watchpoint
+ //
+ // - Watchpoints will be added to the active list in the watch
+ // manager
+ // - Watchpoints will not be triggered
+ w->add_watch("noteout/filter");
+ w->add_watch("noteout/amp_int");
+ TS_ASSERT(!w->trigger_active("noteout/filter"));
+ TS_ASSERT(!w->trigger_active("noteout/amp_int"));
+ TS_ASSERT_EQUAL_STR("noteout/filter", w->active_list[0]);
+ TS_ASSERT_EQUAL_STR("noteout/amp_int", w->active_list[1]);
+ TS_ASSERT_EQUAL_INT(0, w->sample_list[0]);
+ TS_ASSERT_EQUAL_INT(0, w->sample_list[1]);
+ dump_samples("Initial pre-buffer");
+
+ //Run the system
+ //noteout1 should trigger on this buffer
+ note->noteout(outL, outR);
+
+ w->tick();
+ dump_samples("Step 1 pre-buffer");
+ TS_ASSERT(!w->trigger_active("noteout/filter")); //not active as prebuffer is not filled
+ TS_ASSERT(!w->trigger_active("noteout/amp_int"));
+ TS_ASSERT(!tr->hasNext());
+ TS_ASSERT(w->sample_list[0] <= 0); // Is 0 as prebuffer not filled
+ TS_ASSERT(w->sample_list[1] <= 0);
+
+
+ //Both should continue to accumulate samples
+ note->noteout(outL, outR);
+ w->tick();
+ dump_samples("Step 2 pre-buffer\n");
+ TS_ASSERT(!w->trigger_active("noteout/filter")); //not active as prebuffer is not filled
+ TS_ASSERT(!w->trigger_active("noteout/amp_int"));
+ TS_ASSERT(!tr->hasNext());
+ TS_ASSERT(w->sample_list[0] <= 0); // Is 0 as prebuffer not filled
+ TS_ASSERT(w->sample_list[1] <= 0);
+
+ //Continue accum samples
+ note->noteout(outL, outR);
+ w->tick();
+ dump_samples("Step 3 pre-buffer\n");
+ TS_ASSERT(!w->trigger_active("noteout/filter"));
+ TS_ASSERT(!w->trigger_active("noteout/amp_int"));
+ TS_ASSERT(!tr->hasNext());
+ TS_ASSERT(w->sample_list[0] <= 0); // Is 0 as prebuffer not filled
+ TS_ASSERT(w->sample_list[1] <= 0);
+
+ //Finish accumulating samples
+ note->noteout(outL, outR);
+ w->tick();
+ dump_samples("Step 4 pre-buffer\n");
+ TS_ASSERT(w->trigger_active("noteout/filter")); // trigger activate and filling post buffer
+ TS_ASSERT(w->trigger_active("noteout/amp_int"));
+ TS_ASSERT(!tr->hasNext()); // post buffer not reach 128
+ TS_ASSERT(w->sample_list[1] <= 128); // prebuffer + postbuffer filled in
+ TS_ASSERT(w->sample_list[0] <= 128);
+ note->noteout(outL, outR);
+ w->tick();
+ note->noteout(outL, outR);
+ w->tick();
+
+#define f32 "ffffffffffffffffffffffffffffffff"
+#define f128 f32 f32 f32 f32
+ //Verify the output to the user interface
+ //if 128 samples are requested, then 128 should be delivered
+ const char *msg1 = tr->read();
+ TS_ASSERT_EQUAL_STR("noteout/filter", msg1);
+ TS_ASSERT_EQUAL_STR(f128, rtosc_argument_string(msg1));
+ TS_ASSERT_EQUAL_INT(128, strlen(rtosc_argument_string(msg1)));
+ note->noteout(outL, outR);
+ w->tick();
+ TS_ASSERT(tr->hasNext());
+ const char *msg2 = tr->read();
+ TS_ASSERT_EQUAL_STR("noteout/amp_int", msg2);
+ TS_ASSERT_EQUAL_INT(128, strlen(rtosc_argument_string(msg2)));
+ TS_ASSERT_EQUAL_STR(f128, rtosc_argument_string(msg2));
+ TS_ASSERT(!tr->hasNext());
+ }
+
+};
+
+int main()
+{
+ TriggerTest test;
+ RUN_TEST(testSine);
+ RUN_TEST(testCombinedTrigger);
+}
diff --git a/src/Tests/TriggerTest.h b/src/Tests/TriggerTest.h
@@ -1,258 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- AdNoteTest.h - CxxTest for Synth/SUBnote
- Copyright (C) 2009-2011 Mark McCurry
- Author: Mark McCurry
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-
-//Based Upon AdNoteTest.h
-#include <cxxtest/TestSuite.h>
-#include <iostream>
-#include <fstream>
-#include <ctime>
-#include <string>
-#include "../Misc/Master.h"
-#include "../Misc/Allocator.h"
-#include "../Misc/Util.h"
-#include "../Misc/XMLwrapper.h"
-#include "../Synth/SUBnote.h"
-#include "../Params/SUBnoteParameters.h"
-#include "../Params/Presets.h"
-#include "../globals.h"
-#include <rtosc/thread-link.h>
-#include <rtosc/rtosc.h>
-
-using namespace std;
-using namespace zyn;
-
-SYNTH_T *synth;
-
-class TriggerTest:public CxxTest::TestSuite
-{
- public:
-
- SUBnoteParameters *pars;
- SUBnote *note;
- Master *master;
- AbsTime *time;
- Controller *controller;
- float test_freq_log2;
- Alloc memory;
- rtosc::ThreadLink *tr;
- WatchManager *w;
-
-
- float *outR, *outL;
-
- void setUp() {
- synth = new SYNTH_T;
- // //First the sensible settings and variables that have to be set:
- synth->buffersize = 32;
- synth->alias(false);
- outL = new float[synth->buffersize];
- outR = new float[synth->buffersize];
- for(int i = 0; i < synth->buffersize; ++i) {
- outL[i] = 0;
- outR[i] = 0;
- }
-
- time = new AbsTime(*synth);
-
- tr = new rtosc::ThreadLink(1024,3);
- w = new WatchManager(tr);
-
- //prepare the default settings
- SUBnoteParameters *defaultPreset = new SUBnoteParameters(time);
- sprng(3543);
-
- controller = new Controller(*synth, time);
-
- //lets go with.... 50! as a nice note
- test_freq_log2 = log2f(440.0f) + (50.0 - 69.0f) / 12.0f;
-
- SynthParams pars{memory, *controller, *synth, *time, 120, 0, test_freq_log2, false, prng()};
- note = new SUBnote(defaultPreset, pars, w);
- this->pars = defaultPreset;
- }
-
- void tearDown() {
- delete controller;
- delete note;
- delete [] outL;
- delete [] outR;
- delete time;
- delete synth;
- delete pars;
- }
-
- void dump_samples(const char *s) {
- puts(s);
- for(int i=0; i<synth->buffersize; ++i)
- printf(w->prebuffer[0][i]>0?"+":"-");
- printf("\n");
- for(int i=0; i<synth->buffersize; ++i)
- printf(w->prebuffer[1][i]>0?"+":"-");
- printf("\n");
- //for(int i=0; i<synth->buffersize; ++i)
- // printf("%d->%f\n", i, w->prebuffer[0][i]);
- //for(int i=0; i<synth->buffersize; ++i)
- // printf("%d->%f\n", i, w->prebuffer[1][i]);
- }
-
- void testSine(void) {
- //Generate a sine table
- float data[1024] = {};
- for(int i=0; i<1024; ++i)
- data[i] = -sin(2*M_PI*(i/1024.0));
-
- //Preconditions
- //
- //- No pending messages
- //- No active watch points
- //
- TS_ASSERT(!tr->hasNext());
- TS_ASSERT_EQUALS(string(""), w->active_list[0]);
- TS_ASSERT_EQUALS(0, w->sample_list[0]);
- TS_ASSERT(!w->trigger_active("data"));
-
-
- w->add_watch("noteout/filter");
- for(int i=0; i<1024; ++i) {
- w->satisfy("noteout/filter", &data[i], 1);
- w->tick();
- }
- const char *msg1 = tr->read();
- float buf1[128] = {};
- TS_ASSERT(msg1);
- TS_ASSERT_EQUALS(127, rtosc_narguments(msg1));
-
- printf("msg1 = %s\n", msg1);
- printf("msg1 = <%s>\n", rtosc_argument_string(msg1));
- printf("nargs = %d\n", rtosc_narguments(msg1));
- for(int i=0; i<127; ++i)
- buf1[i] = rtosc_argument(msg1, i).f;
-
- w->add_watch("noteout/amp_int");
- for(int i=0; i<1024/97; ++i) {
- w->satisfy("noteout/amp_int", &data[i*97], 97);
- w->tick();
- }
- const char *msg2 = tr->read();
- TS_ASSERT(msg2);
- TS_ASSERT_EQUALS(127, rtosc_narguments(msg2));
- float buf2[128] = {};
- printf("nargs = %d\n", rtosc_narguments(msg2));
- for(int i=0; i<127; ++i)
- buf2[i] = rtosc_argument(msg2, i).f;
- for(int i=0; i<127; ++i){
- TS_ASSERT_EQUALS(buf1[i], buf2[i]);
- TS_ASSERT_EQUALS(buf1[i],data[450+i]);
- TS_ASSERT_EQUALS(buf2[i],data[450+i]);
- }
- }
-
- void testCombinedTrigger() {
- //Generate a note
- note->noteout(outL, outR);
- note->releasekey();
-
- //Preconditions
- //
- //- No pending messages
- //- No active watch points
- //
- TS_ASSERT(!tr->hasNext());
- TS_ASSERT_EQUALS(string(""), w->active_list[0]);
- TS_ASSERT_EQUALS(string(""), w->active_list[1]);
- TS_ASSERT_EQUALS(0, w->sample_list[0]);
- TS_ASSERT_EQUALS(0, w->sample_list[1]);
- TS_ASSERT(!w->trigger_active("noteout/filter"));
- TS_ASSERT(!w->trigger_active("noteout/amp_int"));
-
- //Setup a watchpoint
- //
- // - Watchpoints will be added to the active list in the watch
- // manager
- // - Watchpoints will not be triggered
- w->add_watch("noteout/filter");
- w->add_watch("noteout/amp_int");
- TS_ASSERT(!w->trigger_active("noteout/filter"));
- TS_ASSERT(!w->trigger_active("noteout/amp_int"));
- TS_ASSERT_EQUALS(string("noteout/filter"), w->active_list[0]);
- TS_ASSERT_EQUALS(string("noteout/amp_int"), w->active_list[1]);
- TS_ASSERT_EQUALS(0, w->sample_list[0]);
- TS_ASSERT_EQUALS(0, w->sample_list[1]);
- dump_samples("Initial pre-buffer");
-
- //Run the system
- //noteout1 should trigger on this buffer
- note->noteout(outL, outR);
-
- w->tick();
- dump_samples("Step 1 pre-buffer");
- TS_ASSERT(!w->trigger_active("noteout/filter")); //not active as prebuffer is not filled
- TS_ASSERT(!w->trigger_active("noteout/amp_int"));
- TS_ASSERT(!tr->hasNext());
- TS_ASSERT_LESS_THAN_EQUALS(w->sample_list[0], 0); // Is 0 as prebuffer not filled
- TS_ASSERT_LESS_THAN_EQUALS(w->sample_list[1], 0);
-
-
- //Both should continue to accumulate samples
- note->noteout(outL, outR);
- w->tick();
- dump_samples("Step 2 pre-buffer\n");
- TS_ASSERT(!w->trigger_active("noteout/filter")); //not active as prebuffer is not filled
- TS_ASSERT(!w->trigger_active("noteout/amp_int"));
- TS_ASSERT(!tr->hasNext());
- TS_ASSERT_LESS_THAN_EQUALS(w->sample_list[0], 0); // Is 0 as prebuffer not filled
- TS_ASSERT_LESS_THAN_EQUALS(w->sample_list[1], 0);
-
- //Continue accum samples
- note->noteout(outL, outR);
- w->tick();
- dump_samples("Step 3 pre-buffer\n");
- TS_ASSERT(!w->trigger_active("noteout/filter"));
- TS_ASSERT(!w->trigger_active("noteout/amp_int"));
- TS_ASSERT(!tr->hasNext());
- TS_ASSERT_LESS_THAN_EQUALS(w->sample_list[0], 0); // Is 0 as prebuffer not filled
- TS_ASSERT_LESS_THAN_EQUALS(w->sample_list[1], 0);
-
- //Finish accumulating samples
- note->noteout(outL, outR);
- w->tick();
- dump_samples("Step 4 pre-buffer\n");
- TS_ASSERT(w->trigger_active("noteout/filter")); // trigger activate and filling post buffer
- TS_ASSERT(w->trigger_active("noteout/amp_int"));
- TS_ASSERT(!tr->hasNext()); // post buffer not reach 128
- TS_ASSERT_LESS_THAN_EQUALS(w->sample_list[1], 128); // prebuffer + postbuffer filled in
- TS_ASSERT_LESS_THAN_EQUALS(w->sample_list[0], 128);
- note->noteout(outL, outR);
- w->tick();
- note->noteout(outL, outR);
- w->tick();
-
-#define f32 "ffffffffffffffffffffffffffffffff"
-#define f128 f32 f32 f32 f32
- //Verify the output to the user interface
- //if 128 samples are requested, then 128 should be delivered
- const char *msg1 = tr->read();
- TS_ASSERT_EQUALS(string("noteout/filter"), msg1);
- TS_ASSERT_EQUALS(string(f128), rtosc_argument_string(msg1));
- TS_ASSERT_EQUALS(128, strlen(rtosc_argument_string(msg1)));
- note->noteout(outL, outR);
- w->tick();
- TS_ASSERT(tr->hasNext());
- const char *msg2 = tr->read();
- TS_ASSERT_EQUALS(string("noteout/amp_int"), msg2);
- TS_ASSERT_EQUALS(128, strlen(rtosc_argument_string(msg2)));
- TS_ASSERT_EQUALS(string(f128), rtosc_argument_string(msg2));
- TS_ASSERT(!tr->hasNext());
- }
-
-};
diff --git a/src/Tests/UnisonTest.cpp b/src/Tests/UnisonTest.cpp
@@ -0,0 +1,187 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ AdNoteTest.h - CxxTest for Synth/ADnote
+ Copyright (C) 2009-2011 Mark McCurry
+ Copyright (C) 2009 Harald Hvaal
+ Authors: Mark McCurry, Harald Hvaal
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+
+
+#include "test-suite.h"
+#include <iostream>
+#include <fstream>
+#include <ctime>
+#include <string>
+#include "../Misc/Util.h"
+#include "../Misc/Allocator.h"
+#include "../Synth/ADnote.h"
+#include "../Synth/OscilGen.h"
+#include "../Params/Presets.h"
+#include "../Params/FilterParams.h"
+#include "../DSP/FFTwrapper.h"
+#include "../globals.h"
+using namespace std;
+using namespace zyn;
+
+SYNTH_T *synth;
+
+#define BUF 256
+class UnisonTest
+{
+ public:
+
+ ADnote *note;
+ FFTwrapper *fft;
+ Controller *controller;
+ float test_freq_log2;
+ ADnoteParameters *params;
+ AbsTime *time;
+ Alloc memory;
+
+
+ float outR[BUF], outL[BUF];
+
+ void setUp() {
+ //First the sensible settings and variables that have to be set:
+ synth = new SYNTH_T;
+ synth->buffersize = BUF;
+ synth->alias();
+ time = new AbsTime(*synth);
+
+ memset(outL,0,sizeof(outL));
+ memset(outR,0,sizeof(outR));
+
+ fft = new FFTwrapper(BUF);
+ //prepare the default settings
+ params = new ADnoteParameters(*synth, fft, time);
+
+ //sawtooth to make things a bit more interesting
+ params->VoicePar[0].OscilGn->Pcurrentbasefunc = 3;
+
+ params->GlobalPar.PFilterVelocityScale = 64;
+ params->GlobalPar.GlobalFilter->basefreq = 5076.203125;
+
+ controller = new Controller(*synth, time);
+
+ //lets go with.... 50! as a nice note
+ test_freq_log2 = log2f(440.0f) + (50.0 - 69.0f) / 12.0f;
+ }
+
+ void tearDown() {
+ delete note;
+ delete controller;
+ delete fft;
+ FFT_cleanup();
+ delete time;
+ delete synth;
+ delete params;
+ }
+
+ void run_test(int a, int b, int c, int d, int e, int f, float values[4])
+ {
+ sprng(0);
+
+ const int ADnote_unison_sizes[] =
+ {1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 25, 30, 40, 50, 0};
+ params->VoicePar[0].Unison_size = ADnote_unison_sizes[a];
+ params->VoicePar[0].Unison_frequency_spread = b;
+ params->VoicePar[0].Unison_stereo_spread = c;
+ params->VoicePar[0].Unison_vibratto = d;
+ params->VoicePar[0].Unison_vibratto_speed = e;
+ params->VoicePar[0].Unison_invert_phase = f;
+
+ SynthParams pars{memory, *controller, *synth, *time, 120, 0, test_freq_log2, false, prng()};
+ note = new ADnote(params, pars);
+ note->noteout(outL, outR);
+ TS_ASSERT_DELTA(outL[80], values[0], 1.9e-5);
+ printf("{%f,", outL[80]);
+ note->noteout(outL, outR);
+ TS_ASSERT_DELTA(outR[90], values[1], 1.9e-5);
+ printf("%f,", outR[90]);
+ note->noteout(outL, outR);
+ TS_ASSERT_DELTA(outL[20], values[2], 1.9e-5);
+ printf("%f,", outL[20]);
+ note->noteout(outL, outR);
+ TS_ASSERT_DELTA(outR[200], values[3], 1.9e-5);
+ printf("%f},\n", outR[200]);
+ }
+
+ void testUnison() {
+ sprng(0xbeef);
+
+ float data[][4] = {
+ {0.125972,0.029887,0.000000,0.138013},
+ {-0.095414,-0.083965,-0.000000,0.009048},
+ {-0.077587,-0.001760,-0.021463,-0.013995},
+ {0.041240,-0.008561,-0.000000,-0.099298},
+ {-0.098969,-0.048030,-0.000052,-0.087053},
+ {0.104913,-0.081452,-0.017700,0.000978},
+ {0.041270,0.003788,0.006064,0.002436},
+ {-0.030791,-0.036072,-0.007964,-0.015141},
+ {0.009218,0.015333,-0.007500,0.083076},
+ {0.058909,0.064450,-0.002517,0.041595},
+ {-0.007731,-0.009040,-0.068033,-0.016573},
+ {-0.047286,-0.002355,-0.049196,0.016222},
+ {0.014014,-0.002635,0.006542,0.050710},
+ {-0.054877,-0.027135,0.040211,0.031927},
+ {-0.048367,0.022010,0.018224,0.032846},
+ };
+
+ int freq_spread[15];
+ int stereo_spread[15];
+ int vibrato[15];
+ int vibrato_speed[15];
+ int inv_phase[15];
+ for(int i=0; i<15; ++i)
+ {
+ freq_spread[i] = prng()%0x7f;
+ stereo_spread[i] = prng()%0x7f;
+ vibrato[i] = prng()%0x7f;
+ vibrato_speed[i] = prng()%0x7f;
+ inv_phase[i] = prng()%5;
+ }
+
+ printf("\n");
+ for(int i=0; i<15; ++i)
+ {
+ run_test(i, freq_spread[i], stereo_spread[i],
+ vibrato[i], vibrato_speed[i], inv_phase[i], data[i]);
+ }
+#if 0
+ int sampleCount = 0;
+
+ sampleCount += synth->buffersize;
+
+ TS_ASSERT_DELTA(outL[255], 0.254609f, 0.0001f);
+
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], -0.102197f, 0.0001f);
+
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], -0.111422f, 0.0001f);
+
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], -0.021375f, 0.0001f);
+
+ note->noteout(outL, outR);
+ sampleCount += synth->buffersize;
+ TS_ASSERT_DELTA(outL[255], 0.149882f, 0.0001f);
+#endif
+ }
+};
+
+int main()
+{
+ UnisonTest test;
+ RUN_TEST(testUnison);
+ return test_summary();
+}
diff --git a/src/Tests/UnisonTest.h b/src/Tests/UnisonTest.h
@@ -1,180 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- AdNoteTest.h - CxxTest for Synth/ADnote
- Copyright (C) 2009-2011 Mark McCurry
- Copyright (C) 2009 Harald Hvaal
- Authors: Mark McCurry, Harald Hvaal
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-
-
-#include <cxxtest/TestSuite.h>
-#include <iostream>
-#include <fstream>
-#include <ctime>
-#include <string>
-#include "../Misc/Util.h"
-#include "../Misc/Allocator.h"
-#include "../Synth/ADnote.h"
-#include "../Synth/OscilGen.h"
-#include "../Params/Presets.h"
-#include "../Params/FilterParams.h"
-#include "../DSP/FFTwrapper.h"
-#include "../globals.h"
-using namespace std;
-using namespace zyn;
-
-SYNTH_T *synth;
-
-#define BUF 256
-class AdNoteTest:public CxxTest::TestSuite
-{
- public:
-
- ADnote *note;
- FFTwrapper *fft;
- Controller *controller;
- float test_freq_log2;
- ADnoteParameters *params;
- AbsTime *time;
- Alloc memory;
-
-
- float outR[BUF], outL[BUF];
-
- void setUp() {
- //First the sensible settings and variables that have to be set:
- synth = new SYNTH_T;
- synth->buffersize = BUF;
- synth->alias();
- time = new AbsTime(*synth);
-
- memset(outL,0,sizeof(outL));
- memset(outR,0,sizeof(outR));
-
- fft = new FFTwrapper(BUF);
- //prepare the default settings
- params = new ADnoteParameters(*synth, fft, time);
-
- //sawtooth to make things a bit more interesting
- params->VoicePar[0].OscilGn->Pcurrentbasefunc = 3;
-
- params->GlobalPar.PFilterVelocityScale = 64;
- params->GlobalPar.GlobalFilter->basefreq = 5076.203125;
-
- controller = new Controller(*synth, time);
-
- //lets go with.... 50! as a nice note
- test_freq_log2 = log2f(440.0f) + (50.0 - 69.0f) / 12.0f;
- }
-
- void tearDown() {
- delete note;
- delete controller;
- delete fft;
- FFT_cleanup();
- delete time;
- delete synth;
- delete params;
- }
-
- void run_test(int a, int b, int c, int d, int e, int f, float values[4])
- {
- sprng(0);
-
- const int ADnote_unison_sizes[] =
- {1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 25, 30, 40, 50, 0};
- params->VoicePar[0].Unison_size = ADnote_unison_sizes[a];
- params->VoicePar[0].Unison_frequency_spread = b;
- params->VoicePar[0].Unison_stereo_spread = c;
- params->VoicePar[0].Unison_vibratto = d;
- params->VoicePar[0].Unison_vibratto_speed = e;
- params->VoicePar[0].Unison_invert_phase = f;
-
- SynthParams pars{memory, *controller, *synth, *time, 120, 0, test_freq_log2, false, prng()};
- note = new ADnote(params, pars);
- note->noteout(outL, outR);
- TS_ASSERT_DELTA(outL[80], values[0], 1.9e-5);
- printf("{%f,", outL[80]);
- note->noteout(outL, outR);
- TS_ASSERT_DELTA(outR[90], values[1], 1.9e-5);
- printf("%f,", outR[90]);
- note->noteout(outL, outR);
- TS_ASSERT_DELTA(outL[20], values[2], 1.9e-5);
- printf("%f,", outL[20]);
- note->noteout(outL, outR);
- TS_ASSERT_DELTA(outR[200], values[3], 1.9e-5);
- printf("%f},\n", outR[200]);
- }
-
- void testUnison() {
- sprng(0xbeef);
-
- float data[][4] = {
- {0.125972,0.029887,0.000000,0.138013},
- {-0.095414,-0.083965,-0.000000,0.009048},
- {-0.077587,-0.001760,-0.021463,-0.013995},
- {0.041240,-0.008561,-0.000000,-0.099298},
- {-0.098969,-0.048030,-0.000052,-0.087053},
- {0.104913,-0.081452,-0.017700,0.000978},
- {0.041270,0.003788,0.006064,0.002436},
- {-0.030791,-0.036072,-0.007964,-0.015141},
- {0.009218,0.015333,-0.007500,0.083076},
- {0.058909,0.064450,-0.002517,0.041595},
- {-0.007731,-0.009040,-0.068033,-0.016573},
- {-0.047286,-0.002355,-0.049196,0.016222},
- {0.014014,-0.002635,0.006542,0.050710},
- {-0.054877,-0.027135,0.040211,0.031927},
- {-0.048367,0.022010,0.018224,0.032846},
- };
-
- int freq_spread[15];
- int stereo_spread[15];
- int vibrato[15];
- int vibrato_speed[15];
- int inv_phase[15];
- for(int i=0; i<15; ++i)
- {
- freq_spread[i] = prng()%0x7f;
- stereo_spread[i] = prng()%0x7f;
- vibrato[i] = prng()%0x7f;
- vibrato_speed[i] = prng()%0x7f;
- inv_phase[i] = prng()%5;
- }
-
- printf("\n");
- for(int i=0; i<15; ++i)
- {
- run_test(i, freq_spread[i], stereo_spread[i],
- vibrato[i], vibrato_speed[i], inv_phase[i], data[i]);
- }
-#if 0
- int sampleCount = 0;
-
- sampleCount += synth->buffersize;
-
- TS_ASSERT_DELTA(outL[255], 0.254609f, 0.0001f);
-
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], -0.102197f, 0.0001f);
-
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], -0.111422f, 0.0001f);
-
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], -0.021375f, 0.0001f);
-
- note->noteout(outL, outR);
- sampleCount += synth->buffersize;
- TS_ASSERT_DELTA(outL[255], 0.149882f, 0.0001f);
-#endif
- }
-};
diff --git a/src/Tests/WatchTest.cpp b/src/Tests/WatchTest.cpp
@@ -0,0 +1,91 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ PluginTest.h - CxxTest for realtime watch points
+ Copyright (C) 2015-2015 Mark McCurry
+ Authors: Mark McCurry
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License
+ as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License (version 2 or later) for more details.
+
+ You should have received a copy of the GNU General Public License (version 2)
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+#include "test-suite.h"
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <thread>
+#include <rtosc/thread-link.h>
+#include "../Misc/Time.h"
+#include "../Params/LFOParams.h"
+#include "../Synth/LFO.h"
+#include "../Synth/SynthNote.h"
+#include <unistd.h>
+using namespace std;
+using namespace zyn;
+
+char *instance_name=(char*)"";
+
+class WatchTest
+{
+ public:
+ rtosc::ThreadLink *tr;
+ SYNTH_T *s;
+ AbsTime *at;
+ WatchManager *w;
+ LFOParams *par;
+ LFO *l;
+ void setUp() {
+ tr = new rtosc::ThreadLink(1024,3);
+ s = new SYNTH_T;
+ at = new AbsTime(*s);
+ w = new WatchManager(tr);
+ par = new LFOParams;
+ l = new LFO(*par, 440.0, *at, w);
+
+ }
+
+ void tearDown() {
+ delete at;
+ delete s;
+ delete tr;
+ }
+
+ void testNoWatch(void)
+ {
+ TS_ASSERT(!tr->hasNext());
+ l->lfoout();
+ TS_ASSERT(!tr->hasNext());
+ }
+
+ void testPhaseWatch(void)
+ {
+ TS_ASSERT(!tr->hasNext());
+ w->add_watch("out");
+ l->lfoout();
+ w->tick();
+ TS_ASSERT(tr->hasNext());
+ TS_ASSERT_EQUAL_STR("out", tr->read());
+ TS_ASSERT(!tr->hasNext());
+ }
+
+};
+
+int main()
+{
+ WatchTest test;
+ RUN_TEST(testNoWatch);
+ RUN_TEST(testPhaseWatch);
+ return test_summary();
+}
diff --git a/src/Tests/WatchTest.h b/src/Tests/WatchTest.h
@@ -1,83 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- PluginTest.h - CxxTest for realtime watch points
- Copyright (C) 2015-2015 Mark McCurry
- Authors: Mark McCurry
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License (version 2 or later) for more details.
-
- You should have received a copy of the GNU General Public License (version 2)
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-*/
-#include <cxxtest/TestSuite.h>
-#include <cmath>
-#include <cstdlib>
-#include <iostream>
-#include <fstream>
-#include <string>
-#include <thread>
-#include <rtosc/thread-link.h>
-#include "../Misc/Time.h"
-#include "../Params/LFOParams.h"
-#include "../Synth/LFO.h"
-#include "../Synth/SynthNote.h"
-#include <unistd.h>
-using namespace std;
-using namespace zyn;
-
-char *instance_name=(char*)"";
-
-class WatchTest:public CxxTest::TestSuite
-{
- public:
- rtosc::ThreadLink *tr;
- SYNTH_T *s;
- AbsTime *at;
- WatchManager *w;
- LFOParams *par;
- LFO *l;
- void setUp() {
- tr = new rtosc::ThreadLink(1024,3);
- s = new SYNTH_T;
- at = new AbsTime(*s);
- w = new WatchManager(tr);
- par = new LFOParams;
- l = new LFO(*par, 440.0, *at, w);
-
- }
-
- void tearDown() {
- delete at;
- delete s;
- delete tr;
- }
-
- void testNoWatch(void)
- {
- TS_ASSERT(!tr->hasNext());
- l->lfoout();
- TS_ASSERT(!tr->hasNext());
- }
-
- void testPhaseWatch(void)
- {
- TS_ASSERT(!tr->hasNext());
- w->add_watch("out");
- l->lfoout();
- w->tick();
- TS_ASSERT(tr->hasNext());
- TS_ASSERT_EQUALS(string("out"), tr->read());
- TS_ASSERT(!tr->hasNext());
- }
-
-};
diff --git a/src/Tests/XMLwrapperTest.cpp b/src/Tests/XMLwrapperTest.cpp
@@ -0,0 +1,73 @@
+/*
+ ZynAddSubFX - a software synthesizer
+
+ XMLwrapperTest.h - CxxTest for Misc/XMLwrapper
+ Copyright (C) 2009-2009 Mark McCurry
+ Author: Mark McCurry
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+*/
+#include "test-suite.h"
+#include "../Misc/XMLwrapper.h"
+#include <string>
+#include "../globals.h"
+using namespace std;
+using namespace zyn;
+
+SYNTH_T *synth;
+
+class XMLwrapperTest
+{
+ public:
+ void setUp() {
+ xmla = new XMLwrapper;
+ xmlb = new XMLwrapper;
+ }
+
+
+ void testAddPar() {
+ xmla->addpar("my Pa*_ramet@er", 75);
+ TS_ASSERT_EQUAL_INT(xmla->getpar("my Pa*_ramet@er", 0, -200, 200), 75);
+ }
+
+ //here to verify that no leaks occur
+ void testLoad() {
+ string location = string(SOURCE_DIR) + string(
+ "/Tests/guitar-adnote.xmz");
+ xmla->loadXMLfile(location);
+ }
+
+ void testAnotherLoad()
+ {
+ string dat =
+ "\n<?xml version=\"1.0f\" encoding=\"UTF-8\"?>\n\
+<!DOCTYPE ZynAddSubFX-data>\n\
+<ZynAddSubFX-data version-major=\"2\" version-minor=\"4\"\n\
+version-revision=\"1\" ZynAddSubFX-author=\"Nasca Octavian Paul\">\n\
+</ZynAddSubFX-data>\n";
+ xmlb->putXMLdata(dat.c_str());
+ }
+
+ void tearDown() {
+ delete xmla;
+ delete xmlb;
+ }
+
+
+ private:
+ XMLwrapper *xmla;
+ XMLwrapper *xmlb;
+};
+
+int main()
+{
+ XMLwrapperTest test;
+ RUN_TEST(testAddPar);
+ RUN_TEST(testLoad);
+ RUN_TEST(testAnotherLoad);
+ return test_summary();
+}
+
diff --git a/src/Tests/XMLwrapperTest.h b/src/Tests/XMLwrapperTest.h
@@ -1,63 +0,0 @@
-/*
- ZynAddSubFX - a software synthesizer
-
- XMLwrapperTest.h - CxxTest for Misc/XMLwrapper
- Copyright (C) 2009-2009 Mark McCurry
- Author: Mark McCurry
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-*/
-#include <cxxtest/TestSuite.h>
-#include "../Misc/XMLwrapper.h"
-#include <string>
-#include "../globals.h"
-using namespace std;
-using namespace zyn;
-
-SYNTH_T *synth;
-
-class XMLwrapperTest:public CxxTest::TestSuite
-{
- public:
- void setUp() {
- xmla = new XMLwrapper;
- xmlb = new XMLwrapper;
- }
-
-
- void testAddPar() {
- xmla->addpar("my Pa*_ramet@er", 75);
- TS_ASSERT_EQUALS(xmla->getpar("my Pa*_ramet@er", 0, -200, 200), 75);
- }
-
- //here to verify that no leaks occur
- void testLoad() {
- string location = string(SOURCE_DIR) + string(
- "/Tests/guitar-adnote.xmz");
- xmla->loadXMLfile(location);
- }
-
- void testAnotherLoad()
- {
- string dat =
- "\n<?xml version=\"1.0f\" encoding=\"UTF-8\"?>\n\
-<!DOCTYPE ZynAddSubFX-data>\n\
-<ZynAddSubFX-data version-major=\"2\" version-minor=\"4\"\n\
-version-revision=\"1\" ZynAddSubFX-author=\"Nasca Octavian Paul\">\n\
-</ZynAddSubFX-data>\n";
- xmlb->putXMLdata(dat.c_str());
- }
-
- void tearDown() {
- delete xmla;
- delete xmlb;
- }
-
-
- private:
- XMLwrapper *xmla;
- XMLwrapper *xmlb;
-};
diff --git a/src/Tests/common.h b/src/Tests/common.h
@@ -0,0 +1,250 @@
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+int tap_quiet = 0;
+int global_err = 0;
+int test_counter = 0;
+//expect a
+//actual b
+int assert_int_eq(int a, int b, const char *testcase, int line)
+{
+ test_counter++;
+ int err = a!=b;
+ if(err) {
+ printf("not ok %d - %s...\n", test_counter, testcase);
+ printf("# Expected %d, but observed %d instead (line %d)\n", a, b, line);
+ global_err++;
+ } else if(!tap_quiet)
+ printf("ok %d - %s...\n", test_counter, testcase);
+ return err;
+}
+
+int assert_char_eq(char a, char b, const char *testcase, int line)
+{
+ test_counter++;
+ int err = a!=b;
+ if(err) {
+ printf("not ok %d - %s...\n", test_counter, testcase);
+ printf("# Expected %c, but observed %c instead (line %d)\n", a, b, line);
+ global_err++;
+ } else if(!tap_quiet)
+ printf("ok %d - %s...\n", test_counter, testcase);
+ return err;
+}
+
+int assert_ptr_eq(const void* a, const void* b, const char *testcase, int line)
+{
+ test_counter++;
+ int err = a!=b;
+ if(err) {
+ printf("not ok %d - %s...\n", test_counter, testcase);
+ printf("# Expected %p, but observed %p instead (line %d)\n", a, b, line);
+ global_err++;
+ } else if(!tap_quiet)
+ printf("ok %d - %s...\n", test_counter, testcase);
+ return err;
+}
+
+int assert_true(int a, const char *testcase, int line)
+{
+ test_counter++;
+ int err = !a;
+ if(err) {
+ printf("not ok %d - %s...\n", test_counter, testcase);
+ printf("# Failure on line %d\n", line);
+ global_err++;
+ } else if(!tap_quiet)
+ printf("ok %d - %s...\n", test_counter, testcase);
+ return err;
+}
+
+int assert_false(int a, const char *testcase, int line)
+{
+ return assert_true(!a, testcase, line);
+}
+
+
+int assert_str_eq(const char *a, const char *b, const char *testcase, int line)
+{
+ test_counter++;
+ int err = strcmp(a,b);
+ if(err) {
+ printf("not ok %d - %s...\n", test_counter, testcase);
+ printf("# Expected '%s', but observed '%s' instead (line %d)\n", a, b, line);
+ global_err++;
+ } else if(!tap_quiet)
+ printf("ok %d - %s...\n", test_counter, testcase);
+ return err;
+}
+
+int assert_null(const void *v, const char *testcase, int line)
+{
+ test_counter++;
+ int err = !!v;
+ if(err) {
+ printf("not ok %d - %s...\n", test_counter, testcase);
+ printf("# Expected NULL value, but observed Non-NULL instead (line %d)\n", line);
+ global_err++;
+ } else if(!tap_quiet)
+ printf("ok %d - %s...\n", test_counter, testcase);
+ return err;
+}
+
+int assert_non_null(const void *v, const char *testcase, int line)
+{
+ test_counter++;
+ int err = !v;
+ if(err) {
+ printf("not ok %d - %s...\n", test_counter, testcase);
+ printf("# Expected Non-NULL value, but observed NULL instead (line %d)\n", line);
+ global_err++;
+ } else if(!tap_quiet)
+ printf("ok %d - %s...\n", test_counter, testcase);
+ return err;
+}
+
+int assert_f32_eq(float a, float b,const char *testcase, int line)
+{
+ test_counter++;
+ int err = a!=b;
+ if(err) {
+ printf("not ok %d - %s...\n", test_counter, testcase);
+ printf("# Expected %f, but observed %f instead (line %d)\n", a, b, line);
+ global_err++;
+ } else if(!tap_quiet)
+ printf("ok %d - %s...\n", test_counter, testcase);
+ return err;
+}
+
+int assert_f32_sim(float a, float b, float t, const char *testcase, int line)
+{
+ test_counter++;
+ float tmp = (a-b);
+ tmp = tmp<0?-tmp:tmp;
+ int err = tmp > t;
+ if(err) {
+ printf("not ok %d - %s...\n", test_counter, testcase);
+ printf("# Expected %f+-%f, but observed %f instead (line %d)\n", a, t, b, line);
+ global_err++;
+ } else if(!tap_quiet)
+ printf("ok %d - %s...\n", test_counter, testcase);
+ return err;
+}
+
+//produce a xxd style hexdump with sections highlighted using escape sequences
+//
+//e.g.
+//0000000: 2369 6e63 6c75 6465 203c 7374 6469 6f2e #include <stdio.
+//0000010: 683e 0a23 696e 636c 7564 6520 3c73 7472 h>.#include <str
+//0000020: 696e 672e 683e 0a0a 696e 7420 676c 6f62 ing.h>..int glob
+//0000030: 616c 5f65 7272 203d 2030 3b0a 696e 7420 al_err = 0;.int
+//0000040: 7465 7374 5f63 6f75 6e74 6572 203d 2030 test_counter = 0
+//0000050: 3b0a 2f2f 6578 7065 6374 2061 0a2f 2f61 ;.//expect a.//a
+//
+void hexdump(const char *data, const char *mask, size_t len)
+{
+ const char *bold_gray = "\x1b[30;1m";
+ const char *reset = "\x1b[0m";
+ int offset = 0;
+ while(1)
+ {
+ //print line
+ printf("#%07x: ", offset);
+
+ int char_covered = 0;
+
+ //print hex groups (8)
+ for(int i=0; i<8; ++i) {
+
+ //print doublet
+ for(int j=0; j<2; ++j) {
+ int loffset = offset + 2*i + j;
+ if(loffset >= (int)len)
+ goto escape;
+
+ //print hex
+ {
+ //start highlight
+ if(mask && mask[loffset]){printf("%s", bold_gray);}
+
+ //print chars
+ printf("%02x", 0xff&data[loffset]);
+
+ //end highlight
+ if(mask && mask[loffset]){printf("%s", reset);}
+ char_covered += 2;
+ }
+ }
+ printf(" ");
+ char_covered += 1;
+ }
+escape:
+
+ //print filler if needed
+ for(int i=char_covered; i<41; ++i)
+ printf(" ");
+
+ //print ascii (16)
+ for(int i=0; i<16; ++i) {
+ if(isprint(data[offset+i]))
+ printf("%c", data[offset+i]);
+ else
+ printf(".");
+ }
+ printf("\n");
+ offset += 16;
+ if(offset >= (int)len)
+ return;
+ }
+}
+
+
+int assert_hex_eq(const char *a, const char *b, size_t size_a, size_t size_b,
+ const char *testcase, int line)
+{
+ test_counter++;
+ int err = (size_a != size_b) || memcmp(a, b, size_a);
+ if(err) {
+ printf("not ok %d - %s...\n", test_counter, testcase);
+ printf("# Error on line %d\n", line);
+ //printf("# Expected '%s', but observed '%s' instead (line %d)\n", a, b, line);
+
+ //create difference mask
+ const int longer = size_a > size_b ? size_a : size_b;
+ const int shorter = size_a < size_b ? size_a : size_b;
+ char mask[longer];
+ memset(mask, 0, longer);
+ for(int i=0; i<shorter; ++i)
+ if(a[i] != b[i])
+ mask[i] = 1;
+
+ printf("#\n");
+ printf("# Expected:\n");
+ hexdump(a, mask, size_a);
+ printf("#\n");
+ printf("# Observed:\n");
+ hexdump(b, mask, size_b);
+
+ global_err++;
+ } else if(!tap_quiet)
+ printf("ok %d - %s...\n", test_counter, testcase);
+ return err;
+}
+
+int assert_flt_eq(float a, float b, const char *testcase, int line)
+{
+ int ret = assert_hex_eq((char*)&a, (char*)&b, sizeof(float), sizeof(float),
+ testcase, line);
+ if(ret)
+ printf("#expected=%f actual %f\n", a, b);
+ return ret;
+}
+
+int test_summary(void)
+{
+ printf("# %d test(s) failed out of %d (currently passing %f%% tests)\n",
+ global_err, test_counter, 100.0-global_err*100./test_counter);
+ return global_err ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/src/Tests/test-suite.h b/src/Tests/test-suite.h
@@ -0,0 +1,26 @@
+#include "common.h"
+
+#define TS_ASSERT(b) \
+ assert_true(b, #b, __LINE__)
+
+#define TS_ASSERT_DELTA(a,b,t) \
+ assert_f32_sim(a,b,t,"similar floats", __LINE__)
+
+#define TS_ASSERT_EQUAL_STR(a,b) \
+ assert_str_eq(a,b,a " == " #b, __LINE__)
+
+#define TS_ASSERT_EQUAL_CPP(a,b) \
+ assert_true(a == b,"equality check", __LINE__)
+
+#define TS_ASSERT_EQUAL_INT(a,b) \
+ assert_int_eq(a,b,"similar ints", __LINE__)
+
+#define TS_ASSERT_EQUAL_FLT(a,b) \
+ assert_f32_eq(a,b,"similar ints", __LINE__)
+#define TS_NON_NULL(a) \
+ assert_non_null(a, "valid pointer", __LINE__)
+
+#define RUN_TEST(x) \
+ test.setUp();\
+ test.x();\
+ test.tearDown()