ref: 4fa07020d3c13de61a71d7d4730e059741935799
dir: /LEAF/Inc/leaf-utilities.h/
/* ============================================================================== LEAFUtilities.h Created: 20 Jan 2017 12:02:17pm Author: Michael R Mulshine ============================================================================== */ #ifndef LEAFUTILITIES_H_INCLUDED #define LEAFUTILITIES_H_INCLUDED #ifdef __cplusplus extern "C" { #endif // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ #include "leaf-globals.h" #include "leaf-math.h" #include "leaf-filter.h" #include "leaf-delay.h" // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // STACK implementation (fixed size) #define STACK_SIZE 128 typedef struct _tStack { int data[STACK_SIZE]; uint16_t pos; uint16_t size; uint16_t capacity; oBool ordered; } tStack; void tStack_init (tStack* const); void tStack_free (tStack* const); void tStack_setCapacity (tStack* const, uint16_t cap); int tStack_addIfNotAlreadyThere (tStack* const, uint16_t item); void tStack_add (tStack* const, uint16_t item); int tStack_remove (tStack* const, uint16_t item); void tStack_clear (tStack* const); int tStack_first (tStack* const); int tStack_getSize (tStack* const); int tStack_contains (tStack* const, uint16_t item); int tStack_next (tStack* const); int tStack_get (tStack* const, int which); // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /* Ramp */ typedef struct _tRamp { float inc; float inv_sr_ms; float minimum_time; float curr,dest; float time; int samples_per_tick; } tRamp; void tRamp_init (tRamp* const, float time, int samplesPerTick); void tRamp_free (tRamp* const); float tRamp_tick (tRamp* const); float tRamp_sample (tRamp* const); int tRamp_setTime (tRamp* const, float time); int tRamp_setDest (tRamp* const, float dest); int tRamp_setVal (tRamp* const, float val); // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /* Exponential Smoother */ typedef struct _tExpSmooth { float factor, oneminusfactor; float curr,dest; } tExpSmooth; void tExpSmooth_init (tExpSmooth* const, float val, float factor); void tExpSmooth_free (tExpSmooth* const); float tExpSmooth_tick (tExpSmooth* const); float tExpSmooth_sample (tExpSmooth* const); int tExpSmooth_setFactor (tExpSmooth* const, float factor); int tExpSmooth_setDest (tExpSmooth* const, float dest); int tExpSmooth_setVal (tExpSmooth* const, float val); // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /* PowerEnvelopeFollower */ typedef struct _tPwrFollow { float factor, oneminusfactor; float curr; } tPwrFollow; void tPwrFollow_init (tPwrFollow* const, float factor); void tPwrFollow_free (tPwrFollow* const); float tPwrFollow_tick (tPwrFollow* const, float input); float tPwrFollow_sample (tPwrFollow* const); int tPwrFollow_setFactor (tPwrFollow* const, float factor); // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //Reed Table - borrowed from STK typedef struct _tReedTable { float offset, slope; } tReedTable; void tReedTable_init (tReedTable* const, float offset, float slope); void tReedTable_free (tReedTable* const); float tReedTable_tick (tReedTable* const, float input); float tReedTable_tanh_tick (tReedTable* const p, float input); //tanh softclip version of reed table - replacing the hard clip in original stk code void tReedTable_setOffset (tReedTable* const, float offset); void tReedTable_setSlope (tReedTable* const, float slope); /// /* Feedback leveller */ // An auto VCA that you put into a feedback circuit to make it stay at the same level. // It can enforce level bidirectionally (amplifying and attenuating as needed) or // just attenutating. The former option allows for infinite sustain strings, for example, while // The latter option allows for decaying strings, which can never exceed // a specific level. typedef struct _tFBleveller { float targetLevel; // target power level float strength; // how strongly level difference affects the VCA int mode; // 0 for upwards limiting only, 1 for biderctional limiting float curr; tPwrFollow pwrFlw; // internal power follower needed for level tracking } tFBleveller; void tFBleveller_init (tFBleveller* const, float targetLevel, float factor, float strength, int mode); void tFBleveller_free (tFBleveller* const); float tFBleveller_tick (tFBleveller* const, float input); float tFBleveller_sample (tFBleveller* const); int tFBleveller_setTargetLevel (tFBleveller* const, float TargetLevel); int tFBleveller_setFactor (tFBleveller* const, float factor); int tFBleveller_setMode (tFBleveller* const, int mode); // 0 for upwards limiting only, 1 for biderctional limiting int tFBleveller_setStrength (tFBleveller* const, float strength); // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /* Simple Living String */ typedef struct _tSimpleLivingString { float freq, waveLengthInSamples; // the frequency of the string, determining delay length float dampFreq; // frequency for the bridge LP filter, in Hz float decay; // amplitude damping factor for the string (only active in mode 0) float levMode; float curr; tDelayL delayLine; tOnePole bridgeFilter; tHighpass DCblocker; tFBleveller fbLev; tExpSmooth wlSmooth; } tSimpleLivingString; void tSimpleLivingString_init (tSimpleLivingString* const, float freq, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode); void tSimpleLivingString_free (tSimpleLivingString* const); float tSimpleLivingString_tick (tSimpleLivingString* const, float input); float tSimpleLivingString_sample (tSimpleLivingString* const); int tSimpleLivingString_setFreq (tSimpleLivingString* const, float freq); int tSimpleLivingString_setWaveLength (tSimpleLivingString* const, float waveLength); // in samples int tSimpleLivingString_setDampFreq (tSimpleLivingString* const, float dampFreq); int tSimpleLivingString_setDecay (tSimpleLivingString* const, float decay); // should be near 1.0 int tSimpleLivingString_setTargetLev (tSimpleLivingString* const, float targetLev); int tSimpleLivingString_setLevSmoothFactor (tSimpleLivingString* const, float levSmoothFactor); int tSimpleLivingString_setLevStrength (tSimpleLivingString* const, float levStrength); int tSimpleLivingString_setLevMode (tSimpleLivingString* const, int levMode); // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /* Living String */ typedef struct _tLivingString { float freq, waveLengthInSamples; // the frequency of the whole string, determining delay length float pickPos; // the pick position, dividing the string in two, in ratio float prepIndex; // the amount of pressure on the pickpoint of the string (near 0=soft obj, near 1=hard obj) float dampFreq; // frequency for the bridge LP filter, in Hz float decay; // amplitude damping factor for the string (only active in mode 0) float levMode; float curr; tDelayL delLF,delUF,delUB,delLB; // delay for lower/upper/forward/backward part of the waveguide model tOnePole bridgeFilter, nutFilter, prepFilterU, prepFilterL; tHighpass DCblockerL, DCblockerU; tFBleveller fbLevU, fbLevL; tExpSmooth wlSmooth, ppSmooth; } tLivingString; void tLivingString_init (tLivingString* const, float freq, float pickPos, float prepIndex, float dampFreq, float decay, float targetLev, float levSmoothFactor, float levStrength, int levMode); void tLivingString_free (tLivingString* const); float tLivingString_tick (tLivingString* const, float input); float tLivingString_sample (tLivingString* const); int tLivingString_setFreq (tLivingString* const, float freq); int tLivingString_setWaveLength (tLivingString* const, float waveLength); // in samples int tLivingString_setPickPos (tLivingString* const, float pickPos); int tLivingString_setPrepIndex (tLivingString* const, float prepIndex); int tLivingString_setDampFreq (tLivingString* const, float dampFreq); int tLivingString_setDecay (tLivingString* const, float decay); // should be near 1.0 int tLivingString_setTargetLev (tLivingString* const, float targetLev); int tLivingString_setLevSmoothFactor (tLivingString* const, float levSmoothFactor); int tLivingString_setLevStrength (tLivingString* const, float levStrength); int tLivingString_setLevMode (tLivingString* const, int levMode); // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /* Compressor */ typedef struct _tCompressor { float tauAttack, tauRelease; float T, R, W, M; // Threshold, compression Ratio, decibel Width of knee transition, decibel Make-up gain float x_G[2], y_G[2], x_T[2], y_T[2]; oBool isActive; }tCompressor; void tCompressor_init (tCompressor* const); void tCompressor_free (tCompressor* const); float tCompressor_tick (tCompressor* const, float input); // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /* Attack-Decay envelope */ typedef struct _tEnvelope { const float *exp_buff; const float *inc_buff; uint32_t buff_size; float next; float attackInc, decayInc, rampInc; oBool inAttack, inDecay, inRamp; oBool loop; float gain, rampPeak; float attackPhase, decayPhase, rampPhase; } tEnvelope; void tEnvelope_init (tEnvelope* const, float attack, float decay, oBool loop); void tEnvelope_free (tEnvelope* const); float tEnvelope_tick (tEnvelope* const); int tEnvelope_setAttack (tEnvelope* const, float attack); int tEnvelope_setDecay (tEnvelope* const, float decay); int tEnvelope_loop (tEnvelope* const, oBool loop); int tEnvelope_on (tEnvelope* const, float velocity); // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /* ADSR */ typedef struct _tADSR { const float *exp_buff; const float *inc_buff; uint32_t buff_size; float next; float attackInc, decayInc, releaseInc, rampInc; oBool inAttack, inDecay, inSustain, inRelease, inRamp; float sustain, gain, rampPeak, releasePeak; float attackPhase, decayPhase, releasePhase, rampPhase; } tADSR; void tADSR_init (tADSR* const, float attack, float decay, float sustain, float release); void tADSR_free (tADSR* const); float tADSR_tick (tADSR* const); int tADSR_setAttack (tADSR* const, float attack); int tADSR_setDecay (tADSR* const, float decay); int tADSR_setSustain(tADSR* const, float sustain); int tADSR_setRelease(tADSR* const, float release); int tADSR_on (tADSR* const, float velocity); int tADSR_off (tADSR* const); // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /* Envelope Follower */ typedef struct _tEnvelopeFollower { float y; float a_thresh; float d_coeff; } tEnvelopeFollower; void tEnvelopeFollower_init (tEnvelopeFollower* const, float attackThreshold, float decayCoeff); void tEnvelopeFollower_free (tEnvelopeFollower* const); float tEnvelopeFollower_tick (tEnvelopeFollower* const, float x); int tEnvelopeFollower_decayCoeff (tEnvelopeFollower* const, float decayCoeff); int tEnvelopeFollower_attackThresh (tEnvelopeFollower* const, float attackThresh); // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ /* tAtkDtk */ #define DEFBLOCKSIZE 1024 #define DEFTHRESHOLD 6 #define DEFATTACK 10 #define DEFRELEASE 10 typedef struct _tAtkDtk { float env; //Attack & Release times in msec int atk; int rel; //Attack & Release coefficients based on times float atk_coeff; float rel_coeff; int blocksize; int samplerate; //RMS amplitude of previous block - used to decide if attack is present float prevAmp; float threshold; } tAtkDtk; void tAtkDtk_init (tAtkDtk* const, int blocksize); void tAtkDtk_init_expanded (tAtkDtk* const, int blocksize, int atk, int rel); void tAtkDtk_free (tAtkDtk* const); // set expected input blocksize void tAtkDtk_setBlocksize (tAtkDtk* const, int size); // change atkDetector sample rate void tAtkDtk_setSamplerate (tAtkDtk* const, int inRate); // set attack time and coeff void tAtkDtk_setAtk (tAtkDtk* const, int inAtk); // set release time and coeff void tAtkDtk_setRel (tAtkDtk* const, int inRel); // set level above which values are identified as attacks void tAtkDtk_setThreshold (tAtkDtk* const, float thres); // find largest transient in input block, return index of attack int tAtkDtk_detect (tAtkDtk* const, float *in); // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ // ENV~ from PD, modified for LEAF #define MAXOVERLAP 32 #define INITVSTAKEN 64 typedef struct _tEnv { float buf[ENV_WINDOW_SIZE + INITVSTAKEN]; uint16_t x_phase; /* number of points since last output */ uint16_t x_period; /* requested period of output */ uint16_t x_realperiod; /* period rounded up to vecsize multiple */ uint16_t x_npoints; /* analysis window size in samples */ float x_result; /* result to output */ float x_sumbuf[MAXOVERLAP]; /* summing buffer */ float x_f; uint16_t windowSize, hopSize, blockSize; uint16_t x_allocforvs; /* extra buffer for DSP vector size */ } tEnv; void tEnv_init (tEnv* const, int windowSize, int hopSize, int blockSize); void tEnv_free (tEnv* const); float tEnv_tick (tEnv* const); void tEnv_processBlock (tEnv* const, float* in); // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ #ifdef __cplusplus } #endif #endif // LEAFUTILITIES_H_INCLUDED