zynaddsubfx

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

commit 67f775efbc4a97f7f28de9fcc9a9f7e54d4bd628
parent 6e838ba43db848a0645e96d8609310b23db7ea7b
Author: fundamental <mark.d.mccurry@gmail.com>
Date:   Mon, 22 Jul 2019 22:32:41 -0400

Merge WIP GSoC Signal Scope PR

Diffstat:
Msrc/Misc/Master.cpp | 3++-
Msrc/Synth/ADnote.cpp | 8+++++---
Msrc/Synth/ADnote.h | 3++-
Msrc/Synth/PADnote.cpp | 9+++++++--
Msrc/Synth/PADnote.h | 2++
Msrc/Synth/SUBnote.cpp | 8++++++--
Msrc/Synth/SUBnote.h | 5+++--
Msrc/Synth/WatchPoint.cpp | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/Synth/WatchPoint.h | 5++++-
Msrc/Tests/AdNoteTest.h | 31++++++++++++++++++++++---------
Msrc/Tests/CMakeLists.txt | 3+++
Msrc/Tests/PadNoteTest.h | 10+++++++++-
Msrc/Tests/SubNoteTest.h | 26+++++++++++++++++++++++---
Asrc/Tests/TriggerTest.h | 169+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/Tests/WatchTest.h | 3+++
15 files changed, 346 insertions(+), 34 deletions(-)

diff --git a/src/Misc/Master.cpp b/src/Misc/Master.cpp @@ -369,7 +369,8 @@ static const Ports automate_ports = { static const Ports watchPorts = { {"add:s", rDoc("Add synthesis state to watch"), 0, rBegin; - m->watcher.add_watch(rtosc_argument(msg,0).s); + if(!m->watcher.active(rtosc_argument(msg,0).s)) + m->watcher.add_watch(rtosc_argument(msg,0).s); rEnd}, }; diff --git a/src/Synth/ADnote.cpp b/src/Synth/ADnote.cpp @@ -32,7 +32,7 @@ namespace zyn { ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars, WatchManager *wm, const char *prefix) - :SynthNote(spars), pars(*pars_) + :SynthNote(spars), pars(*pars_), watchOut(wm, prefix, "noteout"), watchOut1(wm,prefix,"noteout1") { memory.beginTransaction(); tmpwavel = memory.valloc<float>(synth.buffersize); @@ -1701,9 +1701,11 @@ int ADnote::noteout(float *outl, float *outr) else for(int i = 0; i < synth.buffersize; ++i) tmpwavel[i] += tw[i]; + if(nvoice == 0) + watchOut(tmpwavel,synth.buffersize); + + watchOut1(tmpwavel,synth.buffersize); } - - float unison_amplitude = 1.0f / sqrt(unison_size[nvoice]); //reduce the amplitude for large unison sizes // Amplitude float oldam = oldamplitude[nvoice] * unison_amplitude; diff --git a/src/Synth/ADnote.h b/src/Synth/ADnote.h @@ -19,6 +19,7 @@ #include "LFO.h" #include "../Params/ADnoteParameters.h" #include "../Params/Controller.h" +#include "WatchPoint.h" //Globals @@ -57,7 +58,7 @@ class ADnote:public SynthNote int setupVoiceUnison(int nvoice); void setupVoiceDetune(int nvoice); void setupVoiceMod(int nvoice, bool first_run = true); - + VecWatchPoint watchOut,watchOut1; /**Changes the frequency of an oscillator. * @param nvoice voice to run computations on * @param in_freq new frequency*/ diff --git a/src/Synth/PADnote.cpp b/src/Synth/PADnote.cpp @@ -28,7 +28,8 @@ namespace zyn { PADnote::PADnote(const PADnoteParameters *parameters, SynthParams pars, const int& interpolation, WatchManager *wm, const char *prefix) - :SynthNote(pars), pars(*parameters), interpolation(interpolation) + :SynthNote(pars), pars(*parameters), interpolation(interpolation), + watchOut(wm, prefix, "noteout"), watchOut1(wm,prefix,"noteout1") { NoteGlobalPar.GlobalFilter = nullptr; NoteGlobalPar.FilterEnvelope = nullptr; @@ -354,7 +355,7 @@ int PADnote::Compute_Cubic(float *outl, int PADnote::noteout(float *outl, float *outr) -{ +{ computecurrentparameters(); float *smps = pars.sample[nsample].smp; if(smps == NULL) { @@ -377,6 +378,7 @@ int PADnote::noteout(float *outl, float *outr) else Compute_Linear(outl, outr, freqhi, freqlo); + watchOut1(outr,synth.buffersize); if(firsttime) { fadein(outl); @@ -399,6 +401,7 @@ int PADnote::noteout(float *outl, float *outr) break; } } + if(ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude, globalnewamplitude)) // Amplitude Interpolation @@ -420,6 +423,8 @@ int PADnote::noteout(float *outl, float *outr) // Apply legato-specific sound signal modifications legato.apply(*this, outl, outr); + watchOut(outr,synth.buffersize); + // Check if the global amplitude is finished. // If it does, disable the note if(NoteGlobalPar.AmpEnvelope->finished()) { diff --git a/src/Synth/PADnote.h b/src/Synth/PADnote.h @@ -35,6 +35,8 @@ class PADnote:public SynthNote bool finished() const; void entomb(void); + VecWatchPoint watchOut,watchOut1; + void releasekey(); private: void setup(float freq, float velocity, int portamento_, diff --git a/src/Synth/SUBnote.cpp b/src/Synth/SUBnote.cpp @@ -44,7 +44,8 @@ SUBnote::SUBnote(const SUBnoteParameters *parameters, SynthParams &spars, WatchM GlobalFilter(nullptr), GlobalFilterEnvelope(nullptr), NoteEnabled(true), - lfilter(nullptr), rfilter(nullptr) + lfilter(nullptr), rfilter(nullptr), + watchOut(wm, prefix, "noteout"), watchOut1(wm,prefix,"noteout1") { setup(spars.frequency, spars.velocity, spars.portamento, spars.note_log2_freq, false, wm, prefix); } @@ -518,6 +519,9 @@ void SUBnote::chanOutput(float *out, bpfilter *bp, int buffer_size) for(int i = 0; i < synth.buffersize; ++i) out[i] += tmpsmp[i] * rolloff; + + if(n == 0) + watchOut(tmpsmp,buffer_size); } } @@ -547,7 +551,7 @@ int SUBnote::noteout(float *outl, float *outr) memcpy(outr, outl, synth.bufferbytes); } - + watchOut1(outl,synth.buffersize); if(firsttick) { int n = 10; if(n > synth.buffersize) diff --git a/src/Synth/SUBnote.h b/src/Synth/SUBnote.h @@ -16,6 +16,7 @@ #include "SynthNote.h" #include "../globals.h" +#include "WatchPoint.h" namespace zyn { @@ -28,7 +29,7 @@ class SUBnote:public SynthNote SynthNote *cloneLegato(void); void legatonote(LegatoParams pars); - + VecWatchPoint watchOut,watchOut1; int noteout(float *outl, float *outr); //note output,return 0 if the note is finished void releasekey(); bool finished() const; @@ -50,7 +51,7 @@ class SUBnote:public SynthNote void KillNote(); const SUBnoteParameters &pars; - + //parameters bool stereo; int numstages; //number of stages of filters diff --git a/src/Synth/WatchPoint.cpp b/src/Synth/WatchPoint.cpp @@ -67,6 +67,9 @@ WatchManager::WatchManager(thrlnk *link) memset(sample_list, 0, sizeof(sample_list)); memset(data_list, 0, sizeof(data_list)); memset(deactivate, 0, sizeof(deactivate)); + memset(prebuffer, 0, sizeof(prebuffer)); + memset(trigger, 0, sizeof(trigger)); + } void WatchManager::add_watch(const char *id) @@ -82,13 +85,14 @@ void WatchManager::add_watch(const char *id) fast_strcpy(active_list[i], id, MAX_WATCH_PATH); new_active = true; sample_list[i] = 0; + //printf("\n added watchpoint ID %s\n",id); break; } } } void WatchManager::del_watch(const char *id) -{ +{ //Queue up the delete for(int i=0; i<MAX_WATCH; ++i) if(!strcmp(active_list[i], id)) @@ -99,14 +103,17 @@ void WatchManager::tick(void) { //Try to send out any vector stuff for(int i=0; i<MAX_WATCH; ++i) { - if(sample_list[i]) { + int framesize = 2; + if(strstr(active_list[i], "noteout") != NULL) + framesize = MAX_SAMPLE-1; + if(sample_list[i] >= framesize-1) { char arg_types[MAX_SAMPLE+1] = {0}; rtosc_arg_t arg_val[MAX_SAMPLE]; for(int j=0; j<sample_list[i]; ++j) { 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; } @@ -118,9 +125,14 @@ void WatchManager::tick(void) //Clear deleted slots for(int i=0; i<MAX_WATCH; ++i) { if(deactivate[i]) { - memset(active_list[i], 0, 128); + //printf("\ndelete id : %s\n",active_list[i]); + memset(active_list[i], 0, MAX_SAMPLE); sample_list[i] = 0; + memset(data_list[i], 0, sizeof(float)*MAX_SAMPLE); + memset(prebuffer[i], 0, sizeof(float)*MAX_SAMPLE); deactivate[i] = false; + trigger[i] = false; + } } @@ -138,6 +150,14 @@ bool WatchManager::active(const char *id) const return false; } +bool WatchManager::trigger_active(const char *id) const +{ + for(int i=0; i<MAX_WATCH; ++i) + if(!strcmp(active_list[i], id)) + return trigger[i]; + return false; +} + int WatchManager::samples(const char *id) const { for(int i=0; i<MAX_WATCH; ++i) @@ -155,8 +175,8 @@ void WatchManager::satisfy(const char *id, float f) } void WatchManager::satisfy(const char *id, float *f, int n) -{ - int selected = -1; +{ + int selected = -1; for(int i=0; i<MAX_WATCH; ++i) if(!strcmp(active_list[i], id)) selected = i; @@ -164,9 +184,66 @@ void WatchManager::satisfy(const char *id, float *f, int n) if(selected == -1) return; + // printf("\npath : %s \n", id); + + // if (!strcmp(id,"/part0/kit0/subpars/noteout")) + // 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]; + } + + if(space >= n) + space = n; + + if(n == 2) + trigger[selected] = true; + //FIXME buffer overflow - for(int i=0; i<n; ++i) - data_list[selected][sample_list[selected]++] = f[i]; + 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]){ + data_list[selected][sample_list[selected]] = f[i]; + sample_list[selected]++; + } + } + + } } - } diff --git a/src/Synth/WatchPoint.h b/src/Synth/WatchPoint.h @@ -39,15 +39,18 @@ struct WatchManager thrlnk *write_back; bool new_active; char active_list[MAX_WATCH][MAX_WATCH_PATH]; - float data_list[MAX_SAMPLE][MAX_WATCH]; + float data_list[MAX_WATCH][MAX_SAMPLE]; + float prebuffer[MAX_WATCH][MAX_SAMPLE]; int sample_list[MAX_WATCH]; bool deactivate[MAX_WATCH]; + bool trigger[MAX_WATCH]; //External API WatchManager(thrlnk *link=0); void add_watch(const char *); void del_watch(const char *); void tick(void); + bool trigger_active(const char *) const; //Watch Point Query API bool active(const char *) const; diff --git a/src/Tests/AdNoteTest.h b/src/Tests/AdNoteTest.h @@ -1,11 +1,9 @@ /* 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 @@ -25,6 +23,7 @@ #include "../Params/Presets.h" #include "../DSP/FFTwrapper.h" #include "../globals.h" +#include <rtosc/thread-link.h> using namespace std; using namespace zyn; @@ -35,6 +34,7 @@ SYNTH_T *synth; class AdNoteTest:public CxxTest::TestSuite { public: + rtosc::ThreadLink *tr; ADnote *note; AbsTime *time; FFTwrapper *fft; @@ -42,7 +42,7 @@ class AdNoteTest:public CxxTest::TestSuite Controller *controller; Alloc memory; unsigned char testnote; - + WatchManager *w; float *outR, *outL; void setUp() { @@ -59,6 +59,8 @@ class AdNoteTest:public CxxTest::TestSuite 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 @@ -93,7 +95,7 @@ class AdNoteTest:public CxxTest::TestSuite float freq = 440.0f * powf(2.0f, (testnote - 69.0f) / 12.0f); SynthParams pars{memory, *controller, *synth, *time, freq, 120, 0, testnote / 12.0f, false, prng()}; - note = new ADnote(defaultPreset, pars); + note = new ADnote(defaultPreset, pars,w); } @@ -123,27 +125,38 @@ class AdNoteTest:public CxxTest::TestSuite #endif sampleCount += synth->buffersize; - TS_ASSERT_DELTA(outL[255], 0.2555f, 0.0001f); - note->releasekey(); - + TS_ASSERT(!tr->hasNext()); + w->add_watch("noteout"); note->noteout(outL, outR); sampleCount += synth->buffersize; TS_ASSERT_DELTA(outL[255], -0.4688f, 0.0001f); - + w->tick(); + TS_ASSERT(!tr->hasNext()); + note->noteout(outL, outR); sampleCount += synth->buffersize; + w->tick(); TS_ASSERT_DELTA(outL[255], 0.0613f, 0.0001f); note->noteout(outL, outR); sampleCount += synth->buffersize; TS_ASSERT_DELTA(outL[255], 0.0971f, 0.0001f); - + w->tick(); note->noteout(outL, outR); sampleCount += synth->buffersize; TS_ASSERT_DELTA(outL[255], -0.0901f, 0.0001f); + w->tick(); + + TS_ASSERT(tr->hasNext()); + TS_ASSERT_EQUALS(string("noteout"), tr->read()); + TS_ASSERT(!tr->hasNext()); + + note->noteout(outL, outR); + sampleCount += synth->buffersize; + while(!note->finished()) { note->noteout(outL, outR); diff --git a/src/Tests/CMakeLists.txt b/src/Tests/CMakeLists.txt @@ -31,6 +31,8 @@ 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 @@ -49,6 +51,7 @@ 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}) diff --git a/src/Tests/PadNoteTest.h b/src/Tests/PadNoteTest.h @@ -29,6 +29,7 @@ #include "../Params/Presets.h" #include "../DSP/FFTwrapper.h" #include "../globals.h" +#include <rtosc/thread-link.h> using namespace std; using namespace zyn; @@ -50,6 +51,8 @@ class PadNoteTest:public CxxTest::TestSuite unsigned char testnote; Alloc memory; int interpolation; + rtosc::ThreadLink *tr; + WatchManager *w; float *outR, *outL; @@ -68,6 +71,8 @@ class PadNoteTest:public CxxTest::TestSuite 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 @@ -152,10 +157,13 @@ class PadNoteTest:public CxxTest::TestSuite note->releasekey(); - + TS_ASSERT(!tr->hasNext()); + w->add_watch("noteout"); note->noteout(outL, outR); sampleCount += synth->buffersize; TS_ASSERT_DELTA(outL[255], -0.0729f, 0.0005f); + w->tick(); + TS_ASSERT(!tr->hasNext()); note->noteout(outL, outR); sampleCount += synth->buffersize; diff --git a/src/Tests/SubNoteTest.h b/src/Tests/SubNoteTest.h @@ -25,6 +25,7 @@ #include "../Params/SUBnoteParameters.h" #include "../Params/Presets.h" #include "../globals.h" +#include <rtosc/thread-link.h> using namespace std; using namespace zyn; @@ -42,6 +43,8 @@ class SubNoteTest:public CxxTest::TestSuite Controller *controller; unsigned char testnote; Alloc memory; + rtosc::ThreadLink *tr; + WatchManager *w; float *outR, *outL; @@ -59,6 +62,9 @@ class SubNoteTest:public CxxTest::TestSuite 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; @@ -79,7 +85,7 @@ class SubNoteTest:public CxxTest::TestSuite float freq = 440.0f * powf(2.0f, (testnote - 69.0f) / 12.0f); SynthParams pars{memory, *controller, *synth, *time, freq, 120, 0, testnote / 12.0f, false, prng()}; - note = new SUBnote(defaultPreset, pars); + note = new SUBnote(defaultPreset, pars, w); this->pars = defaultPreset; } @@ -116,22 +122,36 @@ class SubNoteTest:public CxxTest::TestSuite note->releasekey(); - + TS_ASSERT(!tr->hasNext()); + w->add_watch("noteout"); + note->noteout(outL, outR); sampleCount += synth->buffersize; TS_ASSERT_DELTA(outL[255], 0.0029f, 0.0001f); + w->tick(); note->noteout(outL, outR); sampleCount += synth->buffersize; TS_ASSERT_DELTA(outL[255], -0.0011f, 0.0001f); + w->tick(); + TS_ASSERT(tr->hasNext()); + TS_ASSERT_EQUALS(string("noteout"), tr->read()); + TS_ASSERT(!tr->hasNext()); + + w->add_watch("noteout1"); note->noteout(outL, outR); sampleCount += synth->buffersize; TS_ASSERT_DELTA(outL[255], -0.0017f, 0.0001f); - + w->tick(); + note->noteout(outL, outR); sampleCount += synth->buffersize; TS_ASSERT_DELTA(outL[255], -0.0005f, 0.0001f); + w->tick(); + TS_ASSERT(tr->hasNext()); + TS_ASSERT_EQUALS(string("noteout1"), tr->read()); + TS_ASSERT(!tr->hasNext()); while(!note->finished()) { note->noteout(outL, outR); diff --git a/src/Tests/TriggerTest.h b/src/Tests/TriggerTest.h @@ -0,0 +1,169 @@ +/* + 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 TriggerTest:public CxxTest::TestSuite +{ + public: + + SUBnoteParameters *pars; + SUBnote *note; + Master *master; + AbsTime *time; + Controller *controller; + unsigned char testnote; + 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]; + 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; + + + time = new AbsTime(*synth); + + 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 + testnote = 50; + float freq = 440.0f * powf(2.0f, (testnote - 69.0f) / 12.0f); + + SynthParams pars{memory, *controller, *synth, *time, freq, 120, 0, testnote / 12.0f, 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; + note->releasekey(); + TS_ASSERT(!tr->hasNext()); + w->add_watch("noteout"); + w->add_watch("noteout1"); + TS_ASSERT(!w->trigger_active("noteout")); + TS_ASSERT(!w->trigger_active("noteout1")); + note->noteout(outL, outR); + sampleCount += synth->buffersize; + note->noteout(outL, outR); + sampleCount += synth->buffersize; + TS_ASSERT(w->trigger_active("noteout1")); + TS_ASSERT(w->trigger_active("noteout")); + note->noteout(outL, outR); + sampleCount += synth->buffersize; + 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 + } + +#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/WatchTest.h b/src/Tests/WatchTest.h @@ -30,6 +30,7 @@ #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; @@ -52,6 +53,7 @@ class WatchTest:public CxxTest::TestSuite w = new WatchManager(tr); par = new LFOParams; l = new LFO(*par, 440.0, *at, w); + } void tearDown() { @@ -77,4 +79,5 @@ class WatchTest:public CxxTest::TestSuite TS_ASSERT_EQUALS(string("out"), tr->read()); TS_ASSERT(!tr->hasNext()); } + };