AdNoteTest.cpp (7943B)
1 /* 2 ZynAddSubFX - a software synthesizer 3 AdNoteTest.h - CxxTest for Synth/ADnote 4 Copyright (C) 2009-2011 Mark McCurry 5 Copyright (C) 2009 Harald Hvaal 6 Authors: Mark McCurry, Harald Hvaal 7 This program is free software; you can redistribute it and/or 8 modify it under the terms of the GNU General Public License 9 as published by the Free Software Foundation; either version 2 10 of the License, or (at your option) any later version. 11 */ 12 13 14 #include "test-suite.h" 15 #include <iostream> 16 #include <fstream> 17 #include <ctime> 18 #include <string> 19 #include "../Misc/Master.h" 20 #include "../Misc/Util.h" 21 #include "../Misc/Allocator.h" 22 #include "../Synth/ADnote.h" 23 #include "../Params/Presets.h" 24 #include "../DSP/FFTwrapper.h" 25 #include "../Synth/LFO.h" 26 #include "../Params/LFOParams.h" 27 #include "../globals.h" 28 #include <rtosc/thread-link.h> 29 30 using namespace std; 31 using namespace zyn; 32 33 SYNTH_T *synth; 34 35 36 class AdNoteTest 37 { 38 public: 39 rtosc::ThreadLink *tr; 40 ADnote *note; 41 AbsTime *time; 42 FFTwrapper *fft; 43 ADnoteParameters *defaultPreset; 44 Controller *controller; 45 Alloc memory; 46 float test_freq_log2; 47 WatchManager *w; 48 float *outR, *outL; 49 50 LFOParams *lfop; 51 int randval(int min, int max) 52 { 53 int ret = rand()%(1+max-min)+min; 54 //printf("ret = %d (%d..%d)\n",ret, min,max); 55 return ret; 56 } 57 58 void randomize_params(void) { 59 lfop->Pintensity = randval(0,127); 60 lfop->Pstartphase = randval(0,127); 61 lfop->Pcutoff = randval(0,127); 62 lfop->PLFOtype = randval(0,6); 63 lfop->Prandomness = randval(0,127); 64 lfop->Pfreqrand = randval(0,127); 65 lfop->Pcontinous = randval(0,1); 66 lfop->Pstretch = randval(0,127); 67 lfop->fel = (consumer_location_type_t) randval(1,2); 68 69 } 70 71 void run_lfo_randomtest(void) 72 { 73 LFO* lfo = new LFO(*lfop, 440.0f, *time); 74 for(int i=0; i<100; ++i) { 75 float out = lfo->lfoout(); 76 switch(lfop->fel) 77 { 78 case consumer_location_type_t::amp: 79 TS_ASSERT((-2.001f < out && out < 2.001f)); // try to fix test on MacOS 80 break; 81 case consumer_location_type_t::filter: 82 TS_ASSERT((-8.0f < out && out < 8.0f)); 83 break; 84 case consumer_location_type_t::freq: 85 case consumer_location_type_t::unspecified: 86 default: 87 break; 88 } 89 } 90 delete lfo; 91 } 92 93 94 void setUp() { 95 //First the sensible settings and variables that have to be set: 96 synth = new SYNTH_T; 97 synth->buffersize = 256; 98 //synth->alias(); 99 time = new AbsTime(*synth); 100 101 outL = new float[synth->buffersize]; 102 for(int i = 0; i < synth->buffersize; ++i) 103 *(outL + i) = 0; 104 outR = new float[synth->buffersize]; 105 for(int i = 0; i < synth->buffersize; ++i) 106 *(outR + i) = 0; 107 108 tr = new rtosc::ThreadLink(1024,3); 109 w = new WatchManager(tr); 110 111 fft = new FFTwrapper(synth->oscilsize); 112 //prepare the default settings 113 defaultPreset = new ADnoteParameters(*synth, fft, time); 114 115 //Assert defaults 116 TS_ASSERT(!defaultPreset->VoicePar[1].Enabled); 117 118 XMLwrapper wrap; 119 cout << string(SOURCE_DIR) + string("/guitar-adnote.xmz") 120 << endl; 121 wrap.loadXMLfile(string(SOURCE_DIR) 122 + string("/guitar-adnote.xmz")); 123 TS_ASSERT(wrap.enterbranch("MASTER")); 124 TS_ASSERT(wrap.enterbranch("PART", 0)); 125 TS_ASSERT(wrap.enterbranch("INSTRUMENT")); 126 TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT")); 127 TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT_ITEM", 0)); 128 TS_ASSERT(wrap.enterbranch("ADD_SYNTH_PARAMETERS")); 129 defaultPreset->getfromXML(wrap); 130 //defaultPreset->defaults(); 131 132 //verify xml was loaded 133 TS_ASSERT(defaultPreset->VoicePar[1].Enabled); 134 135 136 137 controller = new Controller(*synth, time); 138 139 //lets go with.... 50! as a nice note 140 test_freq_log2 = log2f(440.0f) + (50.0 - 69.0f) / 12.0f; 141 SynthParams pars{memory, *controller, *synth, *time, 120, 0, test_freq_log2, false, prng()}; 142 143 note = new ADnote(defaultPreset, pars,w); 144 145 } 146 147 void tearDown() { 148 delete note; 149 delete controller; 150 delete defaultPreset; 151 delete fft; 152 delete w; 153 delete tr; 154 delete [] outL; 155 delete [] outR; 156 FFT_cleanup(); 157 delete time; 158 delete synth; 159 } 160 161 void testDefaults() { 162 int sampleCount = 0; 163 164 //#define WRITE_OUTPUT 165 166 #ifdef WRITE_OUTPUT 167 ofstream file("adnoteout", ios::out); 168 #endif 169 note->noteout(outL, outR); 170 #ifdef WRITE_OUTPUT 171 for(int i = 0; i < synth->buffersize; ++i) 172 file << outR[i] << std::endl; 173 174 #endif 175 sampleCount += synth->buffersize; 176 TS_ASSERT_DELTA(outR[255], 0.25552f, 0.0001f); 177 note->releasekey(); 178 179 TS_ASSERT(!tr->hasNext()); 180 w->add_watch("noteout/be4_mix"); 181 note->noteout(outL, outR); 182 sampleCount += synth->buffersize; 183 TS_ASSERT_DELTA(outR[255], -0.46883f, 0.0001f); 184 w->tick(); 185 TS_ASSERT(tr->hasNext()); 186 187 note->noteout(outL, outR); 188 sampleCount += synth->buffersize; 189 w->tick(); 190 TS_ASSERT_DELTA(outR[255], 0.06695f, 0.0001f); 191 192 note->noteout(outL, outR); 193 sampleCount += synth->buffersize; 194 TS_ASSERT_DELTA(outR[255], 0.11621f, 0.0001f); 195 w->tick(); 196 note->noteout(outL, outR); 197 sampleCount += synth->buffersize; 198 TS_ASSERT_DELTA(outR[255], -0.1169f, 0.0001f); 199 w->tick(); 200 201 TS_ASSERT(tr->hasNext()); 202 TS_ASSERT_EQUAL_STR("noteout/be4_mix", tr->read()); 203 TS_ASSERT(!tr->hasNext()); 204 205 note->noteout(outL, outR); 206 sampleCount += synth->buffersize; 207 208 209 while(!note->finished()) { 210 note->noteout(outL, outR); 211 #ifdef WRITE_OUTPUT 212 for(int i = 0; i < synth->buffersize; ++i) 213 file << outL[i] << std::endl; 214 215 #endif 216 sampleCount += synth->buffersize; 217 } 218 #ifdef WRITE_OUTPUT 219 file.close(); 220 #endif 221 222 TS_ASSERT_EQUAL_INT(sampleCount, 30208); 223 224 lfop = new LFOParams(time); 225 lfop->fel = zyn::consumer_location_type_t::amp; 226 lfop->freq = 2.0f; 227 lfop->delay = 0.0f; 228 for(int i=0; i<10000; ++i) { 229 randomize_params(); 230 run_lfo_randomtest(); 231 } 232 delete lfop; 233 234 235 } 236 237 #define OUTPUT_PROFILE 238 #ifdef OUTPUT_PROFILE 239 void testSpeed() { 240 const int samps = 15000; 241 242 int t_on = clock(); // timer before calling func 243 for(int i = 0; i < samps; ++i) 244 note->noteout(outL, outR); 245 int t_off = clock(); // timer when func returns 246 247 printf("AdNoteTest: %f seconds for %d Samples to be generated.\n", 248 (static_cast<float>(t_off - t_on)) / CLOCKS_PER_SEC, samps); 249 } 250 #endif 251 }; 252 253 int main() 254 { 255 tap_quiet = 1; 256 AdNoteTest test; 257 test.setUp(); 258 test.testDefaults(); 259 test.tearDown(); 260 return test_summary(); 261 }