zynaddsubfx

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

PadNoteTest.cpp (10305B)


      1 /*
      2   ZynAddSubFX - a software synthesizer
      3 
      4   PadNoteTest.h - CxxTest for Synth/PADnote
      5   Copyright (C) 20012 zco
      6   Author: zco
      7 
      8   This program is free software; you can redistribute it and/or
      9   modify it under the terms of the GNU General Public License
     10   as published by the Free Software Foundation; either version 2
     11   of the License, or (at your option) any later version.
     12 */
     13 
     14 
     15 //Based Upon AdNoteTest.h and SubNoteTest.h
     16 #include "test-suite.h"
     17 #include <complex>
     18 #include <ctime>
     19 #include <string>
     20 #define private public
     21 #include "../Synth/PADnote.h"
     22 #undef private
     23 #include "../Misc/Master.h"
     24 #include "../Misc/Util.h"
     25 #include "../Misc/Allocator.h"
     26 #include "../Misc/XMLwrapper.h"
     27 #include "../Synth/PADnote.h"
     28 #include "../Synth/OscilGen.h"
     29 #include "../Params/PADnoteParameters.h"
     30 #include "../Params/Presets.h"
     31 #include "../DSP/FFTwrapper.h"
     32 #include "../globals.h"
     33 #include <rtosc/thread-link.h>
     34 using namespace std;
     35 using namespace zyn;
     36 
     37 SYNTH_T *synth;
     38 
     39 #ifndef SOURCE_DIR
     40 #define SOURCE_DIR "BE QUIET COMPILER"
     41 #endif
     42 
     43 class PadNoteTest
     44 {
     45     public:
     46         PADnote      *note;
     47         PADnoteParameters *pars;
     48         Master       *master;
     49         FFTwrapper   *fft;
     50         Controller   *controller;
     51         AbsTime      *time;
     52         float test_freq_log2;
     53         Alloc         memory;
     54         int           interpolation;
     55         rtosc::ThreadLink *tr;
     56         WatchManager *w;
     57 
     58 
     59         float *outR, *outL;
     60 
     61         void setUp() {
     62             interpolation = 0;
     63             synth = new SYNTH_T;
     64             //First the sensible settings and variables that have to be set:
     65             synth->buffersize = 256;
     66             time  = new AbsTime(*synth);
     67 
     68             outL = new float[synth->buffersize];
     69             for(int i = 0; i < synth->buffersize; ++i)
     70                 *(outL + i) = 0;
     71             outR = new float[synth->buffersize];
     72             for(int i = 0; i < synth->buffersize; ++i)
     73                 *(outR + i) = 0;
     74 
     75             tr  = new rtosc::ThreadLink(1024,3);
     76             w   = new WatchManager(tr);
     77 
     78             fft = new FFTwrapper(synth->oscilsize);
     79             //prepare the default settings
     80             pars = new PADnoteParameters(*synth, fft, time);
     81 
     82 
     83             //Assert defaults
     84             ///TS_ASSERT(!defaultPreset->VoicePar[1].Enabled);
     85 
     86             XMLwrapper wrap;
     87             //cout << string(SOURCE_DIR) + string("/guitar-adnote.xmz")
     88             //     << endl;
     89             wrap.loadXMLfile(string(SOURCE_DIR)
     90                               + string("/guitar-adnote.xmz"));
     91             TS_ASSERT(wrap.enterbranch("MASTER"));
     92             TS_ASSERT(wrap.enterbranch("PART", 2));
     93             TS_ASSERT(wrap.enterbranch("INSTRUMENT"));
     94             TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT"));
     95             TS_ASSERT(wrap.enterbranch("INSTRUMENT_KIT_ITEM", 0));
     96             TS_ASSERT(wrap.enterbranch("PAD_SYNTH_PARAMETERS"));
     97             pars->getfromXML(wrap);
     98 
     99 
    100             //defaultPreset->defaults();
    101             pars->applyparameters([]{return false;}, 1);
    102 
    103             //verify xml was loaded
    104             ///TS_ASSERT(defaultPreset->VoicePar[1].Enabled);
    105 
    106 
    107 
    108             controller = new Controller(*synth, time);
    109 
    110             //lets go with.... 50! as a nice note
    111             test_freq_log2 = log2f(440.0f) + (50.0 - 69.0f) / 12.0f;
    112             SynthParams pars_{memory, *controller, *synth, *time, 120, 0, test_freq_log2, false, prng()};
    113 
    114             note = new PADnote(pars, pars_, interpolation);
    115         }
    116 
    117         void tearDown() {
    118             delete note;
    119             delete controller;
    120             delete fft;
    121             delete w;
    122             delete tr;
    123             delete [] outL;
    124             delete [] outR;
    125             delete pars;
    126             FFT_cleanup();
    127             delete time;
    128             delete synth;
    129 
    130             note = NULL;
    131             controller = NULL;
    132             fft = NULL;
    133             outL = NULL;
    134             outR = NULL;
    135             pars = NULL;
    136             synth = NULL;
    137         }
    138 
    139 
    140         void testDefaults() {
    141             int sampleCount = 0;
    142 
    143 
    144 //#define WRITE_OUTPUT
    145 
    146 #ifdef WRITE_OUTPUT
    147             ofstream file("padnoteout", ios::out);
    148 #endif
    149             note->noteout(outL, outR);
    150 
    151 #ifdef WRITE_OUTPUT
    152             for(int i = 0; i < synth->buffersize; ++i)
    153                 file << outL[i] << std::endl;
    154 
    155 #endif
    156             sampleCount += synth->buffersize;
    157 
    158             TS_ASSERT_DELTA(outL[255], -0.0555f, 0.0005f);
    159 
    160 
    161             note->releasekey();
    162 
    163             TS_ASSERT(!tr->hasNext());
    164             w->add_watch("noteout");
    165             note->noteout(outL, outR);
    166             sampleCount += synth->buffersize;
    167             TS_ASSERT_DELTA(outL[255], -0.0726f, 0.0005f);
    168             w->tick();
    169             TS_ASSERT(!tr->hasNext());
    170 
    171             note->noteout(outL, outR);
    172             sampleCount += synth->buffersize;
    173             TS_ASSERT_DELTA(outL[255], -0.0516f, 0.0005f);
    174 
    175             note->noteout(outL, outR);
    176             sampleCount += synth->buffersize;
    177             TS_ASSERT_DELTA(outL[255], 0.0529f, 0.0005f);
    178 
    179             note->noteout(outL, outR);
    180             sampleCount += synth->buffersize;
    181             TS_ASSERT_DELTA(outL[255], 0.0525f, 0.0001f);
    182 
    183             while(!note->finished()) {
    184                 note->noteout(outL, outR);
    185 
    186 #ifdef WRITE_OUTPUT
    187                 for(int i = 0; i < synth->buffersize; ++i)
    188                     file << outL[i] << std::endl;
    189 
    190 #endif
    191                 sampleCount += synth->buffersize;
    192             }
    193 #ifdef WRITE_OUTPUT
    194             file.close();
    195 #endif
    196 
    197             TS_ASSERT_EQUAL_INT(sampleCount, 5888);
    198         }
    199 
    200         void testInitialization() {
    201             TS_ASSERT(pars->Pmode == PADnoteParameters::pad_mode::bandwidth);
    202 
    203             TS_ASSERT_EQUAL_INT(pars->PVolume, 90);
    204             TS_NON_NULL(pars->oscilgen);
    205             TS_NON_NULL(pars->resonance);
    206 
    207             TS_ASSERT_DELTA(note->NoteGlobalPar.Volume, 2.597527f, 0.001f);
    208             TS_ASSERT_DELTA(note->NoteGlobalPar.Panning, 0.500000f, 0.01f);
    209 
    210 
    211             for(int i=0; i<8; ++i)
    212                 TS_NON_NULL(pars->sample[i].smp);
    213             for(int i=8; i<PAD_MAX_SAMPLES; ++i)
    214                 TS_ASSERT(!pars->sample[i].smp);
    215 
    216             TS_ASSERT_DELTA(pars->sample[0].smp[0],   0.0516f, 0.0005f);
    217             TS_ASSERT_DELTA(pars->sample[0].smp[1],   0.0845f, 0.0005f);
    218             TS_ASSERT_DELTA(pars->sample[0].smp[2],   0.1021f, 0.0005f);
    219             TS_ASSERT_DELTA(pars->sample[0].smp[3],   0.0919f, 0.0005f);
    220             TS_ASSERT_DELTA(pars->sample[0].smp[4],   0.0708f, 0.0005f);
    221             TS_ASSERT_DELTA(pars->sample[0].smp[5],   0.0414f, 0.0005f);
    222             TS_ASSERT_DELTA(pars->sample[0].smp[6],   0.0318f, 0.0005f);
    223             TS_ASSERT_DELTA(pars->sample[0].smp[7],   0.0217f, 0.0005f);
    224             TS_ASSERT_DELTA(pars->sample[0].smp[8],   0.0309f, 0.0005f);
    225             TS_ASSERT_DELTA(pars->sample[0].smp[9],   0.0584f, 0.0005f);
    226             TS_ASSERT_DELTA(pars->sample[0].smp[10],  0.0266f, 0.0005f);
    227             TS_ASSERT_DELTA(pars->sample[0].smp[11],  0.0436f, 0.0005f);
    228             TS_ASSERT_DELTA(pars->sample[0].smp[12],  0.0199f, 0.0005f);
    229             TS_ASSERT_DELTA(pars->sample[0].smp[13],  0.0505f, 0.0005f);
    230             TS_ASSERT_DELTA(pars->sample[0].smp[14],  0.0438f, 0.0005f);
    231             TS_ASSERT_DELTA(pars->sample[0].smp[15],  0.0024f, 0.0005f);
    232             TS_ASSERT_DELTA(pars->sample[0].smp[16],  0.0052f, 0.0005f);
    233             TS_ASSERT_DELTA(pars->sample[0].smp[17], -0.0180f, 0.0005f);
    234             TS_ASSERT_DELTA(pars->sample[0].smp[18],  0.0342f, 0.0005f);
    235             TS_ASSERT_DELTA(pars->sample[0].smp[19],  0.0051f, 0.0005f);
    236 
    237 
    238             //Verify Harmonic Input
    239             float harmonics[synth->oscilsize];
    240             memset(harmonics, 0, sizeof(float) * synth->oscilsize);
    241 
    242             pars->oscilgen->get(harmonics, 440.0f, false);
    243 
    244             TS_ASSERT_DELTA(harmonics[0] ,0.683947, 0.0005f);
    245             TS_ASSERT_DELTA(harmonics[1] ,0.128246, 0.0005f);
    246             TS_ASSERT_DELTA(harmonics[2] ,0.003238, 0.0005f);
    247             TS_ASSERT_DELTA(harmonics[3] ,0.280945, 0.0005f);
    248             TS_ASSERT_DELTA(harmonics[4] ,0.263548, 0.0005f);
    249             TS_ASSERT_DELTA(harmonics[5] ,0.357070, 0.0005f);
    250             TS_ASSERT_DELTA(harmonics[6] ,0.096287, 0.0005f);
    251             TS_ASSERT_DELTA(harmonics[7] ,0.128685, 0.0005f);
    252             TS_ASSERT_DELTA(harmonics[8] ,0.003238, 0.0005f);
    253             TS_ASSERT_DELTA(harmonics[9] ,0.149376, 0.0005f);
    254             TS_ASSERT_DELTA(harmonics[10],0.063892, 0.0005f);
    255             TS_ASSERT_DELTA(harmonics[11],0.296716, 0.0005f);
    256             TS_ASSERT_DELTA(harmonics[12],0.051057, 0.0005f);
    257             TS_ASSERT_DELTA(harmonics[13],0.066310, 0.0005f);
    258             TS_ASSERT_DELTA(harmonics[14],0.004006, 0.0005f);
    259             TS_ASSERT_DELTA(harmonics[15],0.038662, 0.0005f);
    260 
    261             float sum = 0;
    262             for(int i=0; i<synth->oscilsize/2; ++i)
    263                 sum += harmonics[i];
    264             TS_ASSERT_DELTA(sum, 5.863001, 0.0005f);
    265 
    266             TS_ASSERT_DELTA(pars->getNhr(0), 0.000000, 0.0005f);
    267             TS_ASSERT_DELTA(pars->getNhr(1), 1.000000, 0.0005f);
    268             TS_ASSERT_DELTA(pars->getNhr(2), 2.000000, 0.0005f);
    269             TS_ASSERT_DELTA(pars->getNhr(3), 3.000000, 0.0005f);
    270             TS_ASSERT_DELTA(pars->getNhr(4), 4.000000, 0.0005f);
    271             TS_ASSERT_DELTA(pars->getNhr(5), 5.000000, 0.0005f);
    272             TS_ASSERT_DELTA(pars->getNhr(6), 6.000000, 0.0005f);
    273             TS_ASSERT_DELTA(pars->getNhr(7), 7.000000, 0.0005f);
    274             TS_ASSERT_DELTA(pars->getNhr(8), 8.000000, 0.0005f);
    275             TS_ASSERT_DELTA(pars->getNhr(9), 9.000000, 0.0005f);
    276 
    277         }
    278 
    279 #define OUTPUT_PROFILE
    280 #ifdef OUTPUT_PROFILE
    281         void testSpeed() {
    282             const int samps = 15000;
    283 
    284             int t_on = clock(); // timer before calling func
    285             for(int i = 0; i < samps; ++i)
    286                 note->noteout(outL, outR);
    287             int t_off = clock(); // timer when func returns
    288 
    289             printf("PadNoteTest: %f seconds for %d Samples to be generated.\n",
    290                    (static_cast<float>(t_off - t_on)) / CLOCKS_PER_SEC, samps);
    291         }
    292 #endif
    293 };
    294 
    295 int main()
    296 {
    297     PadNoteTest test;
    298     RUN_TEST(testDefaults);
    299     RUN_TEST(testInitialization);
    300     RUN_TEST(testSpeed);
    301     return test_summary();
    302 }