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, µtonal, &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 }