zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit 9d7dca8bcfd18e5c72539b481e1ed7d778d3cca4
parent 67f775efbc4a97f7f28de9fcc9a9f7e54d4bd628
Author: fundamental <mark.d.mccurry@gmail.com>
Date:   Mon, 22 Jul 2019 23:11:20 -0400

Format WatchPoint & Formalize Unit Test

Breaks down the trigger test for the watch point system revealing a few bugs.
The TriggerTest is expected to fail with this commit.

Diffstat:
Msrc/Synth/WatchPoint.cpp | 66+++++++++++++++++++++++++++++++++---------------------------------
Msrc/Tests/TriggerTest.h | 159+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
2 files changed, 128 insertions(+), 97 deletions(-)

diff --git a/src/Synth/WatchPoint.cpp b/src/Synth/WatchPoint.cpp @@ -113,7 +113,7 @@ void WatchManager::tick(void) arg_types[j] = 'f'; arg_val[j].f = data_list[i][j]; } - + write_back->writeArray(active_list[i], arg_types, arg_val); deactivate[i] = true; } @@ -132,7 +132,7 @@ void WatchManager::tick(void) memset(prebuffer[i], 0, sizeof(float)*MAX_SAMPLE); deactivate[i] = false; trigger[i] = false; - + } } @@ -190,8 +190,8 @@ void WatchManager::satisfy(const char *id, float *f, int n) // printf("\n matched: %s\n", id); int space = MAX_SAMPLE - sample_list[selected]; - - + + for(int i = 0; i < n; ++i){ prebuffer[selected][i] = f[i]; } @@ -205,45 +205,45 @@ void WatchManager::satisfy(const char *id, float *f, int n) //FIXME buffer overflow if(space){ for(int i=0; i<space; ++i){ - if(!trigger[selected]){ - if(i == 0) - i++; - if (f[i-1] <= 0 && f[i] > 0){ - trigger[selected] = true; - for(int k=0; k<MAX_WATCH; ++k){ - if(selected != k && !trigger[k]){ - char tmp[128]; - char tmp1[128]; - strcpy(tmp, active_list[selected]); - strcpy(tmp1, active_list[k]); - - if(strlen(active_list[k]) < strlen(active_list[selected])) - tmp[strlen(tmp)-1] =0; - else if (strlen(active_list[k]) > strlen(active_list[selected])) - tmp1[strlen(tmp1)-1] =0; - if(!strcmp(tmp1,tmp)){ - trigger[k] = true; - int space_k = MAX_SAMPLE - sample_list[k]; - - if(space_k >= n) - space_k = n; - - for(int j = i; j < space_k ; ++j){ - data_list[k][sample_list[k]] = prebuffer[k][j]; - sample_list[k]++; - } - } + if(!trigger[selected]){ + if(i == 0) + i++; + if (f[i-1] <= 0 && f[i] > 0){ + trigger[selected] = true; + for(int k=0; k<MAX_WATCH; ++k){ + if(selected != k && !trigger[k]){ + char tmp[128]; + char tmp1[128]; + strcpy(tmp, active_list[selected]); + strcpy(tmp1, active_list[k]); + + if(strlen(active_list[k]) < strlen(active_list[selected])) + tmp[strlen(tmp)-1] =0; + else if (strlen(active_list[k]) > strlen(active_list[selected])) + tmp1[strlen(tmp1)-1] =0; + if(!strcmp(tmp1,tmp)){ + trigger[k] = true; + int space_k = MAX_SAMPLE - sample_list[k]; + + if(space_k >= n) + space_k = n; + + for(int j = i; j < space_k ; ++j){ + data_list[k][sample_list[k]] = prebuffer[k][j]; + sample_list[k]++; } + } } } } + } if(trigger[selected]){ data_list[selected][sample_list[selected]] = f[i]; sample_list[selected]++; } } - + } } } diff --git a/src/Tests/TriggerTest.h b/src/Tests/TriggerTest.h @@ -26,6 +26,7 @@ #include "../Params/Presets.h" #include "../globals.h" #include <rtosc/thread-link.h> +#include <rtosc/rtosc.h> using namespace std; using namespace zyn; @@ -55,12 +56,11 @@ class TriggerTest:public CxxTest::TestSuite synth->buffersize = 32; synth->alias(false); 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; - + for(int i = 0; i < synth->buffersize; ++i) { + outL[i] = 0; + outR[i] = 0; + } time = new AbsTime(*synth); @@ -69,17 +69,8 @@ class TriggerTest:public CxxTest::TestSuite //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); - + sprng(0x7eefdead); + controller = new Controller(*synth, time); //lets go with.... 50! as a nice note @@ -101,69 +92,109 @@ class TriggerTest:public CxxTest::TestSuite 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 + 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]); + } -#ifdef WRITE_OUTPUT - ofstream file("subnoteout", ios::out); -#endif + void testCombinedTrigger() { + //Generate a note note->noteout(outL, outR); -#ifdef WRITE_OUTPUT - for(int i = 0; i < synth->buffersize; ++i) - file << outL[i] << std::endl; - -#endif - sampleCount += synth->buffersize; 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")); + TS_ASSERT(!w->trigger_active("noteout1")); + + //Setup a watchpoint + // + // - Watchpoints will be added to the active list in the watch + // manager + // - Watchpoints will not be triggered w->add_watch("noteout"); w->add_watch("noteout1"); TS_ASSERT(!w->trigger_active("noteout")); TS_ASSERT(!w->trigger_active("noteout1")); + TS_ASSERT_EQUALS(string("noteout"), w->active_list[0]); + TS_ASSERT_EQUALS(string("noteout1"), 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); - sampleCount += synth->buffersize; + w->tick(); + dump_samples("Step 1 pre-buffer"); + TS_ASSERT(w->trigger_active("noteout")); + TS_ASSERT(w->trigger_active("noteout1")); + TS_ASSERT(!tr->hasNext()); + TS_ASSERT_LESS_THAN_EQUALS(w->sample_list[0], 32);//only 32 have been + TS_ASSERT_LESS_THAN_EQUALS(w->sample_list[1], 32);//processed so far + + + //Both should continue to accumulate samples note->noteout(outL, outR); - sampleCount += synth->buffersize; + w->tick(); + dump_samples("Step 2 pre-buffer\n"); TS_ASSERT(w->trigger_active("noteout1")); TS_ASSERT(w->trigger_active("noteout")); + TS_ASSERT(!tr->hasNext()); + TS_ASSERT_LESS_THAN_EQUALS(w->sample_list[0], 64);//only 64 have been + TS_ASSERT_LESS_THAN_EQUALS(w->sample_list[1], 64);//processed so far + + //Continue accum samples note->noteout(outL, outR); - sampleCount += synth->buffersize; + w->tick(); + dump_samples("Step 3 pre-buffer\n"); + TS_ASSERT(w->trigger_active("noteout1")); + TS_ASSERT(w->trigger_active("noteout")); + TS_ASSERT(!tr->hasNext()); + TS_ASSERT_LESS_THAN_EQUALS(w->sample_list[0], 96);//only 96 have been + TS_ASSERT_LESS_THAN_EQUALS(w->sample_list[1], 96);//processed so far + + //Finish accumulating samples note->noteout(outL, outR); - sampleCount += synth->buffersize; w->tick(); - TS_ASSERT_EQUALS(string("noteout"), tr->read()); - - 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 + dump_samples("Step 4 pre-buffer\n"); + TS_ASSERT(!w->trigger_active("noteout1")); + TS_ASSERT(!w->trigger_active("noteout")); + TS_ASSERT(tr->hasNext()); + + + +#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"), msg1); + TS_ASSERT_EQUALS(string(f128), rtosc_argument_string(msg1)); + TS_ASSERT_EQUALS(128, strlen(rtosc_argument_string(msg1))); + TS_ASSERT(tr->hasNext()); + const char *msg2 = tr->read(); + TS_ASSERT_EQUALS(string("noteout1"), msg2); + TS_ASSERT_EQUALS(128, strlen(rtosc_argument_string(msg2))); + TS_ASSERT_EQUALS(string(f128), rtosc_argument_string(msg2)); + TS_ASSERT(!tr->hasNext()); } -#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 };