MAXIMILIAN
maximilian.h
1 /*
2 * platform independent synthesis library using portaudio or rtaudio
3  * maximilian.h
4  *
5  * Created by Mick Grierson on 29/12/2009.
6  * Copyright 2009 Mick Grierson & Strangeloop Limited. All rights reserved.
7  * Thanks to the Goldsmiths Creative Computing Team.
8  * Special thanks to Arturo Castro for the PortAudio implementation.
9  *
10  * Permission is hereby granted, free of charge, to any person
11  * obtaining a copy of this software and associated documentation
12  * files (the "Software"), to deal in the Software without
13  * restriction, including without limitation the rights to use,
14  * copy, modify, merge, publish, distribute, sublicense, and/or sell
15  * copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following
17  * conditions:
18  *
19  * The above copyright notice and this permission notice shall be
20  * included in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
24  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
29  * OTHER DEALINGS IN THE SOFTWARE.
30  *
31  */
32 
33 #ifndef MAXIMILIAN_H
34 #define MAXIMILIAN_H
35 
36 //#define MAXIMILIAN_PORTAUDIO
37 #define MAXIMILIAN_RT_AUDIO
38 
39 #include <iostream>
40 #include <fstream>
41 #include <string.h>
42 #include <cstdlib>
43 #include "math.h"
44 #include <cmath>
45 #include <vector>
46 #include <cfloat>
47 #ifdef _WIN32 //|| _WIN64
48 #include <algorithm>
49 #endif
50 #include <numeric>
51 
52 #ifdef ARDUINO
53 #include <limits>
54 #undef min
55 #undef max
56 #undef PI
57 #endif
58 
59 using namespace std;
60 #ifndef PI
61 #define PI 3.1415926535897932384626433832795
62 #endif
63 #define TWOPI 6.283185307179586476925286766559
64 
65 //transpiling some functions to Javascript?
66 #ifdef CHEERP
67 #define CHEERP_EXPORT [[cheerp::jsexport]]
68 #include <cheerp/clientlib.h>
69 #else
70 #define CHEERP_EXPORT
71 #endif
72 
73 //if using CHEERP, then convert incoming arrays to vectors inplace, otherwise, preserve the C++ vector interface
74 //see maxiIndex for a simple example
75 #ifdef CHEERP
76 
77 #define DOUBLEARRAY_REF client::Float64Array *
78 
79 #define DOUBLEARRAY client::Float64Array
80 
81 inline vector<double> convertArrayFromJS(DOUBLEARRAY_REF x)
82 {
83  double *__arrayStart = __builtin_cheerp_make_regular<double>(x, 0);
84  size_t __arrayLength = x->get_length();
85  return vector<double>(__arrayStart, __arrayStart + __arrayLength);
86 }
87 
88 #define NORMALISE_ARRAY_TYPE(invar, outvar) vector<double> outvar = convertArrayFromJS(invar);
89 
90 #else
91 
92 #define DOUBLEARRAY_REF vector<double> &
93 #define DOUBLEARRAY vector<double>
94 
95 #define NORMALISE_ARRAY_TYPE(invar, outvar) vector<double> outvar = vector<double>(invar.begin(), invar.end()); //emplace into new variable
96 
97 #endif
98 
99 const double pitchRatios[256] = {0.0006517771980725, 0.0006905338959768, 0.0007315951515920, 0.0007750981021672, 0.0008211878011934, 0.0008700182079338, 0.0009217521874234, 0.0009765623835847, 0.0010346318595111, 0.0010961542138830, 0.0011613349197432, 0.0012303915573284, 0.0013035543961450, 0.0013810677919537, 0.0014631903031841, 0.0015501962043345, 0.0016423756023869, 0.0017400364158675, 0.0018435043748468, 0.0019531247671694, 0.0020692637190223, 0.0021923084277660, 0.0023226698394865, 0.0024607831146568, 0.0026071087922901, 0.0027621355839074, 0.0029263808391988, 0.0031003924086690, 0.0032847514376044, 0.0034800728317350, 0.0036870087496936, 0.0039062497671694, 0.0041385274380445, 0.0043846168555319, 0.0046453396789730, 0.0049215662293136, 0.0052142175845802, 0.0055242711678147, 0.0058527616783977, 0.0062007848173380, 0.0065695028752089, 0.0069601456634700, 0.0073740174993873, 0.0078124995343387, 0.0082770548760891, 0.0087692337110639, 0.0092906802892685, 0.0098431324586272, 0.0104284351691604, 0.0110485423356295, 0.0117055233567953, 0.0124015696346760, 0.0131390057504177, 0.0139202913269401, 0.0147480349987745, 0.0156249990686774, 0.0165541097521782, 0.0175384692847729, 0.0185813605785370, 0.0196862649172544, 0.0208568722009659, 0.0220970865339041, 0.0234110467135906, 0.0248031392693520, 0.0262780115008354, 0.0278405826538801, 0.0294960699975491, 0.0312499981373549, 0.0331082195043564, 0.0350769385695457, 0.0371627211570740, 0.0393725298345089, 0.0417137444019318, 0.0441941730678082, 0.0468220934271812, 0.0496062822639942, 0.0525560230016708, 0.0556811690330505, 0.0589921437203884, 0.0624999962747097, 0.0662164390087128, 0.0701538771390915, 0.0743254423141479, 0.0787450596690178, 0.0834274888038635, 0.0883883461356163, 0.0936441868543625, 0.0992125645279884, 0.1051120460033417, 0.1113623380661011, 0.1179842874407768, 0.1249999925494194, 0.1324328780174255, 0.1403077542781830, 0.1486508846282959, 0.1574901193380356, 0.1668549776077271, 0.1767766922712326, 0.1872883737087250, 0.1984251290559769, 0.2102240920066833, 0.2227246761322021, 0.2359685748815536, 0.2500000000000000, 0.2648657560348511, 0.2806155085563660, 0.2973017692565918, 0.3149802684783936, 0.3337099552154541, 0.3535533845424652, 0.3745767772197723, 0.3968502581119537, 0.4204482138156891, 0.4454493522644043, 0.4719371497631073, 0.5000000000000000, 0.5297315716743469, 0.5612310171127319, 0.5946035385131836, 0.6299605369567871, 0.6674199104309082, 0.7071067690849304, 0.7491535544395447, 0.7937005162239075, 0.8408964276313782, 0.8908987045288086, 0.9438742995262146, 1.0000000000000000, 1.0594631433486938, 1.1224620342254639, 1.1892070770263672, 1.2599210739135742, 1.3348398208618164, 1.4142135381698608, 1.4983071088790894, 1.5874010324478149, 1.6817928552627563, 1.7817974090576172, 1.8877485990524292, 2.0000000000000000, 2.1189262866973877, 2.2449240684509277, 2.3784141540527344, 2.5198421478271484, 2.6696796417236328, 2.8284270763397217, 2.9966142177581787, 3.1748020648956299, 3.3635857105255127, 3.5635950565338135, 3.7754974365234375, 4.0000000000000000, 4.2378525733947754, 4.4898481369018555, 4.7568287849426270, 5.0396842956542969, 5.3393597602844238, 5.6568546295166016, 5.9932284355163574, 6.3496046066284180, 6.7271714210510254, 7.1271901130676270, 7.5509948730468750, 8.0000000000000000, 8.4757051467895508, 8.9796962738037109, 9.5136575698852539, 10.0793685913085938, 10.6787195205688477, 11.3137092590332031, 11.9864568710327148, 12.6992092132568359, 13.4543428421020508, 14.2543802261352539, 15.1019897460937500, 16.0000000000000000, 16.9514102935791016, 17.9593944549560547, 19.0273151397705078, 20.1587371826171875, 21.3574390411376953, 22.6274185180664062, 23.9729137420654297, 25.3984184265136719, 26.9086875915527344, 28.5087604522705078, 30.2039794921875000, 32.0000000000000000, 33.9028205871582031, 35.9187889099121094, 38.0546302795410156, 40.3174743652343750, 42.7148780822753906, 45.2548370361328125, 47.9458274841308594, 50.7968368530273438, 53.8173751831054688, 57.0175209045410156, 60.4079589843750000, 64.0000076293945312, 67.8056411743164062, 71.8375778198242188, 76.1092605590820312, 80.6349563598632812, 85.4297561645507812, 90.5096740722656250, 95.8916625976562500, 101.5936737060546875, 107.6347503662109375, 114.0350418090820312, 120.8159179687500000, 128.0000152587890625, 135.6112823486328125, 143.6751556396484375, 152.2185211181640625, 161.2699127197265625, 170.8595123291015625, 181.0193481445312500, 191.7833251953125000, 203.1873474121093750, 215.2695007324218750, 228.0700836181640625, 241.6318511962890625, 256.0000305175781250, 271.2225646972656250, 287.3503112792968750, 304.4370422363281250, 322.5398254394531250, 341.7190246582031250, 362.0386962890625000, 383.5666503906250000, 406.3746948242187500, 430.5390014648437500, 456.1401977539062500, 483.2637023925781250, 512.0000610351562500, 542.4451293945312500, 574.7006225585937500, 608.8740844726562500, 645.0796508789062500, 683.4380493164062500, 724.0773925781250000, 767.1333007812500000, 812.7494506835937500, 861.0780029296875000, 912.2803955078125000, 966.5274047851562500, 1024.0001220703125000, 1084.8903808593750000, 1149.4012451171875000, 1217.7481689453125000, 1290.1593017578125000, 1366.8762207031250000, 1448.1549072265625000, 1534.2666015625000000, 1625.4989013671875000};
100 
101 class CHEERP_EXPORT maxiSettings
102 {
103 public:
104  maxiSettings();
105  static int sampleRate;
106  static int channels;
107  static int bufferSize;
108  static void setup(int initSampleRate, int initChannels, int initBufferSize)
109  {
110  maxiSettings::sampleRate = initSampleRate;
111  maxiSettings::channels = initChannels;
112  maxiSettings::bufferSize = initBufferSize;
113  }
114  //
115  // static void setSampleRate(int sampleRate_){
116  // maxiSettings::sampleRate = sampleRate_;
117  // }
118  //
119  // static void setNumChannels(int channels_){
120  // maxiSettings::channels = channels_;
121  // }
122  //
123  // static void setBufferSize(int bufferSize_){
124  // maxiSettings::bufferSize = bufferSize_;
125  // }
126  //
127  static int getSampleRate()
128  {
129  return maxiSettings::sampleRate;
130  }
131  //
132  // static int getNumChannels() {
133  // return maxiSettings::channels;
134  // }
135  //
136  // static int getBufferSize() {
137  // return maxiSettings::bufferSize;
138  // }
139 };
140 
141 class CHEERP_EXPORT maxiOsc
142 {
143 
144  double frequency;
145  double phase;
146  double startphase;
147  double endphase;
148  double output;
149  double tri;
150 
151 public:
152  maxiOsc();
153  double sinewave(double frequency);
154  double coswave(double frequency);
155  double phasor(double frequency);
156  double phasorBetween(double frequency, double startphase, double endphase); //renamed to avoid overrides
157  double saw(double frequency);
158  double triangle(double frequency);
159  double square(double frequency);
160  double pulse(double frequency, double duty);
161  double impulse(double frequency);
162  double noise();
163  double sinebuf(double frequency);
164  double sinebuf4(double frequency);
165  double sawn(double frequency);
166  double rect(double frequency, double duty);
167  void phaseReset(double phaseIn);
168 };
169 
171 {
172 
173  double period;
174  double output;
175  double startval;
176  double currentval;
177  double nextval;
178  int isPlaying;
179 
180 public:
181  maxiEnvelope() {}
182  // double line(int numberofsegments,double segments[100]);
183  double line(int numberofsegments, std::vector<double> &segments);
184 
185  void trigger(int index, double amp);
186  int valindex;
187  double amplitude;
188 
189  // ------------------------------------------------
190  // getters/setters
191  void setValindex(int index)
192  {
193  valindex = index;
194  }
195 
196  void setAmplitude(double amp)
197  {
198  amplitude = amp;
199  }
200 
201  int getValindex() const
202  {
203  return valindex;
204  }
205 
206  double getAmplitude() const
207  {
208  return amplitude;
209  }
210  // ------------------------------------------------
211 };
212 
213 class CHEERP_EXPORT maxiDelayline
214 {
215  double frequency;
216  int phase;
217  double startphase;
218  double endphase;
219  double output;
220  double memory[88200 * 2];
221 
222 public:
223  maxiDelayline();
224  double dl(double input, int size, double feedback);
225  double dlFromPosition(double input, int size, double feedback, int position); //renamed to avoid overrides
226 };
227 
228 class CHEERP_EXPORT maxiFilter
229 {
230 private:
231  double gain;
232  double input;
233  double output;
234  double inputs[10];
235  double outputs[10];
236  double cutoff1;
237  double x; //speed
238  double y; //pos
239  double z; //pole
240  double c; //filter coefficient
241 
242 public:
243  maxiFilter();
244  double cutoff;
245  double resonance;
246  double lores(double input, double cutoff1, double resonance);
247  double hires(double input, double cutoff1, double resonance);
248  double bandpass(double input, double cutoff1, double resonance);
249  double lopass(double input, double cutoff);
250  double hipass(double input, double cutoff);
251 
252  // ------------------------------------------------
253  // getters/setters
254  void setCutoff(double cut)
255  {
256  cutoff = cut;
257  }
258 
259  void setResonance(double res)
260  {
261  resonance = res;
262  }
263 
264  double getCutoff()
265  {
266  return cutoff;
267  }
268 
269  double getResonance()
270  {
271  return resonance;
272  }
273  // ------------------------------------------------
274 };
275 
276 class maxiMix
277 {
278  double input;
279  double two[2];
280  double four[4];
281  double eight[8];
282 
283 public:
284  // double x;
285  // double y;
286  // double z;
287 
288  // ------------------------------------------------
289  // getters/setters
290 
291  // ------------------------------------------------
292 
293  // double *stereo(double input,double two[2],double x);
294  // double *quad(double input,double four[4], double x,double y);
295  // double *ambisonic(double input,double eight[8],double x,double y, double z);
296 
297  // should return or just be void function
298  void stereo(double input, std::vector<double> &two, double x);
299  void quad(double input, std::vector<double> &four, double x, double y);
300  void ambisonic(double input, std::vector<double> &eight, double x, double y, double z);
301 };
302 
303 //lagging with an exponential moving average
304 //a lower alpha value gives a slower lag
305 template <class T>
307 {
308 public:
309  T alpha, alphaReciprocal;
310  T val;
311 
312  maxiLagExp()
313  {
314  init(0.5, 0.0);
315  };
316 
317  maxiLagExp(T initAlpha, T initVal)
318  {
319  init(initAlpha, initVal);
320  }
321 
322  void init(T initAlpha, T initVal)
323  {
324  alpha = initAlpha;
325  alphaReciprocal = 1.0 - alpha;
326  val = initVal;
327  }
328 
329  inline void addSample(T newVal)
330  {
331  val = (alpha * newVal) + (alphaReciprocal * val);
332  }
333 
334  // getters/setters
335  void setAlpha(T alpha_)
336  {
337  alpha = alpha_;
338  }
339 
340  void setAlphaReciprocal(T alphaReciprocal_)
341  {
342  alphaReciprocal = alphaReciprocal_;
343  }
344 
345  void setVal(T val_)
346  {
347  val = val_;
348  }
349 
350  T getAlpha() const
351  {
352  return alpha;
353  }
354 
355  T getAlphaReciprocal() const
356  {
357  return alphaReciprocal;
358  }
359 
360  inline T value() const
361  {
362  return val;
363  }
364 };
365 
366 class CHEERP_EXPORT maxiTrigger
367 {
368 public:
369  maxiTrigger();
370  //zerocrossing
371  double onZX(double input)
372  {
373  double isZX = 0.0;
374  if ((previousValue <= 0.0 || firstTrigger) && input > 0)
375  {
376  isZX = 1.0;
377  }
378  previousValue = input;
379  firstTrigger = 0;
380  return isZX;
381  }
382 
383  //change detector
384  double onChanged(double input, double tolerance)
385  {
386  double changed = 0;
387  if (fabs(input - previousValue) > tolerance)
388  {
389  changed = 1;
390  }
391  previousValue = input;
392  return changed;
393  }
394 
395 private:
396  double previousValue = 1;
397  bool firstTrigger = 1;
398 };
399 
400 // class DualModeF64Array {
401 
402 // public:
403 // #ifdef CHEERP
404 // client::Float64Array *data = new client::Float64Array(1);
405 // #else
406 // std::vector<double> data;
407 // #endif
408 
409 // size_t size() {
410 // #ifdef CHEERP
411 // return data->get_length();
412 // #else
413 // return data.size();
414 // #endif
415 
416 // }
417 
418 // void clear() {
419 // #ifdef CHEERP
420 // data->fill(0);
421 // #else
422 // data.clear();
423 // #endif
424 
425 // }
426 
427 // #ifdef CHEERP
428 // void setFrom(client::Float64Array *newdata) {
429 // data = new client::Float64Array(newdata);
430 // }
431 // #else
432 // void setFrom(std::vector<double> &newdata) {
433 // data = newdata;
434 // }
435 // #endif
436 
437 
438 
439 // };
440 #ifdef CHEERP
441 #define DECLARE_F64_ARRAY(x) client::Float64Array *x = new client::Float64Array(1);
442 #define F64_ARRAY_SIZE(x) x->get_length()
443 #define F64_ARRAY_SETFROM(to,from) to = new client::Float64Array(from);
444 #define F64_ARRAY_CLEAR(x) x->fill(0);
445 #define F64_ARRAY_AT(x,i) (*x)[i]
446 #else
447 #define DECLARE_F64_ARRAY(x) std::vector<double> x;
448 #define F64_ARRAY_SIZE(x) x.size()
449 #define F64_ARRAY_SETFROM(to,from) to = from;
450 #define F64_ARRAY_CLEAR(x) x.clear();
451 #define F64_ARRAY_AT(x,i) x[i]
452 
453 #endif
454 
455 class CHEERP_EXPORT maxiSample
456 {
457 
458 private:
459  double position, recordPosition;
460  double speed;
461  double output;
462  maxiLagExp<double> loopRecordLag;
463  // DualModeF64Array test;
464 
465 public:
466 // // int myDataSize;
467  short myChannels;
468  int mySampleRate;
469  inline long getLength() { return F64_ARRAY_SIZE(amplitudes); };
470  // void setLength(unsigned long numSamples);
471  short myBitsPerSample;
472  maxiTrigger zxTrig;
473 
474 
475  DECLARE_F64_ARRAY(amplitudes);
476 
477  maxiSample();
478 
479 #ifndef CHEERP
480  maxiSample &operator=(const maxiSample &source)
481  {
482  if (this == &source)
483  return *this;
484  position = 0;
485  recordPosition = 0;
486  myChannels = source.myChannels;
487  mySampleRate = maxiSettings::sampleRate;
488  F64_ARRAY_SETFROM(amplitudes,source.amplitudes);
489  return *this;
490  }
491 
492  string myPath;
493  int myChunkSize;
494  int mySubChunk1Size;
495  int readChannel;
496  short myFormat;
497  int myByteRate;
498  short myBlockAlign;
499 
500  bool load(string fileName, int channel = 0);
501  bool save();
502  bool save(string filename);
503  // read a wav file into this class
504  bool read();
505 
506  // return a printable summary of the wav file
507  string getSummary();
508 
509 #endif
510 #ifdef VORBIS
511  bool loadOgg(string filename, int channel = 0);
512  int setSampleFromOggBlob(vector<unsigned char> &oggBlob, int channel = 0);
513 #endif
514  // -------------------------
515  bool isReady() {return F64_ARRAY_SIZE(amplitudes) > 1;}
516 
517  void setSample(DOUBLEARRAY_REF _sampleData)
518  {
519  // NORMALISE_ARRAY_TYPE(_sampleData, sampleData)
520  // amplitudes = sampleData;
521  F64_ARRAY_SETFROM(amplitudes, _sampleData);
522  // amplitudes.setFrom(_sampleData);
523  mySampleRate = 44100;
524  position = F64_ARRAY_SIZE(amplitudes) - 1;
525  }
526 
527  void setSampleAndRate(DOUBLEARRAY_REF _sampleData, int sampleRate)
528  {
529  setSample(_sampleData);
530  mySampleRate = sampleRate;
531  }
532 
533  void clear() { F64_ARRAY_CLEAR(amplitudes) }
534  // // -------------------------
535 
536  void trigger();
537 
538  void loopRecord(double newSample, const bool recordEnabled, const double recordMix, double start, double end)
539  {
540  loopRecordLag.addSample(recordEnabled);
541  if (recordPosition < start * F64_ARRAY_SIZE(amplitudes))
542  recordPosition = start * F64_ARRAY_SIZE(amplitudes);
543  if (recordEnabled)
544  {
545  double currentSample = F64_ARRAY_AT(amplitudes,(int)recordPosition) / 32767.0;
546  newSample = (recordMix * currentSample) + ((1.0 - recordMix) * newSample);
547  newSample *= loopRecordLag.value();
548  amplitudes[(unsigned long)recordPosition] = newSample * 32767;
549  }
550  ++recordPosition;
551  if (recordPosition >= end * F64_ARRAY_SIZE(amplitudes))
552  recordPosition = start * F64_ARRAY_SIZE(amplitudes);
553  }
554 
555  void reset() {position=0;}
556 
557  double play();
558 
559  double playLoop(double start, double end); // start and end are between 0.0 and 1.0
560 
561  double playOnce();
562  double playOnZX(double trigger);
563  double playOnZXAtSpeed(double trig, double speed); //API CHANGE
564  double playOnZXAtSpeedFromOffset(double trig, double speed, double offset); //API CHANGE
565  double playOnZXAtSpeedBetweenPoints(double trig, double speed, double offset, double length); //API CHANGE
566 
567  double loopSetPosOnZX(double trigger, double position); // position between 0 and 1.0
568 
569  double playOnceAtSpeed(double speed); //API CHANGE
570 
571  void setPosition(double newPos); // between 0.0 and 1.0
572 
573  double playUntil(double end);
574  double playUntilAtSpeed(double end, double speed);
575 
576  double playAtSpeed(double speed); //API CHANGE
577 
578  double playAtSpeedBetweenPointsFromPos(double frequency, double start, double end, double pos); //API CHANGE
579 
580  double playAtSpeedBetweenPoints(double frequency, double start, double end); //API CHANGE
581 
582  double play4(double frequency, double start, double end);
583 
584 
585  void normalise(double maxLevel); //0 < maxLevel < 1.0
586  void autoTrim(float alpha, float threshold, bool trimStart, bool trimEnd); //alpha of lag filter (lower == slower reaction), threshold to mark start and end, < 32767
587 };
588 
589 class CHEERP_EXPORT maxiMap
590 {
591 public:
592  maxiMap();
593  static double inline linlin(double val, double inMin, double inMax, double outMin, double outMax)
594  {
595  val = max(min(val, inMax), inMin);
596  return ((val - inMin) / (inMax - inMin) * (outMax - outMin)) + outMin;
597  }
598 
599  static double inline linexp(double val, double inMin, double inMax, double outMin, double outMax)
600  {
601  //clipping
602  val = max(min(val, inMax), inMin);
603  return pow((outMax / outMin), (val - inMin) / (inMax - inMin)) * outMin;
604  }
605 
606  static double inline explin(double val, double inMin, double inMax, double outMin, double outMax)
607  {
608  //clipping
609  val = max(min(val, inMax), inMin);
610  return (log(val / inMin) / log(inMax / inMin) * (outMax - outMin)) + outMin;
611  }
612 
613  //replacing the templated version
614  static double inline clamp(double v, const double low, const double high)
615  {
616  if (v > high)
617  {
618  v = high;
619  }
620  else if (v < low)
621  {
622  v = low;
623  }
624  return v;
625  }
626 };
627 
628 class maxiDyn
629 {
630 
631 public:
632  // double gate(double input, double threshold=0.9, long holdtime=1, double attack=1, double release=0.9995);
633  // double compressor(double input, double ratio, double threshold=0.9, double attack=1, double release=0.9995);
634  double gate(double input, double threshold = 0.9, long holdtime = 1, double attack = 1, double release = 0.9995);
635  double compressor(double input, double ratio, double threshold = 0.9, double attack = 1, double release = 0.9995);
636  double compress(double input);
637 
638  double input;
639  double ratio;
640  double currentRatio;
641  double threshold;
642  double output;
643  double attack;
644  double release;
645  double amplitude;
646 
647  void setAttack(double attackMS);
648  void setRelease(double releaseMS);
649  void setThreshold(double thresholdI);
650  void setRatio(double ratioF);
651  long holdtime;
652  long holdcount;
653  int attackphase, holdphase, releasephase;
654 
655  // ------------------------------------------------
656  // getters/setters
657  // int getTrigger() const{
658  // return trigger;
659  // }
660 
661  // void setTrigger(int trigger){
662  // this->trigger = trigger;
663  // }
664 
665  // ------------------------------------------------
666 };
667 
668 class maxiEnv
669 {
670 
671 public:
672  double ar(double input, double attack = 1, double release = 0.9, long holdtime = 1, int trigger = 0);
673  double adsr(double input, double attack = 1, double decay = 0.99, double sustain = 0.125, double release = 0.9, long holdtime = 1, int trigger = 0);
674  double adsr(double input, int trigger);
675  double input;
676  double output;
677  double attack;
678  double decay;
679  double sustain;
680  double release;
681  double amplitude;
682 
683  void setAttack(double attackMS);
684  void setRelease(double releaseMS);
685  void setDecay(double decayMS);
686  void setSustain(double sustainL);
687  int trigger;
688 
689  long holdtime = 1;
690  long holdcount;
691  int attackphase, decayphase, sustainphase, holdphase, releasephase;
692 
693  // ------------------------------------------------
694  // getters/setters
695  int getTrigger() const
696  {
697  return trigger;
698  }
699 
700  void setTrigger(int trigger)
701  {
702  this->trigger = trigger;
703  }
704 
705  // ------------------------------------------------
706 };
707 
708 class convert
709 {
710 public:
711  static double mtof(int midinote);
712 
713  static double msToSamps(double timeMs)
714  {
715  return timeMs / 1000.0 * maxiSettings::sampleRate;
716  }
717 };
718 
720 {
721 public:
722  inline double sah(double sigIn, double holdTimeMs)
723  {
724  double holdTimeSamples = convert::msToSamps(holdTimeMs);
725 
726  if (phase >= holdTimeSamples)
727  {
728  phase -= holdTimeSamples;
729  }
730  if (phase < 1.0)
731  holdValue = sigIn;
732  phase++;
733  return holdValue;
734  }
735 
736 private:
737  double phase = 0;
738  double holdValue = 0;
739  bool firstRun = 1;
740 };
741 
743 {
744 public:
746  inline bool zx(double x)
747  {
748  bool res = 0;
749  if (previous_x <= 0 && x > 0)
750  {
751  res = 1;
752  }
753  previous_x = x;
754  return res;
755  }
756 
757 private:
758  double previous_x = 0;
759 };
760 
761 //needs oversampling
762 class CHEERP_EXPORT maxiNonlinearity
763 {
764 public:
766  /*atan distortion, see http://www.musicdsp.org/showArchiveComment.php?ArchiveID=104*/
767  double atanDist(const double in, const double shape);
768  /*shape from 1 (soft clipping) to infinity (hard clipping)*/
769  double fastAtanDist(const double in, const double shape);
770  double softclip(double x);
771  double hardclip(double x);
772  //asymmetric clipping: chose the shape of curves for both positive and negative values of x
773  //try it here https://www.desmos.com/calculator/to6eixatsa
774  double asymclip(double x, double a, double b);
775  double fastatan(double x);
776 };
777 
778 inline double maxiNonlinearity::asymclip(double x, double a, double b)
779 {
780 
781  if (x >= 1)
782  {
783  x = 1;
784  }
785  else if (x <= -1)
786  {
787  x = -1;
788  }
789  else if (x < 0)
790  {
791  x = -(pow(-x, a));
792  }
793  else
794  {
795  x = pow(x, b);
796  }
797  return x;
798 }
799 
800 inline double maxiNonlinearity::hardclip(double x)
801 {
802  x = x >= 1 ? 1 : (x <= -1 ? -1 : x);
803  return x;
804 }
805 inline double maxiNonlinearity::softclip(double x)
806 {
807  if (x >= 1)
808  {
809  x = 1;
810  }
811  else if (x <= -1)
812  {
813  x = -1;
814  }
815  else
816  {
817  x = (2 / 3.0) * (x - pow(x, 3) / 3.0);
818  }
819  return x;
820 }
821 
822 inline double maxiNonlinearity::fastatan(double x)
823 {
824  return (x / (1.0 + 0.28 * (x * x)));
825 }
826 
827 inline double maxiNonlinearity::atanDist(const double in, const double shape)
828 {
829  double out;
830  out = (1.0 / atan(shape)) * atan(in * shape);
831  return out;
832 }
833 
834 inline double maxiNonlinearity::fastAtanDist(const double in, const double shape)
835 {
836  double out;
837  out = (1.0 / fastatan(shape)) * fastatan(in * shape);
838  return out;
839 }
840 
841 using maxiDistortion = maxiNonlinearity; // backwards compatibility
842 
844 {
845 public:
846  //delay = delay time - ~800 sounds good
847  //feedback = 0 - 1
848  //speed = lfo speed in Hz, 0.0001 - 10 sounds good
849  //depth = 0 - 1
850  double flange(const double input, const unsigned int delay, const double feedback, const double speed, const double depth);
851  maxiDelayline dl;
852  maxiOsc lfo;
853 };
854 
855 inline double maxiFlanger::flange(const double input, const unsigned int delay, const double feedback, const double speed, const double depth)
856 {
857  //todo: needs fixing
858  double output;
859  double lfoVal = lfo.triangle(speed);
860  output = dl.dl(input, delay + (lfoVal * depth * delay) + 1, feedback);
861  double normalise = (1 - fabs(output));
862  output *= normalise;
863  return (output + input) / 2.0;
864 }
865 
867 {
868 public:
869  //delay = delay time - ~800 sounds good
870  //feedback = 0 - 1
871  //speed = lfo speed in Hz, 0.0001 - 10 sounds good
872  //depth = 0 - 1
873  double chorus(const double input, const unsigned int delay, const double feedback, const double speed, const double depth);
874  maxiDelayline dl, dl2;
875  maxiOsc lfo;
876  maxiFilter lopass;
877 };
878 
879 inline double maxiChorus::chorus(const double input, const unsigned int delay, const double feedback, const double speed, const double depth)
880 {
881  //this needs fixing
882  double output1, output2;
883  double lfoVal = lfo.noise();
884  lfoVal = lopass.lores(lfoVal, speed, 1.0) * 2.0;
885  output1 = dl.dl(input, delay + (lfoVal * depth * delay) + 1, feedback);
886  output2 = dl2.dl(input, (delay + (lfoVal * depth * delay * 1.02) + 1) * 0.98, feedback * 0.99);
887  output1 *= (1.0 - fabs(output1));
888  output2 *= (1.0 - fabs(output2));
889  return (output1 + output2 + input) / 3.0;
890 }
891 
892 template <typename T>
894 {
895 public:
897  {
898  setAttack(100);
899  setRelease(100);
900  env = 0;
901  }
902  void setAttack(T attackMS)
903  {
904  attack = pow(0.01, 1.0 / (attackMS * maxiSettings::sampleRate * 0.001));
905  }
906  void setRelease(T releaseMS)
907  {
908  release = pow(0.01, 1.0 / (releaseMS * maxiSettings::sampleRate * 0.001));
909  }
910  inline T play(T input)
911  {
912  input = fabs(input);
913  if (input > env)
914  env = attack * (env - input) + input;
915  else
916  env = release * (env - input) + input;
917  return env;
918  }
919  void reset() { env = 0; }
920  inline T getEnv() { return env; }
921  inline void setEnv(T val) { env = val; }
922 
923 private:
924  T attack, release, env;
925 };
926 
929 
931 {
932 public:
933  double xm1, ym1;
934  maxiDCBlocker() : xm1(0), ym1(0) {}
935  inline double play(double input, double R)
936  {
937  ym1 = input - xm1 + R * ym1;
938  xm1 = input;
939  return ym1;
940  }
941 };
942 
943 /*
944  State Variable Filter
945 
946  algorithm from http://www.cytomic.com/files/dsp/SvfLinearTrapOptimised.pdf
947  usage:
948  either set the parameters separately as required (to save CPU)
949 
950  filter.setCutoff(param1);
951  filter.setResonance(param2);
952 
953  w = filter.play(w, 0.0, 1.0, 0.0, 0.0);
954 
955  or set everything together at once
956 
957  w = filter.setCutoff(param1).setResonance(param2).play(w, 0.0, 1.0, 0.0, 0.0);
958 
959  */
960 class maxiSVF
961 {
962 public:
963  maxiSVF() : v0z(0), v1(0), v2(0) { setParams(1000, 1); }
964 
965  //20 < cutoff < 20000
966  inline void setCutoff(double cutoff)
967  {
968  setParams(cutoff, res);
969  }
970 
971  //from 0 upwards, starts to ring from 2-3ish, cracks a bit around 10
972  inline void setResonance(double q)
973  {
974  setParams(freq, q);
975  }
976 
977  //run the filter, and get a mixture of lowpass, bandpass, highpass and notch outputs
978  inline double play(double w, double lpmix, double bpmix, double hpmix, double notchmix)
979  {
980  double low, band, high, notch;
981  double v1z = v1;
982  double v2z = v2;
983  double v3 = w + v0z - 2.0 * v2z;
984  v1 += g1 * v3 - g2 * v1z;
985  v2 += g3 * v3 + g4 * v1z;
986  v0z = w;
987  low = v2;
988  band = v1;
989  high = w - k * v1 - v2;
990  notch = w - k * v1;
991  return (low * lpmix) + (band * bpmix) + (high * hpmix) + (notch * notchmix);
992  }
993 
994 private:
995  inline void setParams(double _freq, double _res)
996  {
997  freq = _freq;
998  res = _res;
999  g = tan(PI * freq / maxiSettings::sampleRate);
1000  damping = res == 0 ? 0 : 1.0 / res;
1001  k = damping;
1002  ginv = g / (1.0 + g * (g + k));
1003  g1 = ginv;
1004  g2 = 2.0 * (g + k) * ginv;
1005  g3 = g * ginv;
1006  g4 = 2.0 * ginv;
1007  }
1008 
1009  double v0z, v1, v2, g, damping, k, ginv, g1, g2, g3, g4;
1010  double freq, res;
1011 };
1012 
1013 //based on http://www.earlevel.com/main/2011/01/02/biquad-formulas/ and https://ccrma.stanford.edu/~jos/fp/Direct_Form_II.html
1014 class CHEERP_EXPORT maxiBiquad
1015 {
1016 public:
1017  maxiBiquad();
1018  enum filterTypes
1019  {
1020  LOWPASS,
1021  HIGHPASS,
1022  BANDPASS,
1023  NOTCH,
1024  PEAK,
1025  LOWSHELF,
1026  HIGHSHELF
1027  };
1028  inline double play(double input)
1029  {
1030  v[0] = input - (b1 * v[1]) - (b2 * v[2]);
1031  double y = (a0 * v[0]) + (a1 * v[1]) + (a2 * v[2]);
1032  v[2] = v[1];
1033  v[1] = v[0];
1034  return y;
1035  }
1036  inline void set(filterTypes filtType, double cutoff, double Q, double peakGain)
1037  {
1038  double norm = 0;
1039  double V = pow(10.0, abs(peakGain) / 20.0);
1040  double K = tan(PI * cutoff / maxiSettings::sampleRate);
1041  switch (filtType)
1042  {
1043  case LOWPASS:
1044  norm = 1.0 / (1.0 + K / Q + K * K);
1045  a0 = K * K * norm;
1046  a1 = 2.0 * a0;
1047  a2 = a0;
1048  b1 = 2.0 * (K * K - 1.0) * norm;
1049  b2 = (1.0 - K / Q + K * K) * norm;
1050  break;
1051 
1052  case HIGHPASS:
1053  norm = 1. / (1. + K / Q + K * K);
1054  a0 = 1 * norm;
1055  a1 = -2 * a0;
1056  a2 = a0;
1057  b1 = 2 * (K * K - 1) * norm;
1058  b2 = (1 - K / Q + K * K) * norm;
1059  break;
1060 
1061  case BANDPASS:
1062  norm = 1. / (1. + K / Q + K * K);
1063  a0 = K / Q * norm;
1064  a1 = 0.;
1065  a2 = -a0;
1066  b1 = 2. * (K * K - 1.) * norm;
1067  b2 = (1. - K / Q + K * K) * norm;
1068  break;
1069 
1070  case NOTCH:
1071  norm = 1. / (1. + K / Q + K * K);
1072  a0 = (1. + K * K) * norm;
1073  a1 = 2. * (K * K - 1.) * norm;
1074  a2 = a0;
1075  b1 = a1;
1076  b2 = (1. - K / Q + K * K) * norm;
1077  break;
1078 
1079  case PEAK:
1080  if (peakGain >= 0.0)
1081  { // boost
1082  norm = 1. / (1. + 1. / Q * K + K * K);
1083  a0 = (1. + V / Q * K + K * K) * norm;
1084  a1 = 2. * (K * K - 1.) * norm;
1085  a2 = (1. - V / Q * K + K * K) * norm;
1086  b1 = a1;
1087  b2 = (1. - 1. / Q * K + K * K) * norm;
1088  }
1089  else
1090  { // cut
1091  norm = 1. / (1. + V / Q * K + K * K);
1092  a0 = (1. + 1 / Q * K + K * K) * norm;
1093  a1 = 2. * (K * K - 1) * norm;
1094  a2 = (1. - 1. / Q * K + K * K) * norm;
1095  b1 = a1;
1096  b2 = (1. - V / Q * K + K * K) * norm;
1097  }
1098  break;
1099  case LOWSHELF:
1100  if (peakGain >= 0.)
1101  { // boost
1102  norm = 1. / (1. + SQRT2 * K + K * K);
1103  a0 = (1. + sqrt(2. * V) * K + V * K * K) * norm;
1104  a1 = 2. * (V * K * K - 1.) * norm;
1105  a2 = (1. - sqrt(2. * V) * K + V * K * K) * norm;
1106  b1 = 2. * (K * K - 1.) * norm;
1107  b2 = (1. - SQRT2 * K + K * K) * norm;
1108  }
1109  else
1110  { // cut
1111  norm = 1. / (1. + sqrt(2. * V) * K + V * K * K);
1112  a0 = (1. + SQRT2 * K + K * K) * norm;
1113  a1 = 2. * (K * K - 1.) * norm;
1114  a2 = (1. - SQRT2 * K + K * K) * norm;
1115  b1 = 2. * (V * K * K - 1.) * norm;
1116  b2 = (1. - sqrt(2. * V) * K + V * K * K) * norm;
1117  }
1118  break;
1119  case HIGHSHELF:
1120  if (peakGain >= 0.)
1121  { // boost
1122  norm = 1. / (1. + SQRT2 * K + K * K);
1123  a0 = (V + sqrt(2. * V) * K + K * K) * norm;
1124  a1 = 2. * (K * K - V) * norm;
1125  a2 = (V - sqrt(2. * V) * K + K * K) * norm;
1126  b1 = 2. * (K * K - 1) * norm;
1127  b2 = (1. - SQRT2 * K + K * K) * norm;
1128  }
1129  else
1130  { // cut
1131  norm = 1. / (V + sqrt(2. * V) * K + K * K);
1132  a0 = (1. + SQRT2 * K + K * K) * norm;
1133  a1 = 2. * (K * K - 1.) * norm;
1134  a2 = (1. - SQRT2 * K + K * K) * norm;
1135  b1 = 2. * (K * K - V) * norm;
1136  b2 = (V - sqrt(2. * V) * K + K * K) * norm;
1137  }
1138  break;
1139  }
1140  }
1141 
1142 private:
1143  double a0 = 0, a1 = 0, a2 = 0, b1 = 0, b2 = 0;
1144  filterTypes filterType;
1145  const double SQRT2 = sqrt(2.0);
1146  double v[3] = {0, 0, 0};
1147 };
1148 
1150 {
1151 public:
1152  maxiXFade() {}
1153  static vector<double> xfade(vector<double> &ch1, vector<double> &ch2, double xfader)
1154  {
1155  xfader = maxiMap::clamp(xfader, -1, 1);
1156  double xfNorm = maxiMap::linlin(xfader, -1, 1, 0, 1);
1157  double gainCh1 = sqrt(1.0 - xfNorm);
1158  double gainCh2 = sqrt(xfNorm);
1159  vector<double> output(ch1.size(), 0.0);
1160  for (size_t i = 0; i < output.size(); i++)
1161  {
1162  output[i] = (ch1[i] * gainCh1) + (ch2[i] * gainCh2);
1163  }
1164  return output;
1165  }
1166  static double xfade(double ch1, double ch2, double xfader)
1167  {
1168  vector<double> vch1 = {ch1};
1169  vector<double> vch2 = {ch2};
1170  return maxiXFade::xfade(vch1, vch2, xfader)[0];
1171  }
1172 };
1173 
1175 {
1176 public:
1177  maxiLine() {}
1178  inline double play(double trigger)
1179  {
1180  if (!lineComplete)
1181  {
1182  if (trigEnable && !triggered)
1183  {
1184  triggered = (trigger > 0.0 && lastTrigVal <= 0.0);
1185  lineValue = lineStart;
1186  }
1187  if (triggered)
1188  {
1189  lineValue += inc;
1190  if (inc <= 0)
1191  {
1192  lineComplete = lineValue <= lineEnd;
1193  }
1194  else
1195  {
1196  lineComplete = lineValue >= lineEnd;
1197  }
1198  if (lineComplete)
1199  {
1200  if (!oneShot)
1201  {
1202  reset();
1203  }
1204  }
1205  }
1206  lastTrigVal = trigger;
1207  }
1208  return lineValue;
1209  }
1210  inline void prepare(double start, double end, double durationMs, bool isOneShot)
1211  {
1212  lineValue = lineStart;
1213  lineStart = start;
1214  lineEnd = end;
1215  double lineMag = end - start;
1216  double durInSamples = durationMs / 1000.0 * maxiSettings::sampleRate;
1217  inc = lineMag / durInSamples;
1218  oneShot = isOneShot;
1219  reset();
1220  }
1221  inline void triggerEnable(double on)
1222  {
1223  trigEnable = on > 0.0;
1224  }
1225  inline bool isLineComplete()
1226  {
1227  return lineComplete;
1228  }
1229 
1230 private:
1231  double phase = 0;
1232  double lineValue = 0;
1233  double inc = 0;
1234  double lastTrigVal = -1;
1235  double trigEnable = false;
1236  double triggered = false;
1237  bool lineComplete = false;
1238  double lineStart = 0;
1239  double lineEnd = 0;
1240  bool oneShot = 1;
1241  void reset()
1242  {
1243  triggered = false;
1244  lineComplete = false;
1245  }
1246 };
1247 
1249 {
1250 public:
1251  static double add(double x, double y)
1252  {
1253  return x + y;
1254  };
1255  static double div(double x, double y)
1256  {
1257  return x / y;
1258  };
1259  static double mul(double x, double y)
1260  {
1261  return x * y;
1262  };
1263  static double sub(double x, double y)
1264  {
1265  return x - y;
1266  };
1267  static double gt(double x, double y)
1268  {
1269  return x > y;
1270  }
1271  static double lt(double x, double y)
1272  {
1273  return x < y;
1274  }
1275  static double gte(double x, double y)
1276  {
1277  return x >= y;
1278  }
1279  static double lte(double x, double y)
1280  {
1281  return x <= y;
1282  }
1283  static double mod(double x, double y)
1284  {
1285  return fmod(x, y);
1286  }
1287  static double abs(double x)
1288  {
1289  return fabs(x);
1290  }
1291  static double xpowy(double x, double y)
1292  {
1293  return pow(x, y);
1294  }
1295 };
1296 
1297 //https://tutorials.siam.org/dsweb/cotutorial/index.php?s=3&p=0
1298 //https://www.complexity-explorables.org/explorables/ride-my-kuramotocycle/
1300 {
1301 public:
1303  inline double play(double freq, double K, std::vector<double> phases)
1304  {
1305 
1306  double phaseAdj = 0;
1307  for (double v : phases)
1308  {
1309  phaseAdj += sin(v - phase);
1310  }
1311  phase += dt * (freq + ((K / phases.size()) * phaseAdj));
1312  if (phase >= TWOPI)
1313  phase -= TWOPI;
1314  else if (phase < 0)
1315  phase += TWOPI;
1316  return phase;
1317  }
1318  inline void setPhase(double newPhase) { phase = newPhase; }
1319  inline double getPhase() { return phase; }
1320 
1321 private:
1322  double phase = 0.0;
1323  double dt = TWOPI / maxiSettings::sampleRate;
1324 };
1325 
1326 //a local group of oscillators
1328 {
1329 public:
1330  maxiKuramotoOscillatorSet(const size_t N)
1331  {
1332  oscs.resize(N);
1333  phases.resize(N);
1334  };
1335  void setPhases(const std::vector<double> &phases)
1336  {
1337  size_t iOsc = 0;
1338  for (double v : phases)
1339  {
1340  oscs[iOsc].setPhase(v);
1341  iOsc++;
1342  }
1343  }
1344 
1345  void setPhase(const double phase, const size_t oscillatorIdx)
1346  {
1347  oscs[oscillatorIdx].setPhase(phase);
1348  }
1349 
1350  double getPhase(size_t i)
1351  {
1352  return oscs[i].getPhase();
1353  }
1354 
1355  size_t size()
1356  {
1357  return oscs.size();
1358  }
1359 
1360  double play(double freq, double K)
1361  {
1362  double mix = 0.0;
1363  //gather phases
1364  for (size_t i = 0; i < phases.size(); i++)
1365  {
1366  phases[i] = oscs[i].getPhase();
1367  }
1368  for (auto &v : oscs)
1369  {
1370  mix += v.play(freq, K, phases);
1371  }
1372  return mix / phases.size();
1373  }
1374 
1375 protected:
1376  std::vector<maxiKuramotoOscillator> oscs;
1377  std::vector<double> phases;
1378 };
1379 
1380 //a single oscillator, updated according to phase information from remote oscillators
1381 //best guesses of the remote oscillators are maintained, and asynchronously updated
1382 //use case: a networked clock
1384 {
1385 public:
1386  //1 local oscillator and N-1 remote oscillators
1388 
1389  void setPhase(const double phase, const size_t oscillatorIdx)
1390  {
1391  oscs[oscillatorIdx].setPhase(phase);
1392  update = 1;
1393  }
1394  void setPhases(const std::vector<double> &phases)
1395  {
1396  size_t iOsc = 0;
1397  for (double v : phases)
1398  {
1399  oscs[iOsc].setPhase(v);
1400  iOsc++;
1401  }
1402  update = 1;
1403  }
1404 
1405  double play(double freq, double K)
1406  {
1407  double mix = 0.0;
1408  //gather phases
1409  if (update)
1410  {
1411  for (size_t i = 0; i < phases.size(); i++)
1412  {
1413  phases[i] = oscs[i].getPhase();
1414  }
1415  }
1416  for (auto &v : oscs)
1417  {
1418  mix += v.play(freq, update ? K : 0, phases);
1419  }
1420  update = 0;
1421  return mix / phases.size();
1422  }
1423 
1424  double getPhase(size_t i)
1425  {
1426  return maxiKuramotoOscillatorSet::getPhase(i);
1427  }
1428 
1429  size_t size()
1430  {
1431  return maxiKuramotoOscillatorSet::size();
1432  }
1433 
1434 private:
1435  bool update = 0;
1436 };
1437 
1439 {
1440 public:
1441  typedef uint32_t bitsig;
1442 
1443  // static bitsig sig(bitsig v) return v;
1444  // maxiBits() {}
1445  // maxiBits(const bitsig v) : t(v) {}
1446 
1447  static bitsig sig(bitsig v) { return v; }
1448 
1449  static bitsig at(const bitsig v, const bitsig idx)
1450  {
1451  return 1 & (v >> idx);
1452  }
1453  static bitsig shl(const bitsig v, const bitsig shift)
1454  {
1455  return v << shift;
1456  }
1457  static bitsig shr(const bitsig v, const bitsig shift)
1458  {
1459  return v >> shift;
1460  }
1461  static bitsig r(const bitsig v, const bitsig offset, const bitsig width)
1462  {
1463  bitsig mask = maxiBits::l(width);
1464  bitsig shift = offset - width + 1;
1465  bitsig x = 0;
1466  x = v & shl(mask, shift);
1467  x = x >> shift;
1468  return x;
1469  }
1470  static bitsig land(const bitsig v, const bitsig x)
1471  {
1472  return v & x;
1473  }
1474  static bitsig lor(const bitsig v, const bitsig x)
1475  {
1476  return v | x;
1477  }
1478  static bitsig lxor(const bitsig v, const bitsig x)
1479  {
1480  return v ^ x;
1481  }
1482  static bitsig neg(const bitsig v)
1483  {
1484  return ~v;
1485  }
1486  static bitsig inc(const bitsig v)
1487  {
1488  return v + 1;
1489  }
1490  static bitsig dec(const bitsig v)
1491  {
1492  return v - 1;
1493  }
1494  static bitsig add(const bitsig v, const bitsig m)
1495  {
1496  return v + m;
1497  }
1498  static bitsig sub(const bitsig v, const bitsig m)
1499  {
1500  return v - m;
1501  }
1502  static bitsig mul(const bitsig v, const bitsig m)
1503  {
1504  return v * m;
1505  }
1506  static bitsig div(const bitsig v, const bitsig m)
1507  {
1508  return v / m;
1509  }
1510  static bitsig gt(const bitsig v, const bitsig m)
1511  {
1512  return v > m;
1513  }
1514  static bitsig lt(const bitsig v, const bitsig m)
1515  {
1516  return v < m;
1517  }
1518  static bitsig gte(const bitsig v, const bitsig m)
1519  {
1520  return v >= m;
1521  }
1522  static bitsig lte(const bitsig v, const bitsig m)
1523  {
1524  return v <= m;
1525  }
1526  static bitsig eq(const bitsig v, const bitsig m)
1527  {
1528  return v == m;
1529  }
1530  static bitsig ct(const bitsig v, const bitsig width)
1531  {
1532  bitsig x = 0;
1533  for (size_t i = 0; i < width; i++)
1534  {
1535  x += (v & (1 << i)) > 0;
1536  }
1537  return x;
1538  }
1539  static bitsig l(const bitsig width)
1540  {
1541  bitsig v = 0;
1542  for (size_t i = 0; i < width; i++)
1543  {
1544  v += (1 << i);
1545  }
1546  return v;
1547  }
1548 
1549  static bitsig noise()
1550  {
1551  bitsig v = static_cast<bitsig>(rand());
1552  return v;
1553  }
1554 
1555  static double toSignal(const bitsig t)
1556  {
1557  return maxiMap::linlin(t, 0, (double)std::numeric_limits<uint32_t>::max(), -1, 1);
1558  }
1559 
1560  static double toTrigSignal(const bitsig t)
1561  {
1562  return t > 0 ? 1.0 : -1.0;
1563  }
1564 
1565  static bitsig fromSignal(const double t)
1566  {
1567  const bitsig halfRange = (std::numeric_limits<uint32_t>::max() / 2);
1568  const bitsig val = halfRange + (t * (halfRange - 1));
1569  return val;
1570  }
1571 
1572  // void sett(maxiBits::bitsig v){t=v;}
1573  // maxiBits::bitsig gett() const {return t;};
1574 
1575  // maxiBits::bitsig t=0;
1576 };
1577 
1579 {
1580 public:
1581  double count(double incTrigger, double resetTrigger)
1582  {
1583  if (inctrig.onZX(incTrigger))
1584  {
1585  value++;
1586  }
1587  if (rstrig.onZX(resetTrigger))
1588  {
1589  value = 0;
1590  }
1591  return value;
1592  }
1593 
1594 private:
1595  double value = 0;
1596  maxiTrigger inctrig, rstrig;
1597 };
1598 
1599 class CHEERP_EXPORT maxiIndex
1600 {
1601 public:
1602  maxiIndex();
1603  double pull(const double trigSig, double indexSig, DOUBLEARRAY_REF _values)
1604  {
1605  // double *__arrayStart = __builtin_cheerp_make_regular<double>(_values, 0);
1606  // size_t __arrayLength = _values->get_length();
1607  // vector<double> values = vector<double>(__arrayStart, __arrayStart + __arrayLength);
1608  NORMALISE_ARRAY_TYPE(_values, values)
1609  if (trig.onZX(trigSig))
1610  {
1611  if (indexSig < 0)
1612  indexSig = 0;
1613  if (indexSig > 1)
1614  indexSig = 1;
1615  size_t arrayIndex = static_cast<size_t>(floor(indexSig * 0.99999999 * values.size()));
1616  value = values[arrayIndex];
1617  }
1618  return value;
1619  }
1620 
1621 private:
1622  maxiTrigger trig;
1623  double value = 0;
1624 };
1625 
1626 class CHEERP_EXPORT maxiRatioSeq
1627 {
1628 public:
1629  maxiRatioSeq();
1630  double playTrig(double phase, DOUBLEARRAY_REF times)
1631  {
1632  // NORMALISE_ARRAY_TYPE(_times, times)
1633  double trig = 0;
1634  // double sum = std::accumulate(times.begin(), times.end(), 0);
1635  double sum=0;
1636  size_t seqlen = F64_ARRAY_SIZE(times);
1637  for(size_t i=0; i < seqlen; i++) sum += F64_ARRAY_AT(times,i);
1638  double accumulatedTime = 0;
1639  for (size_t i = 0; i < seqlen; i++)
1640  {
1641  accumulatedTime += F64_ARRAY_AT(times,i);
1642  double normalisedTime = accumulatedTime / sum;
1643  if (normalisedTime == 1.0)
1644  normalisedTime = 0.0;
1645  if (prevPhase > phase)
1646  {
1647  //wrapping point
1648  prevPhase = -1.0 / maxiSettings::sampleRate;
1649  }
1650  if ((prevPhase <= normalisedTime && phase > normalisedTime))
1651  {
1652  trig = 1;
1653  break;
1654  }
1655  }
1656  prevPhase = phase;
1657  return trig;
1658  }
1659 
1660  double playValues(double phase, DOUBLEARRAY_REF times, DOUBLEARRAY_REF values)
1661  {
1662  // NORMALISE_ARRAY_TYPE(_times, times)
1663  // NORMALISE_ARRAY_TYPE(_values, values)
1664  size_t vallen = F64_ARRAY_SIZE(values);
1665  if (lengthOfValues != vallen)
1666  {
1667  lengthOfValues = vallen;
1668  counter = lengthOfValues - 1;
1669  }
1670  if (playTrig(phase, times))
1671  {
1672  counter++;
1673  if (counter == vallen)
1674  {
1675  counter = 0;
1676  }
1677  }
1678  return F64_ARRAY_AT(values,counter);
1679  }
1680 
1681 private:
1682  double prevPhase = 0;
1683  size_t counter = 0;
1684  size_t lengthOfValues = 0;
1685 };
1686 
1687 #endif
Definition: maximilian.h:709
Definition: maximilian.h:1384
Definition: maximilian.h:1015
Definition: maximilian.h:1439
Definition: maximilian.h:867
Definition: maximilian.h:1579
Definition: maximilian.h:931
Definition: maximilian.h:214
Definition: maximilian.h:629
Definition: maximilian.h:669
Definition: maximilian.h:894
Definition: maximilian.h:171
Definition: maximilian.h:229
Definition: maximilian.h:844
Definition: maximilian.h:1600
Definition: maximilian.h:1300
Definition: maximilian.h:1328
Definition: maximilian.h:307
Definition: maximilian.h:1175
Definition: maximilian.h:590
Definition: maximilian.h:1249
Definition: maximilian.h:277
Definition: maximilian.h:763
Definition: maximilian.h:142
Definition: maximilian.h:1627
Definition: maximilian.h:961
Definition: maximilian.h:720
Definition: maximilian.h:456
Definition: maximilian.h:102
Definition: maximilian.h:367
Definition: maximilian.h:1150
Definition: maximilian.h:743