zynaddsubfx

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

InstrumentStats.cpp (10610B)


      1 /*
      2   ZynAddSubFX - a software synthesizer
      3 
      4   InstrumentStats.cpp - Instrument Profiler and Regression Tester
      5   Copyright (C) 2016 Mark McCurry
      6 
      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 #include <cmath>
     13 #include <cstdlib>
     14 #include <iostream>
     15 #include <fstream>
     16 #include <string>
     17 #include "../Misc/Time.h"
     18 #include "../Misc/Sync.h"
     19 #include "../Misc/MiddleWare.h"
     20 #include "../Misc/Part.h"
     21 #include "../Misc/Util.h"
     22 #include "../Misc/Allocator.h"
     23 #include "../Misc/Microtonal.h"
     24 #include "../DSP/FFTwrapper.h"
     25 #include "../globals.h"
     26 
     27 #include "../Effects/EffectMgr.h"
     28 #include "../Params/LFOParams.h"
     29 #include "../Params/EnvelopeParams.h"
     30 #include "../Params/ADnoteParameters.h"
     31 #include "../Params/PADnoteParameters.h"
     32 #include "../Params/SUBnoteParameters.h"
     33 using namespace std;
     34 using namespace zyn;
     35 
     36 SYNTH_T *synth;
     37 AbsTime *time_;
     38 Sync *sync_;
     39 
     40 char *instance_name=(char*)"";
     41 MiddleWare *middleware;
     42 
     43 enum RunMode {
     44     MODE_PROFILE,
     45     MODE_TEST,
     46 };
     47 
     48 RunMode mode;
     49 
     50 int compress = 0;
     51 float *outL, *outR;
     52 Alloc      alloc;
     53 Microtonal microtonal(compress);
     54 FFTwrapper fft(1024);
     55 Part *p;
     56 
     57 double tic()
     58 {
     59     timespec ts;
     60     // clock_gettime(CLOCK_MONOTONIC, &ts); // Works on FreeBSD
     61     clock_gettime(CLOCK_REALTIME, &ts);
     62     double t = ts.tv_sec;
     63     t += 1e-9*ts.tv_nsec;
     64     return t;
     65 }
     66 
     67 double toc()
     68 {
     69     return tic();
     70 }
     71 
     72 int interp=1;
     73 void setup() {
     74     synth = new SYNTH_T;
     75     synth->buffersize = 256;
     76     synth->samplerate = 48000;
     77     synth->alias();
     78     time_ = new AbsTime(*synth);
     79     sync_ = new Sync();
     80     //for those patches that are just really big
     81     alloc.addMemory(malloc(1024*1024),1024*1024);
     82 
     83     outL  = new float[1024];
     84     for(int i = 0; i < synth->buffersize; ++i)
     85         outL[i] = 0.0f;
     86     outR = new float[1024];
     87     for(int i = 0; i < synth->buffersize; ++i)
     88         outR[i] = 0.0f;
     89 
     90     p = new Part(alloc, *synth, *time_, sync_, compress, interp, &microtonal, &fft);
     91 }
     92 
     93 void xml(string s)
     94 {
     95     double t_on = tic();
     96     p->loadXMLinstrument(s.c_str());
     97     double t_off = toc();
     98     if(mode == MODE_PROFILE)
     99         printf("%f, ", t_off - t_on);
    100 }
    101 
    102 void load()
    103 {
    104     double t_on = tic();
    105     p->applyparameters();
    106     p->initialize_rt();
    107     double t_off = toc();
    108     if(mode == MODE_PROFILE)
    109         printf("%f, ", t_off - t_on);
    110 }
    111 
    112 void noteOn()
    113 {
    114     int total_notes = 0;
    115     double t_on = tic(); // timer before calling func
    116     for(int i=40; i<100; ++i)
    117         total_notes += p->NoteOn(i,100,0);
    118     double t_off = toc(); // timer when func returns
    119     printf("%d, ", total_notes);
    120     if(mode == MODE_PROFILE)
    121         printf("%f, ", t_off - t_on);
    122 }
    123 
    124 void speed()
    125 {
    126     const int samps = 150;
    127 
    128     double t_on = tic(); // timer before calling func
    129     for(int i = 0; i < samps; ++i) {
    130         p->ComputePartSmps();
    131         if(mode==MODE_TEST)
    132             printf("%f, %f, ", p->partoutl[0], p->partoutr[0]);
    133     }
    134     double t_off = toc(); // timer when func returns
    135 
    136     if(mode==MODE_PROFILE)
    137         printf("%f, %d, ", t_off - t_on, samps*synth->buffersize);
    138 }
    139 
    140 void noteOff()
    141 {
    142     double t_on = tic(); // timer before calling func
    143     p->AllNotesOff();
    144     p->ComputePartSmps();
    145     double t_off = toc(); // timer when func returns
    146     if(mode == MODE_PROFILE)
    147         printf("%f, ", t_off - t_on);
    148 }
    149 
    150 void memUsage()
    151 {
    152     if(mode == MODE_PROFILE)
    153         printf("%lld", alloc.totalAlloced());
    154 }
    155 
    156 /*
    157  *  Kit fields used
    158  *
    159  *  Kit type
    160  *
    161  *  Add synth engines used
    162  *    Add synth voices  used
    163  *  Sub synth engines used
    164  *  Pad synth engines used
    165  *
    166  *
    167  *  Total Envelopes
    168  *  Optional Envelopes
    169  *
    170  *  Total Free mode Envelopes
    171  *
    172  *  Total LFO
    173  *  Optional LFO
    174  *
    175  *  Total Filters
    176  *
    177  *  Total 'Analog' Filters
    178  *  Total SVF Filters
    179  *  Total Formant Filters
    180  *
    181  *  Total Effects
    182  */
    183 void usage_stats(void)
    184 {
    185     int kit_type        = 0;
    186     int kits_used       = 0;
    187     int add_engines     = 0;
    188     int add_voices      = 0;
    189     int sub_engines     = 0;
    190     int pad_engines     = 0;
    191 
    192     int env_total       = 0;
    193     int env_optional    = 0;
    194     int env_free        = 0;
    195 
    196     int lfo_total       = 0;
    197     int lfo_optional    = 0;
    198 
    199     int filter_total    = 0;
    200     int filter_analog   = 0;
    201     int filter_svf      = 0;
    202     int filter_formant  = 0;
    203 
    204     int effects_total   = 0;
    205 
    206     kit_type = p->Pkitmode;
    207     for(int i=0; i<NUM_KIT_ITEMS; ++i) {
    208         auto &k = p->kit[i];
    209         if(!(k.Penabled || (i==0 && p->Pkitmode == 0l)))
    210             continue;
    211 
    212         if(k.Padenabled) {
    213             auto &e = *k.adpars;
    214             add_engines += 1;
    215             for(int j=0; j<NUM_VOICES; ++j) {
    216                 auto &v = k.adpars->VoicePar[j];
    217                 if(!v.Enabled)
    218                     continue;
    219                 add_voices += 1;
    220                 if(v.PFilterEnabled) {
    221                     auto &f = *v.VoiceFilter;
    222                     filter_total += 1;
    223                     if(f.Pcategory == 0)
    224                         filter_analog += 1;
    225                     else if(f.Pcategory == 1)
    226                         filter_formant += 1;
    227                     else
    228                         filter_svf += 1;
    229                 }
    230                 if(v.PFreqLfoEnabled && v.FreqLfo->Pintensity) {
    231                     lfo_optional += 1;
    232                     lfo_total    += 1;
    233                 }
    234                 if(v.PFilterLfoEnabled && v.FilterLfo->Pintensity) {
    235                     lfo_optional += 1;
    236                     lfo_total    += 1;
    237                 }
    238                 if(v.PAmpLfoEnabled && v.AmpLfo->Pintensity) {
    239                     lfo_optional += 1;
    240                     lfo_total    += 1;
    241                 }
    242                 if(v.PFreqEnvelopeEnabled) {
    243                     env_optional += 1;
    244                     env_total    += 1;
    245                     env_free += !!v.FreqEnvelope->Pfreemode;
    246                 }
    247                 if(v.PFilterEnvelopeEnabled) {
    248                     env_optional += 1;
    249                     env_total    += 1;
    250                     env_free += !!v.FilterEnvelope->Pfreemode;
    251                 }
    252                 if(v.PAmpEnvelopeEnabled) {
    253                     env_optional += 1;
    254                     env_total    += 1;
    255                     env_free += !!v.AmpEnvelope->Pfreemode;
    256                 }
    257             }
    258 
    259 
    260 
    261             if(e.GlobalPar.GlobalFilter) {
    262                 auto &f = *e.GlobalPar.GlobalFilter;
    263                 filter_total += 1;
    264                 if(f.Pcategory == 0)
    265                     filter_analog += 1;
    266                 else if(f.Pcategory == 1)
    267                     filter_formant += 1;
    268                 else
    269                     filter_svf += 1;
    270             }
    271             if(e.GlobalPar.FreqLfo->Pintensity)
    272                 lfo_total += 1;
    273             if(e.GlobalPar.FilterLfo->Pintensity)
    274                 lfo_total += 1;
    275             if(e.GlobalPar.AmpLfo->Pintensity)
    276                 lfo_total += 1;
    277             env_total += 3;
    278             env_free += !!e.GlobalPar.FreqEnvelope->Pfreemode;
    279             env_free += !!e.GlobalPar.FilterEnvelope->Pfreemode;
    280             env_free += !!e.GlobalPar.AmpEnvelope->Pfreemode;
    281         }
    282 
    283         if(k.Ppadenabled) {
    284             pad_engines += 1;
    285             auto &e = *k.padpars;
    286             if(e.GlobalFilter) {
    287                 auto &f = *e.GlobalFilter;
    288                 filter_total += 1;
    289                 if(f.Pcategory == 0)
    290                     filter_analog += 1;
    291                 else if(f.Pcategory == 1)
    292                     filter_formant += 1;
    293                 else
    294                     filter_svf += 1;
    295             }
    296             if(e.FreqLfo->Pintensity)
    297                 lfo_total += 1;
    298             if(e.FilterLfo->Pintensity)
    299                 lfo_total += 1;
    300             if(e.AmpLfo->Pintensity)
    301                 lfo_total += 1;
    302             env_total += 3;
    303             env_free += !!e.FreqEnvelope->Pfreemode;
    304             env_free += !!e.FilterEnvelope->Pfreemode;
    305             env_free += !!e.AmpEnvelope->Pfreemode;
    306         }
    307 
    308         if(k.Psubenabled) {
    309             sub_engines += 1;
    310             auto &e = *k.subpars;
    311 
    312             if(e.PGlobalFilterEnabled) {
    313                 auto &f = *e.GlobalFilter;
    314                 filter_total += 1;
    315                 if(f.Pcategory == 0)
    316                     filter_analog += 1;
    317                 else if(f.Pcategory == 1)
    318                     filter_formant += 1;
    319                 else
    320                     filter_svf += 1;
    321             }
    322             if(e.PFreqEnvelopeEnabled) {
    323                 env_total += 1;
    324                 env_optional += 1;
    325                 env_free  += !!e.FreqEnvelope->Pfreemode;
    326             }
    327             if(e.PGlobalFilterEnabled) {
    328                 env_total += 1;
    329                 env_optional += 1;
    330                 env_free  += !!e.GlobalFilterEnvelope->Pfreemode;
    331             }
    332             if(e.PBandWidthEnvelopeEnabled) {
    333                 env_total += 1;
    334                 env_optional += 1;
    335                 env_free  += !!e.BandWidthEnvelope->Pfreemode;
    336             }
    337         }
    338 
    339         kits_used += 1;
    340     }
    341 
    342     for(int i=0; i<NUM_PART_EFX; ++i) {
    343         if(p->partefx[i]->efx)
    344             effects_total += 1;
    345     }
    346 
    347     printf("Kit type:       %d\n", kit_type);
    348     printf("Kits used:      %d\n", kits_used);
    349     printf("Add engines:    %d\n", add_engines);
    350     printf("    Add voices:    %d\n", add_voices);
    351     printf("Sub engines:    %d\n", sub_engines);
    352     printf("Pad engines:    %d\n", pad_engines);
    353 
    354     printf("\n");
    355 
    356     printf("Env total:      %d\n", env_total);
    357     printf("Env optional:   %d\n", env_optional);
    358     printf("Env free:       %d\n", env_free);
    359 
    360     printf("\n");
    361 
    362     printf("LFO total:      %d\n", lfo_total);
    363     printf("LFO optional:   %d\n", lfo_optional);
    364 
    365     printf("\n");
    366 
    367     printf("Filter total:   %d\n", filter_total);
    368     printf("Filter analog:  %d\n", filter_analog);
    369     printf("Filter svf:     %d\n", filter_svf);
    370     printf("Filter formant: %d\n", filter_formant);
    371 
    372     printf("\n");
    373 
    374     printf("Effects Total:  %d\n", effects_total);
    375 }
    376 
    377 int main(int argc, char **argv)
    378 {
    379     if(argc < 2) {
    380         fprintf(stderr, "Please supply a xiz file\n");
    381         return 1;
    382     }
    383     if(argc == 2) {
    384         mode = MODE_PROFILE;
    385         setup();
    386         xml(argv[1]);
    387         load();
    388         memUsage();
    389         printf(", ");
    390         noteOn();
    391         speed();
    392         noteOff();
    393         memUsage();
    394         printf("\n");
    395     } else if(argc == 3) {
    396         mode = MODE_TEST;
    397         setup();
    398         xml(argv[2]);
    399         load();
    400         usage_stats();
    401     }
    402 }