ref: 8b254651676c1c577ecc1bacf05470e61258476a
parent: 62e2951b664a111eb7f82de959e5c1ee8466cd75
author: Matthew Wang <mjw7@princeton.edu>
date: Thu Feb 25 08:48:20 EST 2021
add set sample rate function to all object that depend on sample rate
--- a/leaf/Inc/leaf-analysis.h
+++ b/leaf/Inc/leaf-analysis.h
@@ -364,8 +364,8 @@
float atk_coeff;
float rel_coeff;
- int blocksize;
- int samplerate;
+ int blockSize;
+ int sampleRate;
//RMS amplitude of previous block - used to decide if attack is present
float prevAmp;
@@ -385,6 +385,7 @@
void tAttackDetection_setRelease (tAttackDetection* const, int inRel);
void tAttackDetection_setThreshold (tAttackDetection* const, float thres);
int tAttackDetection_detect (tAttackDetection* const, float *in);
+ void tAttackDetection_setSampleRate (tAttackDetection* const, float sr);
//==============================================================================
@@ -593,6 +594,7 @@
float alpha;
float tolerance;
+ float invSampleRate;
} _tPeriodDetection;
typedef _tPeriodDetection* tPeriodDetection;
@@ -603,12 +605,13 @@
float tPeriodDetection_tick (tPeriodDetection* const, float sample);
float tPeriodDetection_getPeriod (tPeriodDetection* const);
- float tPeriodDetection_getFidelity (tPeriodDetection* pd);
+ float tPeriodDetection_getFidelity (tPeriodDetection* const);
void tPeriodDetection_setHopSize (tPeriodDetection* const, int hs);
void tPeriodDetection_setWindowSize (tPeriodDetection* const, int ws);
void tPeriodDetection_setFidelityThreshold(tPeriodDetection* const, float threshold);
void tPeriodDetection_setAlpha (tPeriodDetection* const, float alpha);
void tPeriodDetection_setTolerance (tPeriodDetection* const, float tolerance);
+ void tPeriodDetection_setSampleRate (tPeriodDetection* const, float sr);
//==============================================================================
@@ -644,7 +647,6 @@
typedef struct _tZeroCrossingCollector
{
-
tMempool mempool;
tZeroCrossingInfo* _info;
@@ -689,7 +691,6 @@
typedef struct _tBitset
{
-
tMempool mempool;
unsigned int _value_size;
@@ -718,7 +719,6 @@
typedef struct _tBACF
{
-
tMempool mempool;
tBitset _bitset;
@@ -806,7 +806,6 @@
typedef struct _sub_collector
{
-
tMempool mempool;
float _first_period;
@@ -845,6 +844,10 @@
unsigned int _num_pulses; // = 0;
int _half_empty; // 0;
+ float sampleRate;
+ float lowestFreq;
+ float highestFreq;
+
tBACF _bacf;
} _tPeriodDetector;
@@ -866,6 +869,7 @@
int tPeriodDetector_isReset (tPeriodDetector* const detector);
void tPeriodDetector_setHysteresis (tPeriodDetector* const detector, float hysteresis);
+ void tPeriodDetector_setSampleRate (tPeriodDetector* const detector, float sr);
//==============================================================================
@@ -942,6 +946,8 @@
_pitch_info _current;
int _frames_after_shift;// = 0;
+ float sampleRate;
+
} _tPitchDetector;
typedef _tPitchDetector* tPitchDetector;
@@ -958,8 +964,8 @@
int tPitchDetector_indeterminate (tPitchDetector* const detector);
void tPitchDetector_setHysteresis (tPitchDetector* const detector, float hysteresis);
+ void tPitchDetector_setSampleRate (tPitchDetector* const detector, float sr);
-
//==============================================================================
/*!
@@ -1041,6 +1047,8 @@
float highest, lowest;
float thresh;
+
+ float sampleRate;
} _tDualPitchDetector;
@@ -1058,9 +1066,7 @@
void tDualPitchDetector_setHysteresis (tDualPitchDetector* const detector, float hysteresis);
void tDualPitchDetector_setPeriodicityThreshold (tDualPitchDetector* const detector, float thresh);
-
-
-
+ void tDualPitchDetector_setSampleRate (tDualPitchDetector* const detector, float sr);
#ifdef __cplusplus
}
--- a/leaf/Inc/leaf-distortion.h
+++ b/leaf/Inc/leaf-distortion.h
@@ -61,7 +61,6 @@
typedef struct _tSampleReducer
{
-
tMempool mempool;
float invRatio;
float hold;
@@ -124,9 +123,9 @@
typedef struct _tOversampler
{
-
tMempool mempool;
int maxRatio;
+ int allowHighQuality;
int ratio;
int offset;
float* pCoeffs;
@@ -143,11 +142,12 @@
void tOversampler_free (tOversampler* const);
void tOversampler_upsample (tOversampler* const, float input, float* output);
- float tOversampler_downsample (tOversampler* const os, float* input);
+ float tOversampler_downsample (tOversampler* const, float* input);
float tOversampler_tick (tOversampler* const, float input, float* oversample,
float (*effectTick)(float));
void tOversampler_setRatio (tOversampler* const, int ratio);
- int tOversampler_getLatency (tOversampler* const os);
+ void tOversampler_setQuality (tOversampler* const, int quality);
+ int tOversampler_getLatency (tOversampler* const);
//==============================================================================
--- a/leaf/Inc/leaf-dynamics.h
+++ b/leaf/Inc/leaf-dynamics.h
@@ -69,6 +69,8 @@
int isActive;
+ float sampleRate;
+
} _tCompressor;
typedef _tCompressor* tCompressor;
--- a/leaf/Inc/leaf-effects.h
+++ b/leaf/Inc/leaf-effects.h
@@ -1,8 +1,8 @@
/*==============================================================================
leaf-effects.h
-
+
==============================================================================*/
#ifndef LEAF_EFFECTS_H_INCLUDED
@@ -20,8 +20,8 @@
#include "leaf-analysis.h"
#include "leaf-envelopes.h"
-
-
+
+
//==============================================================================
/*!
@@ -89,7 +89,7 @@
@param talkbox A pointer to the relevant tTalkbox.
@} */
-
+
#define NUM_TALKBOX_PARAM 4
typedef struct _tTalkbox
@@ -98,7 +98,7 @@
tMempool mempool;
float param[NUM_TALKBOX_PARAM];
-
+
int bufsize;
float* car0;
float* car1;
@@ -117,8 +117,9 @@
float G;
double* dl;
double* Rt;
-
+ float sampleRate;
+
} _tTalkbox;
typedef _tTalkbox* tTalkbox;
@@ -138,11 +139,12 @@
void tTalkbox_setWarpOn (tTalkbox* const voc, float warpOn);
void tTalkbox_setFreeze (tTalkbox* const voc, float freeze);
void tTalkbox_warpedAutocorrelate (float * x, double* dl, double* Rt, unsigned int L, float * R, unsigned int P, float lambda);
+ void tTalkbox_setSampleRate (tTalkbox* const voc, float sr);
//==============================================================================
-
+
/*!
@defgroup ttalkboxfloat tTalkboxFloat
@ingroup effects
@@ -208,55 +210,58 @@
@param talkbox A pointer to the relevant tTalkboxFloat.
@} */
-
+
typedef struct _tTalkboxFloat
- {
-
- tMempool mempool;
-
- float param[NUM_TALKBOX_PARAM];
-
- int bufsize;
- float* car0;
- float* car1;
- float* window;
- float* buf0;
- float* buf1;
- float* k;
- float warpFactor;
- int32_t warpOn;
- int freeze;
- float emphasis;
- int32_t K, N, O, pos;
- float wet, dry, FX;
- float d0, d1, d2, d3, d4;
- float u0, u1, u2, u3, u4;
- float G;
- float* dl;
- float* Rt;
-
- } _tTalkboxFloat;
-
- typedef _tTalkboxFloat* tTalkboxFloat;
-
- void tTalkboxFloat_init (tTalkboxFloat* const, int bufsize, LEAF* const leaf);
- void tTalkboxFloat_initToPool (tTalkboxFloat* const, int bufsize, tMempool* const);
- void tTalkboxFloat_free (tTalkboxFloat* const);
-
- float tTalkboxFloat_tick (tTalkboxFloat* const, float synth, float voice);
- float tTalkboxFloat_tickFrozen (tTalkboxFloat* const voc, float synth, float voice);
- void tTalkboxFloat_update (tTalkboxFloat* const);
- void tTalkboxFloat_suspend (tTalkboxFloat* const);
- void tTalkboxFloat_lpcDurbin (float *r, int p, float *k, float *g);
- void tTalkboxFloat_lpc (float *buf, float *car, float* dl, float* Rt, int32_t n, int32_t o, float warp, int warpOn, float *k, int freeze, float *G);
- void tTalkboxFloat_setQuality (tTalkboxFloat* const, float quality);
- void tTalkboxFloat_setWarpFactor (tTalkboxFloat* const voc, float warp);
- void tTalkboxFloat_setWarpOn (tTalkboxFloat* const voc, int warpOn);
- void tTalkboxFloat_setFreeze (tTalkboxFloat* const voc, int freeze);
- void tTalkboxFloat_warpedAutocorrelate (float * x, float* dl, float* Rt, unsigned int L, float * R, unsigned int P, float lambda);
- //==============================================================================
-
-
+ {
+
+ tMempool mempool;
+
+ float param[NUM_TALKBOX_PARAM];
+
+ int bufsize;
+ float* car0;
+ float* car1;
+ float* window;
+ float* buf0;
+ float* buf1;
+ float* k;
+ float warpFactor;
+ int32_t warpOn;
+ int freeze;
+ float emphasis;
+ int32_t K, N, O, pos;
+ float wet, dry, FX;
+ float d0, d1, d2, d3, d4;
+ float u0, u1, u2, u3, u4;
+ float G;
+ float* dl;
+ float* Rt;
+
+ float sampleRate;
+
+ } _tTalkboxFloat;
+
+ typedef _tTalkboxFloat* tTalkboxFloat;
+
+ void tTalkboxFloat_init (tTalkboxFloat* const, int bufsize, LEAF* const leaf);
+ void tTalkboxFloat_initToPool (tTalkboxFloat* const, int bufsize, tMempool* const);
+ void tTalkboxFloat_free (tTalkboxFloat* const);
+
+ float tTalkboxFloat_tick (tTalkboxFloat* const, float synth, float voice);
+ float tTalkboxFloat_tickFrozen (tTalkboxFloat* const voc, float synth, float voice);
+ void tTalkboxFloat_update (tTalkboxFloat* const);
+ void tTalkboxFloat_suspend (tTalkboxFloat* const);
+ void tTalkboxFloat_lpcDurbin (float *r, int p, float *k, float *g);
+ void tTalkboxFloat_lpc (float *buf, float *car, float* dl, float* Rt, int32_t n, int32_t o, float warp, int warpOn, float *k, int freeze, float *G);
+ void tTalkboxFloat_setQuality (tTalkboxFloat* const, float quality);
+ void tTalkboxFloat_setWarpFactor (tTalkboxFloat* const voc, float warp);
+ void tTalkboxFloat_setWarpOn (tTalkboxFloat* const voc, int warpOn);
+ void tTalkboxFloat_setFreeze (tTalkboxFloat* const voc, int freeze);
+ void tTalkboxFloat_warpedAutocorrelate (float * x, float* dl, float* Rt, unsigned int L, float * R, unsigned int P, float lambda);
+ void tTalkboxFloat_setSampleRate (tTalkboxFloat* const voc, float sr);
+ //==============================================================================
+
+
/*!
@defgroup tvocoder tVocoder
@ingroup effects
@@ -310,6 +315,7 @@
//filter coeffs and buffers - seems it's faster to leave this global than make local copy
float f[NBANDS][13]; //[0-8][0 1 2 | 0 1 2 3 | 0 1 2 3 | val rate]
+ float invSampleRate;
} _tVocoder;
typedef _tVocoder* tVocoder;
@@ -321,6 +327,7 @@
float tVocoder_tick (tVocoder* const, float synth, float voice);
void tVocoder_update (tVocoder* const);
void tVocoder_suspend (tVocoder* const);
+ void tVocoder_setSampleRate (tVocoder* const, float sr);
//==============================================================================
@@ -369,7 +376,7 @@
@param pulse A pointer to the relevant tRosenbergGlottalPulse.
@} */
-
+
typedef struct _tRosenbergGlottalPulse
{
@@ -380,22 +387,25 @@
float invPulseLengthMinusOpenLength;
float freq;
float inc;
+ float invSampleRate;
} _tRosenbergGlottalPulse;
-
+
typedef _tRosenbergGlottalPulse* tRosenbergGlottalPulse;
-
+
void tRosenbergGlottalPulse_init (tRosenbergGlottalPulse* const, LEAF* const leaf);
void tRosenbergGlottalPulse_initToPool (tRosenbergGlottalPulse* const, tMempool* const);
void tRosenbergGlottalPulse_free (tRosenbergGlottalPulse* const);
-
+
float tRosenbergGlottalPulse_tick (tRosenbergGlottalPulse* const);
float tRosenbergGlottalPulse_tickHQ (tRosenbergGlottalPulse* const gp);
void tRosenbergGlottalPulse_setFreq (tRosenbergGlottalPulse* const, float freq);
-
- void tRosenbergGlottalPulse_setOpenLength (tRosenbergGlottalPulse* const, float openLength);
-
- void tRosenbergGlottalPulse_setPulseLength (tRosenbergGlottalPulse* const, float pulseLength);
- void tRosenbergGlottalPulse_setOpenLengthAndPulseLength (tRosenbergGlottalPulse* const gp, float openLength, float pulseLength);
+
+ void tRosenbergGlottalPulse_setOpenLength (tRosenbergGlottalPulse* const, float openLength);
+
+ void tRosenbergGlottalPulse_setPulseLength (tRosenbergGlottalPulse* const, float pulseLength);
+ void tRosenbergGlottalPulse_setOpenLengthAndPulseLength(tRosenbergGlottalPulse* const, float
+ openLength, float pulseLength);
+ void tRosenbergGlottalPulse_setSampleRate(tRosenbergGlottalPulse* const, float sr);
//==============================================================================
/*!
@@ -421,7 +431,7 @@
@fn void tSOLAD_ioSamples (tSOLAD *w, float* in, float* out, int blocksize)
@brief Send one block of input samples, receive one block of output samples
@param solad A pointer to the relevant tSOLAD.
-
+
@fn void tSOLAD_setPeriod (tSOLAD *w, float period)
@brief Set periodicity analysis data
@param solad A pointer to the relevant tSOLAD.
@@ -440,11 +450,11 @@
@} */
-//#define LOOPSIZE (2048*2) // (4096*2) // loop size must be power of two
-//#define LOOPMASK (LOOPSIZE - 1)
+ //#define LOOPSIZE (2048*2) // (4096*2) // loop size must be power of two
+ //#define LOOPMASK (LOOPSIZE - 1)
#define PITCHFACTORDEFAULT 1.0f
#define INITPERIOD 64.0f
-//#define MAXPERIOD (float)((LOOPSIZE - w->blocksize) * 0.8f)
+ //#define MAXPERIOD (float)((LOOPSIZE - w->blocksize) * 0.8f)
#define MINPERIOD 8.0f
typedef struct _tSOLAD
@@ -484,6 +494,7 @@
void tSOLAD_setReadLag (tSOLAD *w, float readlag);
// reset state variables
void tSOLAD_resetState (tSOLAD *w);
+ void tSOLAD_setSampleRate (tSOLAD* const, float sr);
/*!
@defgroup tpitchshift tPitchShift
@@ -536,6 +547,8 @@
int index;
float pickiness;
+
+ float sampleRate;
} _tPitchShift;
typedef _tPitchShift* tPitchShift;
@@ -548,6 +561,7 @@
void tPitchShift_shiftTo (tPitchShift* const, float freq, float* in, float* out);
void tPitchShift_setPickiness (tPitchShift* const, float p);
+ void tPitchShift_setSampleRate(tPitchShift* const, float sr);
/*!
@defgroup tsimpleretune tSimpleRetune
@@ -620,7 +634,8 @@
void tSimpleRetune_tuneVoices (tSimpleRetune* const, float* t);
void tSimpleRetune_tuneVoice (tSimpleRetune* const, int voice, float t);
float tSimpleRetune_getInputFrequency (tSimpleRetune* const);
-
+ void tSimpleRetune_setSampleRate (tSimpleRetune* const, float sr);
+
/*!
@defgroup tretune tRetune
@ingroup effects
@@ -695,6 +710,7 @@
void tRetune_tuneVoices (tRetune* const, float* t);
void tRetune_tuneVoice (tRetune* const, int voice, float t);
float tRetune_getInputFrequency (tRetune* const);
+ void tRetune_setSampleRate (tRetune* const, float sr);
//==============================================================================
@@ -772,6 +788,8 @@
tHighpass hp2;
tFeedbackLeveler fbl1;
tFeedbackLeveler fbl2;
+ float sampleRate;
+ float invSampleRate;
} _tFormantShifter;
typedef _tFormantShifter* tFormantShifter;
@@ -786,6 +804,7 @@
void tFormantShifter_ioSamples (tFormantShifter* const, float* in, float* out, int size, float fwarp);
void tFormantShifter_setShiftFactor (tFormantShifter* const, float shiftFactor);
void tFormantShifter_setIntensity (tFormantShifter* const, float intensity);
+ void tFormantShifter_setSampleRate (tFormantShifter* const fsr, float sr);
//==============================================================================
@@ -796,3 +815,4 @@
#endif // LEAF_EFFECTS_H_INCLUDED
//==============================================================================
+
--- a/leaf/Inc/leaf-envelopes.h
+++ b/leaf/Inc/leaf-envelopes.h
@@ -345,9 +345,11 @@
const float *exp_buff;
uint32_t buff_size;
uint32_t buff_sizeMinusOne;
+ float sampleRate;
float bufferSizeDividedBySampleRateInMs;
float next;
+ float attack, decay, release;
float attackInc, decayInc, releaseInc, rampInc;
uint32_t whichStage;
@@ -374,6 +376,7 @@
void tADSRT_setLeakFactor (tADSRT* const, float leakFactor);
void tADSRT_on (tADSRT* const, float velocity);
void tADSRT_off (tADSRT* const);
+ void tADSRT_setSampleRate (tADSRT* const, float sr);
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
@@ -444,9 +447,13 @@
{
tMempool mempool;
+ float sampleRate;
float sampleRateInMs;
int state;
float output;
+ float attack;
+ float decay;
+ float release;
float attackRate;
float decayRate;
float releaseRate;
@@ -481,6 +488,7 @@
void tADSRS_setLeakFactor (tADSRS* const, float leakFactor);
void tADSRS_on (tADSRS* const, float velocity);
void tADSRS_off (tADSRS* const);
+ void tADSRS_setSampleRate (tADSRS* const, float sr);
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
@@ -528,9 +536,9 @@
typedef struct _tRamp
{
-
tMempool mempool;
float inc;
+ float sampleRate;
float inv_sr_ms;
float minimum_time;
float curr,dest;
@@ -550,6 +558,7 @@
void tRamp_setTime (tRamp* const, float time);
void tRamp_setDest (tRamp* const, float dest);
void tRamp_setVal (tRamp* const, float val);
+ void tRamp_setSampleRate (tRamp* const, float sr);
/*!
@defgroup trampupdown tRampUpDown
@@ -599,10 +608,10 @@
typedef struct _tRampUpDown
{
-
tMempool mempool;
float upInc;
float downInc;
+ float sampleRate;
float inv_sr_ms;
float minimum_time;
float curr,dest;
@@ -623,9 +632,8 @@
void tRampUpDown_setDownTime (tRampUpDown* const, float downTime);
void tRampUpDown_setDest (tRampUpDown* const, float dest);
void tRampUpDown_setVal (tRampUpDown* const, float val);
+ void tRampUpDown_setSampleRate (tRampUpDown* const, float sr);
-
-
/*!
@defgroup tslide tSlide
@ingroup envelopes
@@ -670,7 +678,6 @@
typedef struct _tSlide
{
-
tMempool mempool;
float prevOut;
float currentOut;
--- a/leaf/Inc/leaf-filters.h
+++ b/leaf/Inc/leaf-filters.h
@@ -143,10 +143,12 @@
{
tMempool mempool;
+ float freq;
float gain;
float a0,a1;
float b0,b1;
float lastIn, lastOut;
+ float twoPiTimesInvSampleRate;
} _tOnePole;
typedef _tOnePole* tOnePole;
@@ -162,6 +164,7 @@
void tOnePole_setFreq (tOnePole* const, float freq);
void tOnePole_setCoefficients(tOnePole* const, float b0, float a1);
void tOnePole_setGain (tOnePole* const, float gain);
+ void tOnePole_setSampleRate (tOnePole* const, float sr);
//==============================================================================
@@ -228,6 +231,9 @@
int normalize;
float lastOut[2];
+
+ float sampleRate;
+ float twoPiTimesInvSampleRate;
} _tTwoPole;
typedef _tTwoPole* tTwoPole;
@@ -243,6 +249,7 @@
void tTwoPole_setResonance (tTwoPole* const, float freq, float radius, int normalize);
void tTwoPole_setCoefficients(tTwoPole* const, float b0, float a1, float a2);
void tTwoPole_setGain (tTwoPole* const, float gain);
+ void tTwoPole_setSampleRate (tTwoPole* const, float sr);
//==============================================================================
@@ -298,11 +305,11 @@
typedef struct _tOneZero
{
-
tMempool mempool;
float gain;
float b0,b1;
float lastIn, lastOut, frequency;
+ float invSampleRate;
} _tOneZero;
typedef _tOneZero* tOneZero;
@@ -317,7 +324,8 @@
void tOneZero_setZero (tOneZero* const, float theZero);
void tOneZero_setCoefficients(tOneZero* const, float b0, float b1);
void tOneZero_setGain (tOneZero* const, float gain);
- float tOneZero_getPhaseDelay (tOneZero *f, float frequency);
+ float tOneZero_getPhaseDelay (tOneZero* const, float frequency);
+ void tOneZero_setSampleRate (tOneZero* const, float sr);
//==============================================================================
@@ -374,15 +382,13 @@
typedef struct _tTwoZero
{
-
tMempool mempool;
float gain;
float b0, b1, b2;
-
float frequency, radius;
-
float lastIn[2];
+ float twoPiTimesInvSampleRate;
} _tTwoZero;
typedef _tTwoZero* tTwoZero;
@@ -398,6 +404,7 @@
void tTwoZero_setNotch (tTwoZero* const, float frequency, float radius);
void tTwoZero_setCoefficients(tTwoZero* const, float b0, float b1, float b2);
void tTwoZero_setGain (tTwoZero* const, float gain);
+ void tTwoZero_setSampleRate (tTwoZero* const, float sr);
//==============================================================================
@@ -552,7 +559,6 @@
typedef struct _tBiQuad
{
-
tMempool mempool;
float gain;
@@ -564,6 +570,9 @@
float frequency, radius;
int normalize;
+
+ float sampleRate;
+ float twoPiTimesInvSampleRate;
} _tBiQuad;
typedef _tBiQuad* tBiQuad;
@@ -582,6 +591,7 @@
void tBiQuad_setResonance (tBiQuad* const, float freq, float radius, int normalize);
void tBiQuad_setCoefficients(tBiQuad* const, float b0, float b1, float b2, float a1, float a2);
void tBiQuad_setGain (tBiQuad* const, float gain);
+ void tBiQuad_setSampleRate (tBiQuad* const, float sr);
//==============================================================================
@@ -636,12 +646,13 @@
typedef struct _tSVF
{
-
tMempool mempool;
SVFType type;
float cutoff, Q;
float ic1eq,ic2eq;
float g,k,a1,a2,a3,cH,cB,cL,cBK;
+ float sampleRate;
+ float invSampleRate;
} _tSVF;
typedef _tSVF* tSVF;
@@ -654,6 +665,7 @@
void tSVF_setFreq (tSVF* const, float freq);
void tSVF_setQ (tSVF* const, float Q);
void tSVF_setFreqAndQ (tSVF* const svff, float freq, float Q);
+ void tSVF_setSampleRate (tSVF* const svff, float sr);
//==============================================================================
@@ -749,10 +761,10 @@
typedef struct _tHighpass
{
-
tMempool mempool;
float xs, ys, R;
float frequency;
+ float twoPiTimesInvSampleRate;
} _tHighpass;
typedef _tHighpass* tHighpass;
@@ -764,6 +776,7 @@
float tHighpass_tick (tHighpass* const, float x);
void tHighpass_setFreq (tHighpass* const, float freq);
float tHighpass_getFreq (tHighpass* const);
+ void tHighpass_setSampleRate (tHighpass* const, float sr);
//==============================================================================
@@ -835,6 +848,7 @@
void tButterworth_setF1 (tButterworth* const, float in);
void tButterworth_setF2 (tButterworth* const, float in);
void tButterworth_setFreqs (tButterworth* const, float f1, float f2);
+ void tButterworth_setSampleRate (tButterworth* const, float sr);
//==============================================================================
@@ -952,10 +966,6 @@
@brief Free a tVZFilter from its mempool.
@param filter A pointer to the tVZFilter to free.
- @fn void tVZFilter_setSampleRate (tVZFilter* const, float sampleRate)
- @brief
- @param filter A pointer to the relevant tVZFilter.
-
@fn float tVZFilter_tick (tVZFilter* const, float input)
@brief
@param filter A pointer to the relevant tVZFilter.
@@ -991,6 +1001,10 @@
@fn float tVZFilter_BandwidthToR (tVZFilter* const vf, float B)
@brief
@param filter A pointer to the relevant tVZFilter.
+
+ @fn void tVZFilter_setSampleRate (tVZFilter* const, float sampleRate)
+ @brief
+ @param filter A pointer to the relevant tVZFilter.

@} */
@@ -1012,7 +1026,6 @@
typedef struct _tVZFilter
{
-
tMempool mempool;
VZFilterType type;
@@ -1032,8 +1045,8 @@
float B; // bandwidth (in octaves)
float m; // morph parameter (0...1)
- float sr; //local sampling rate of filter (may be different from leaf sr if oversampled)
- float inv_sr;
+ float sampleRate; //local sampling rate of filter (may be different from leaf sr if oversampled)
+ float invSampleRate;
} _tVZFilter;
typedef _tVZFilter* tVZFilter;
@@ -1094,8 +1107,8 @@
//diode ladder filter
typedef struct _tDiodeFilter
{
-
tMempool mempool;
+ float cutoff;
float f;
float r;
float Vt;
@@ -1106,6 +1119,7 @@
float g1inv;
float g2inv;
float s0, s1, s2, s3;
+ float invSampleRate;
} _tDiodeFilter;
typedef _tDiodeFilter* tDiodeFilter;
@@ -1117,7 +1131,7 @@
float tDiodeFilter_tick (tDiodeFilter* const, float input);
void tDiodeFilter_setFreq (tDiodeFilter* const vf, float cutoff);
void tDiodeFilter_setQ (tDiodeFilter* const vf, float resonance);
-
+ void tDiodeFilter_setSampleRate(tDiodeFilter* const vf, float sr);
#ifdef __cplusplus
}
--- a/leaf/Inc/leaf-instruments.h
+++ b/leaf/Inc/leaf-instruments.h
@@ -115,6 +115,7 @@
void t808Cowbell_setFreq (t808Cowbell* const, float freq);
void t808Cowbell_setOscMix (t808Cowbell* const, float oscMix);
void t808Cowbell_setStick (t808Cowbell* const, int useStick);
+ void t808Cowbell_setSampleRate (t808Cowbell* const, float sr);
//==============================================================================
@@ -227,6 +228,7 @@
void t808Hihat_setOscFreq (t808Hihat* const, float freq);
void t808Hihat_setStretch (t808Hihat* const hihat, float stretch);
void t808Hihat_setFM (t808Hihat* const hihat, float FM_amount);
+ void t808Hihat_setSampleRate (t808Hihat* const, float sr);
//==============================================================================
@@ -333,6 +335,7 @@
void t808Snare_setToneNoiseMix (t808Snare* const, float toneNoiseMix);
void t808Snare_setNoiseFilterFreq (t808Snare* const, float noiseFilterFreq);
void t808Snare_setNoiseFilterQ (t808Snare* const, float noiseFilterQ);
+ void t808Snare_setSampleRate (t808Snare* const, float sr);
//==============================================================================
@@ -437,6 +440,7 @@
void t808Kick_setToneNoiseMix (t808Kick* const, float toneNoiseMix);
void t808Kick_setNoiseFilterFreq (t808Kick* const, float noiseFilterFreq);
void t808Kick_setNoiseFilterQ (t808Kick* const, float noiseFilterQ);
+ void t808kick_setSampleRate (t808Kick* const, float sr);
//==============================================================================
--- a/leaf/Inc/leaf-midi.h
+++ b/leaf/Inc/leaf-midi.h
@@ -309,7 +309,8 @@
int tPoly_getKey (tPoly* const poly, uint8_t voice);
int tPoly_getVelocity (tPoly* const poly, uint8_t voice);
int tPoly_isOn (tPoly* const poly, uint8_t voice);
-
+ void tPoly_setSampleRate (tPoly* const poly, float sr);
+
//==============================================================================
/*! @}
--- a/leaf/Inc/leaf-oscillators.h
+++ b/leaf/Inc/leaf-oscillators.h
@@ -63,11 +63,11 @@
typedef struct _tCycle
{
-
tMempool mempool;
// Underlying phasor
float phase;
float inc,freq;
+ float invSampleRate;
} _tCycle;
typedef _tCycle* tCycle;
@@ -78,6 +78,7 @@
float tCycle_tick (tCycle* const osc);
void tCycle_setFreq (tCycle* const osc, float freq);
+ void tCycle_setSampleRate(tCycle* const osc, float sr);
//==============================================================================
@@ -122,6 +123,7 @@
float inc,freq;
int oct;
float w;
+ float invSampleRate;
} _tTriangle;
typedef _tTriangle* tTriangle;
@@ -132,7 +134,7 @@
float tTriangle_tick (tTriangle* const osc);
void tTriangle_setFreq (tTriangle* const osc, float freq);
-
+ void tTriangle_setSampleRate (tTriangle* const osc, float sr);
//==============================================================================
@@ -177,6 +179,7 @@
float inc,freq;
int oct;
float w;
+ float invSampleRate;
} _tSquare;
typedef _tSquare* tSquare;
@@ -187,6 +190,7 @@
float tSquare_tick (tSquare* const osc);
void tSquare_setFreq (tSquare* const osc, float freq);
+ void tSquare_setSampleRate (tSquare* const osc, float sr);
/*!
@} */
@@ -234,6 +238,7 @@
float inc,freq;
int oct;
float w;
+ float invSampleRate;
} _tSawtooth;
typedef _tSawtooth* tSawtooth;
@@ -244,6 +249,7 @@
float tSawtooth_tick (tSawtooth* const osc);
void tSawtooth_setFreq (tSawtooth* const osc, float freq);
+ void tSawtooth_setSampleRate (tSawtooth* const osc, float sr);
//==============================================================================
@@ -288,6 +294,7 @@
float inc,freq;
float skew;
float lastOut;
+ float invSampleRate;
} _tPBTriangle;
typedef _tPBTriangle* tPBTriangle;
@@ -299,6 +306,7 @@
float tPBTriangle_tick (tPBTriangle* const osc);
void tPBTriangle_setFreq (tPBTriangle* const osc, float freq);
void tPBTriangle_setSkew (tPBTriangle* const osc, float skew);
+ void tPBTriangle_setSampleRate (tPBTriangle* const osc, float sr);
//==============================================================================
@@ -342,6 +350,7 @@
float phase;
float inc,freq;
float width;
+ float invSampleRate;
} _tPBPulse;
typedef _tPBPulse* tPBPulse;
@@ -353,6 +362,7 @@
float tPBPulse_tick (tPBPulse* const osc);
void tPBPulse_setFreq (tPBPulse* const osc, float freq);
void tPBPulse_setWidth (tPBPulse* const osc, float width);
+ void tPBPulse_setSampleRate (tPBPulse* const osc, float sr);
//==============================================================================
@@ -391,6 +401,7 @@
tMempool mempool;
float phase;
float inc,freq;
+ float invSampleRate;
} _tPBSaw;
typedef _tPBSaw* tPBSaw;
@@ -401,6 +412,7 @@
float tPBSaw_tick (tPBSaw* const osc);
void tPBSaw_setFreq (tPBSaw* const osc, float freq);
+ void tPBSaw_setSampleRate (tPBSaw* const osc, float sr);
//==============================================================================
@@ -441,6 +453,7 @@
float phase;
float inc,freq;
uint8_t phaseDidReset;
+ float invSampleRate;
} _tPhasor;
typedef _tPhasor* tPhasor;
@@ -451,6 +464,7 @@
float tPhasor_tick (tPhasor* const osc);
void tPhasor_setFreq (tPhasor* const osc, float freq);
+ void tPhasor_setSampleRate (tPhasor* const osc, float sr);
//==============================================================================
@@ -643,9 +657,7 @@
void tNeuron_setV2 (tNeuron* const neuron, float V2);
void tNeuron_setV3 (tNeuron* const neuron, float V3);
void tNeuron_setTimeStep (tNeuron* const neuron, float timestep);
-
-
//==============================================================================
@@ -708,6 +720,7 @@
float _f [FILLEN + STEP_DD_PULSE_LENGTH];
int _j, _k;
bool _init;
+ float invSampleRate;
} _tMBPulse;
typedef _tMBPulse* tMBPulse;
@@ -721,6 +734,7 @@
void tMBPulse_setWidth(tMBPulse* const osc, float w);
float tMBPulse_sync(tMBPulse* const osc, float sync);
void tMBPulse_setSyncMode(tMBPulse* const osc, int hardOrSoft);
+ void tMBPulse_setSampleRate (tMBPulse* const osc, float sr);
/*!
@defgroup tmbtriangle tMBTriangle
@@ -779,6 +793,7 @@
float _f [FILLEN + LONGEST_DD_PULSE_LENGTH];
int _j, _k;
bool _init;
+ float invSampleRate;
} _tMBTriangle;
typedef _tMBTriangle* tMBTriangle;
@@ -792,6 +807,7 @@
void tMBTriangle_setWidth(tMBTriangle* const osc, float w);
float tMBTriangle_sync(tMBTriangle* const osc, float sync);
void tMBTriangle_setSyncMode(tMBTriangle* const osc, int hardOrSoft);
+ void tMBTriangle_setSampleRate (tMBTriangle* const osc, float sr);
/*!
@@ -849,6 +865,7 @@
float _f [FILLEN + STEP_DD_PULSE_LENGTH];
int _j;
bool _init;
+ float invSampleRate;
} _tMBSaw;
typedef _tMBSaw* tMBSaw;
@@ -861,6 +878,7 @@
void tMBSaw_setFreq(tMBSaw* const osc, float f);
float tMBSaw_sync(tMBSaw* const osc, float sync);
void tMBSaw_setSyncMode(tMBSaw* const osc, int hardOrSoft);
+ void tMBSaw_setSampleRate (tMBSaw* const osc, float sr);
//==============================================================================
@@ -908,6 +926,7 @@
int size;
float inc, freq;
float phase;
+ float invSampleRate;
} _tTable;
typedef _tTable* tTable;
@@ -918,6 +937,7 @@
float tTable_tick(tTable* const osc);
void tTable_setFreq(tTable* const osc, float freq);
+ void tTable_setSampleRate (tTable* const osc, float sr);
//==============================================================================
@@ -953,11 +973,14 @@
{
tMempool mempool;
+ float* baseTable;
float** tables;
int size;
int numTables;
+ float maxFreq;
float baseFreq, invBaseFreq;
tButterworth bl;
+ float sampleRate;
} _tWaveTable;
typedef _tWaveTable* tWaveTable;
@@ -967,6 +990,7 @@
void tWaveTable_initToPool(tWaveTable* const osc, float* table, int size,
float maxFreq, tMempool* const mempool);
void tWaveTable_free(tWaveTable* const osc);
+ void tWaveTable_setSampleRate (tWaveTable* const osc, float sr);
//==============================================================================
@@ -995,6 +1019,7 @@
float inc, freq;
float phase;
float phaseOffset;
+ float invSampleRate;
int oct;
float w;
@@ -1011,6 +1036,7 @@
void tWaveOsc_setFreq(tWaveOsc* const osc, float freq);
void tWaveOsc_setAntiAliasing(tWaveOsc* const osc, float aa);
void tWaveOsc_setPhaseOffset(tWaveOsc* const osc, float phase);
+ void tWaveOsc_setSampleRate (tWaveOsc* const osc, float sr);
//==============================================================================
@@ -1087,6 +1113,7 @@
void tWaveSynth_setIndexGain(tWaveSynth* const osc, int i, float gain);
void tWaveSynth_setIndexPhase(tWaveSynth* const osc, int i, float phase);
// void tWaveSynth_setIndexTable(tWaveSynth* const osc, int i, float* table, int size);
+ void tWaveSynth_setSampleRate (tWaveSynth* const osc, float sr);
//==============================================================================
@@ -1122,13 +1149,16 @@
{
tMempool mempool;
+ float* baseTable;
float** tables;
int numTables;
int* sizes;
+ float maxFreq;
float baseFreq, invBaseFreq;
tButterworth bl;
float dsBuffer[2];
tOversampler ds;
+ float sampleRate;
} _tWaveTableS;
typedef _tWaveTableS* tWaveTableS;
@@ -1136,6 +1166,7 @@
void tWaveTableS_init(tWaveTableS* const osc, float* table, int size, float maxFreq, LEAF* const leaf);
void tWaveTableS_initToPool(tWaveTableS* const osc, float* table, int size, float maxFreq, tMempool* const mempool);
void tWaveTableS_free(tWaveTableS* const osc);
+ void tWaveTableS_setSampleRate (tWaveTableS* const osc, float sr);
/*!
@defgroup twaveoscs tWaveOscS
@@ -1182,6 +1213,7 @@
float inc, freq;
float phase;
float phaseOffset;
+ float invSampleRate;
int oct;
float w;
float aa;
@@ -1197,6 +1229,7 @@
void tWaveOscS_setFreq(tWaveOscS* const osc, float freq);
void tWaveOscS_setAntiAliasing(tWaveOscS* const osc, float aa);
void tWaveOscS_setPhaseOffset(tWaveOscS* const osc, float phase);
+ void tWaveOscS_setSampleRate (tWaveOscS* const osc, float sr);
//==============================================================================
@@ -1273,6 +1306,7 @@
void tWaveSynthS_setIndexGain(tWaveSynthS* const osc, int i, float gain);
void tWaveSynthS_setIndexPhase(tWaveSynthS* const osc, int i, float phase);
// void tWaveSynthS_setIndexTable(tWaveSynthS* const osc, int i, float* table, int size);
+ void tWaveSynthS_setSampleRate (tWaveSynthS* const osc, float sr);
#ifdef __cplusplus
}
--- a/leaf/Inc/leaf-physical.h
+++ b/leaf/Inc/leaf-physical.h
@@ -71,7 +71,7 @@
@fn void tPluck_noteOff (tPluck* const, float amplitude )
@brief Stop a note with the given amplitude (speed of decay)
@param string A pointer to the relevant tPluck.
-
+
@fn void tPluck_setFrequency (tPluck* const, float frequency )
@brief Set instrument parameters for a particular frequency.
@param string A pointer to the relevant tPluck.
@@ -79,7 +79,7 @@
@fn void tPluck_controlChange (tPluck* const, int number, float value)
@brief Perform the control change specified by \e number and \e value (0.0 - 128.0).
@param string A pointer to the relevant tPluck.
-
+
@fn float tPluck_getLastOut (tPluck* const)
@brief
@param string A pointer to the relevant tPluck.
@@ -100,7 +100,7 @@
float loopGain;
float lastFreq;
- float sr;
+ float sampleRate;
} _tPluck;
typedef _tPluck* tPluck;
@@ -116,6 +116,7 @@
void tPluck_setFrequency (tPluck* const, float frequency );
void tPluck_controlChange (tPluck* const, int number, float value);
float tPluck_getLastOut (tPluck* const);
+ void tPluck_setSampleRate (tPluck* const, float sr);
//==============================================================================
@@ -146,7 +147,7 @@
@fn void tKarplusStrong_pluck (tKarplusStrong* const, float amplitude)
@brief Pluck the string.
@param string A pointer to the relevant tKarplusStrong.
-
+
@fn void tKarplusStrong_noteOn (tKarplusStrong* const, float frequency, float amplitude)
@brief Start a note with the given frequency and amplitude.
@param string A pointer to the relevant tKarplusStrong.
@@ -210,6 +211,8 @@
float pickupPosition;
float lastOut;
+
+ float sampleRate;
} _tKarplusStrong;
typedef _tKarplusStrong* tKarplusStrong;
@@ -307,6 +310,7 @@
tHighpass DCblocker;
tFeedbackLeveler fbLev;
tExpSmooth wlSmooth;
+ float sampleRate;
} _tSimpleLivingString;
typedef _tSimpleLivingString* tSimpleLivingString;
@@ -329,6 +333,7 @@
void tSimpleLivingString_setLevSmoothFactor (tSimpleLivingString* const, float levSmoothFactor);
void tSimpleLivingString_setLevStrength (tSimpleLivingString* const, float levStrength);
void tSimpleLivingString_setLevMode (tSimpleLivingString* const, int levMode);
+ void tSimpleLivingString_setSampleRate (tSimpleLivingString* const, float sr);
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
@@ -404,7 +409,6 @@
typedef struct _tLivingString
{
-
tMempool mempool;
float freq, waveLengthInSamples; // the frequency of the whole string, determining delay length
float pickPos; // the pick position, dividing the string in two, in ratio
@@ -418,6 +422,7 @@
tHighpass DCblockerL, DCblockerU;
tFeedbackLeveler fbLevU, fbLevL;
tExpSmooth wlSmooth, ppSmooth;
+ float sampleRate;
} _tLivingString;
typedef _tLivingString* tLivingString;
@@ -442,11 +447,11 @@
void tLivingString_setLevSmoothFactor (tLivingString* const, float levSmoothFactor);
void tLivingString_setLevStrength (tLivingString* const, float levStrength);
void tLivingString_setLevMode (tLivingString* const, int levMode);
+ void tLivingString_setSampleRate (tLivingString* const, float sr);
-
- // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
+ // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
/*!
@defgroup tlivingstring2 tLivingString2
@ingroup physical
@@ -524,55 +529,56 @@
@} */
typedef struct _tLivingString2
- {
-
- tMempool mempool;
- 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 prepPos; // the preparation position, dividing the string in two, in ratio
- float pickupPos; // the preparation position, dividing the string in two, in ratio
- float prepIndex; // the amount of pressure on the preparation position of the string (near 0=soft obj, near 1=hard obj)
- float decay; // amplitude damping factor for the string (only active in mode 0)
- int levMode;
- float brightness;
- float curr;
- tHermiteDelay delLF,delUF,delUB,delLB; // delay for lower/upper/forward/backward part of the waveguide model
- tTwoZero bridgeFilter, nutFilter, prepFilterU, prepFilterL;
- tHighpass DCblockerL, DCblockerU;
- tFeedbackLeveler fbLevU, fbLevL;
- tExpSmooth wlSmooth, ppSmooth, prpSmooth, puSmooth;
- } _tLivingString2;
-
- typedef _tLivingString2* tLivingString2;
-
- void tLivingString2_init (tLivingString2* const, float freq, float pickPos, float prepPos, float pickupPos, float prepIndex,
- float brightness, float decay, float targetLev, float levSmoothFactor,
- float levStrength, int levMode, LEAF* const leaf);
- void tLivingString2_initToPool (tLivingString2* const, float freq, float pickPos, float prepPos, float pickupPos, float prepIndex,
- float brightness, float decay, float targetLev, float levSmoothFactor,
- float levStrength, int levMode, tMempool* const);
- void tLivingString2_free (tLivingString2* const);
-
- float tLivingString2_tick (tLivingString2* const, float input);
- float tLivingString2_sample (tLivingString2* const);
- void tLivingString2_setFreq (tLivingString2* const, float freq);
- void tLivingString2_setWaveLength (tLivingString2* const, float waveLength); // in samples
- void tLivingString2_setPickPos (tLivingString2* const, float pickPos);
- void tLivingString2_setPrepPos (tLivingString2* const, float prepPos);
- void tLivingString2_setPickupPos (tLivingString2* const, float pickupPos);
- void tLivingString2_setPrepIndex (tLivingString2* const, float prepIndex);
- void tLivingString2_setBrightness (tLivingString2* const, float brightness);
- void tLivingString2_setDecay (tLivingString2* const, float decay); // from 0 to 1, gets converted to real decay factor
- void tLivingString2_setTargetLev (tLivingString2* const, float targetLev);
- void tLivingString2_setLevSmoothFactor (tLivingString2* const, float levSmoothFactor);
- void tLivingString2_setLevStrength (tLivingString2* const, float levStrength);
- void tLivingString2_setLevMode (tLivingString2* const, int levMode);
-
-
-
- // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
- // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
+ {
+ tMempool mempool;
+ 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 prepPos; // the preparation position, dividing the string in two, in ratio
+ float pickupPos; // the preparation position, dividing the string in two, in ratio
+ float prepIndex; // the amount of pressure on the preparation position of the string (near 0=soft obj, near 1=hard obj)
+ float decay; // amplitude damping factor for the string (only active in mode 0)
+ int levMode;
+ float brightness;
+ float curr;
+ tHermiteDelay delLF,delUF,delUB,delLB; // delay for lower/upper/forward/backward part of the waveguide model
+ tTwoZero bridgeFilter, nutFilter, prepFilterU, prepFilterL;
+ tHighpass DCblockerL, DCblockerU;
+ tFeedbackLeveler fbLevU, fbLevL;
+ tExpSmooth wlSmooth, ppSmooth, prpSmooth, puSmooth;
+ float sampleRate;
+ } _tLivingString2;
+
+ typedef _tLivingString2* tLivingString2;
+
+ void tLivingString2_init (tLivingString2* const, float freq, float pickPos, float prepPos, float pickupPos, float prepIndex,
+ float brightness, float decay, float targetLev, float levSmoothFactor,
+ float levStrength, int levMode, LEAF* const leaf);
+ void tLivingString2_initToPool (tLivingString2* const, float freq, float pickPos, float prepPos, float pickupPos, float prepIndex,
+ float brightness, float decay, float targetLev, float levSmoothFactor,
+ float levStrength, int levMode, tMempool* const);
+ void tLivingString2_free (tLivingString2* const);
+
+ float tLivingString2_tick (tLivingString2* const, float input);
+ float tLivingString2_sample (tLivingString2* const);
+ void tLivingString2_setFreq (tLivingString2* const, float freq);
+ void tLivingString2_setWaveLength (tLivingString2* const, float waveLength); // in samples
+ void tLivingString2_setPickPos (tLivingString2* const, float pickPos);
+ void tLivingString2_setPrepPos (tLivingString2* const, float prepPos);
+ void tLivingString2_setPickupPos (tLivingString2* const, float pickupPos);
+ void tLivingString2_setPrepIndex (tLivingString2* const, float prepIndex);
+ void tLivingString2_setBrightness (tLivingString2* const, float brightness);
+ void tLivingString2_setDecay (tLivingString2* const, float decay); // from 0 to 1, gets converted to real decay factor
+ void tLivingString2_setTargetLev (tLivingString2* const, float targetLev);
+ void tLivingString2_setLevSmoothFactor (tLivingString2* const, float levSmoothFactor);
+ void tLivingString2_setLevStrength (tLivingString2* const, float levStrength);
+ void tLivingString2_setLevMode (tLivingString2* const, int levMode);
+ void tLivingString2_setSampleRate (tLivingString2* const, float sr);
+
+
+
+ // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+ // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
+
/*!
@defgroup tcomplexlivingstring tComplexLivingString
@ingroup physical
@@ -649,7 +655,6 @@
typedef struct _tComplexLivingString
{
-
tMempool mempool;
float freq, waveLengthInSamples; // the frequency of the whole string, determining delay length
float pickPos; // the pick position, dividing the string, in ratio
@@ -665,10 +670,11 @@
tHighpass DCblockerL, DCblockerU;
tFeedbackLeveler fbLevU, fbLevL;
tExpSmooth wlSmooth, pickPosSmooth, prepPosSmooth;
+ float sampleRate;
} _tComplexLivingString;
-
+
typedef _tComplexLivingString* tComplexLivingString;
-
+
void tComplexLivingString_init (tComplexLivingString* const, float freq, float pickPos,
float prepPos, float prepIndex, float dampFreq,
float decay, float targetLev, float levSmoothFactor,
@@ -678,7 +684,7 @@
float decay, float targetLev, float levSmoothFactor,
float levStrength, int levMode, tMempool* const);
void tComplexLivingString_free (tComplexLivingString* const);
-
+
float tComplexLivingString_tick (tComplexLivingString* const, float input);
float tComplexLivingString_sample (tComplexLivingString* const);
void tComplexLivingString_setFreq (tComplexLivingString* const, float freq);
@@ -692,10 +698,11 @@
void tComplexLivingString_setLevSmoothFactor (tComplexLivingString* const, float levSmoothFactor);
void tComplexLivingString_setLevStrength (tComplexLivingString* const, float levStrength);
void tComplexLivingString_setLevMode (tComplexLivingString* const, int levMode);
+ void tComplexLivingString_setSampleRate (tComplexLivingString* const, float sr);
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
-
+
/*!
@defgroup treedtable tReedTable
@ingroup physical
@@ -733,7 +740,7 @@
@param reed A pointer to the relevant tReedTable.
@} */
-
+
typedef struct _tReedTable
{
@@ -761,4 +768,5 @@
#endif // LEAF_PHYSICAL_H_INCLUDED
//==============================================================================
+
--- a/leaf/Inc/leaf-reverb.h
+++ b/leaf/Inc/leaf-reverb.h
@@ -78,6 +78,8 @@
float mix, t60;
float inv_441;
+ float sampleRate;
+ float invSampleRate;
tDelay allpassDelays[2];
tDelay combDelay;
@@ -97,6 +99,7 @@
float tPRCReverb_tick (tPRCReverb* const, float input);
void tPRCReverb_setT60 (tPRCReverb* const, float t60);
void tPRCReverb_setMix (tPRCReverb* const, float mix);
+ void tPRCReverb_setSampleRate(tPRCReverb* const, float sr);
//==============================================================================
@@ -149,7 +152,9 @@
float mix, t60;
- float inv_sr, inv_441;
+ float inv_441;
+ float sampleRate;
+ float invSampleRate;
tLinearDelay allpassDelays[8];
tLinearDelay combDelays[6];
@@ -171,6 +176,7 @@
void tNReverb_tickStereo (tNReverb* const rev, float input, float* output);
void tNReverb_setT60 (tNReverb* const, float t60);
void tNReverb_setMix (tNReverb* const, float mix);
+ void tNReverb_setSampleRate (tNReverb* const, float sr);
//==============================================================================
@@ -245,12 +251,13 @@
tMempool mempool;
+ float sampleRate;
float predelay;
float input_filter;
float feedback_filter;
float feedback_gain;
float mix;
- uint32_t frozen;
+ int frozen;
float size, size_max, t;
@@ -296,7 +303,7 @@
float tDattorroReverb_tick (tDattorroReverb* const, float input);
void tDattorroReverb_tickStereo (tDattorroReverb* const rev, float input, float* output);
void tDattorroReverb_setMix (tDattorroReverb* const, float mix);
- void tDattorroReverb_setFreeze (tDattorroReverb* const rev, uint32_t freeze);
+ void tDattorroReverb_setFreeze (tDattorroReverb* const rev, int freeze);
void tDattorroReverb_setHP (tDattorroReverb* const, float freq);
void tDattorroReverb_setSize (tDattorroReverb* const, float size);
void tDattorroReverb_setInputDelay (tDattorroReverb* const, float preDelay);
@@ -303,6 +310,7 @@
void tDattorroReverb_setInputFilter (tDattorroReverb* const, float freq);
void tDattorroReverb_setFeedbackFilter (tDattorroReverb* const, float freq);
void tDattorroReverb_setFeedbackGain (tDattorroReverb* const, float gain);
+ void tDattorroReverb_setSampleRate (tDattorroReverb* const, float sr);
#ifdef __cplusplus
}
--- a/leaf/Inc/leaf-sampling.h
+++ b/leaf/Inc/leaf-sampling.h
@@ -243,13 +243,12 @@
typedef struct _tSampler
{
-
tMempool mempool;
tBuffer samp;
- float leafInvSampleRate;
- float leafSampleRate;
+ float invSampleRate;
+ float sampleRate;
float ticksPerSevenMs;
float rateFactor;
uint32_t channels;
@@ -284,11 +283,11 @@
typedef _tSampler* tSampler;
void tSampler_init (tSampler* const, tBuffer* const, LEAF* const leaf);
- void tSampler_initToPool (tSampler* const sp, tBuffer* const b, tMempool* const mp, LEAF* const leaf);
+ void tSampler_initToPool (tSampler* const sp, tBuffer* const b, tMempool* const mp, LEAF* const leaf);
void tSampler_free (tSampler* const);
float tSampler_tick (tSampler* const);
- float tSampler_tickStereo (tSampler* const sp, float* outputArray);
+ float tSampler_tickStereo (tSampler* const sp, float* outputArray);
void tSampler_setSample (tSampler* const, tBuffer* const);
void tSampler_setMode (tSampler* const, PlayMode mode);
void tSampler_play (tSampler* const);
@@ -296,8 +295,9 @@
void tSampler_setStart (tSampler* const, int32_t start);
void tSampler_setEnd (tSampler* const, int32_t end);
void tSampler_setLength (tSampler* const, int32_t length);
- void tSampler_setCrossfadeLength (tSampler* const sp, uint32_t length);
+ void tSampler_setCrossfadeLength (tSampler* const, uint32_t length);
void tSampler_setRate (tSampler* const, float rate);
+ void tSampler_setSampleRate (tSampler* const, float sr);
//==============================================================================
@@ -388,7 +388,7 @@
void tAutoSampler_setWindowSize (tAutoSampler* const, uint32_t size);
void tAutoSampler_setCrossfadeLength (tAutoSampler* const, uint32_t length);
void tAutoSampler_setRate (tAutoSampler* const, float rate);
-
+ void tAutoSampler_setSampleRate (tAutoSampler* const, float sr);
/*!
@defgroup tmbsampler tMBSampler
--- a/leaf/Src/leaf-analysis.c
+++ b/leaf/Src/leaf-analysis.c
@@ -360,27 +360,13 @@
mpool_free((char*)a, a->mempool);
}
-/*******Public Functions***********/
-
-
void tAttackDetection_setBlocksize(tAttackDetection* const ad, int size)
{
_tAttackDetection* a = *ad;
- a->blocksize = size;
+ a->blockSize = size;
}
-void tAttackDetection_setSamplerate(tAttackDetection* const ad, int inRate)
-{
- _tAttackDetection* a = *ad;
-
- a->samplerate = inRate;
-
- //Reset atk and rel to recalculate coeff
- tAttackDetection_setAttack(ad, a->atk);
- tAttackDetection_setRelease(ad, a->rel);
-}
-
void tAttackDetection_setThreshold(tAttackDetection* const ad, float thres)
{
_tAttackDetection* a = *ad;
@@ -391,7 +377,7 @@
{
_tAttackDetection* a = *ad;
a->atk = inAtk;
- a->atk_coeff = powf(0.01f, 1.0f/(a->atk * a->samplerate * 0.001f));
+ a->atk_coeff = powf(0.01f, 1.0f/(a->atk * a->sampleRate * 0.001f));
}
void tAttackDetection_setRelease(tAttackDetection* const ad, int inRel)
@@ -398,10 +384,9 @@
{
_tAttackDetection* a = *ad;
a->rel = inRel;
- a->rel_coeff = powf(0.01f, 1.0f/(a->rel * a->samplerate * 0.001f));
+ a->rel_coeff = powf(0.01f, 1.0f/(a->rel * a->sampleRate * 0.001f));
}
-
int tAttackDetection_detect(tAttackDetection* const ad, float *in)
{
_tAttackDetection* a = *ad;
@@ -420,6 +405,16 @@
return result;
}
+void tAttackDetection_setSampleRate(tAttackDetection* const ad, float sr)
+{
+ _tAttackDetection* a = *ad;
+
+ a->sampleRate = sr;
+
+ tAttackDetection_setAttack(ad, a->atk);
+ tAttackDetection_setRelease(ad, a->rel);
+}
+
/*******Private Functions**********/
static void atkdtk_init(tAttackDetection* const ad, int blocksize, int atk, int rel)
@@ -428,9 +423,9 @@
LEAF* leaf = a->mempool->leaf;
a->env = 0;
- a->blocksize = blocksize;
+ a->blockSize = blocksize;
a->threshold = DEFTHRESHOLD;
- a->samplerate = leaf->sampleRate;
+ a->sampleRate = leaf->sampleRate;
a->prevAmp = 0;
a->env = 0;
@@ -445,7 +440,7 @@
int i = 0;
float tmp;
- for(i = 0; i < a->blocksize; ++i){
+ for(i = 0; i < a->blockSize; ++i){
tmp = fastabsf(in[i]);
if(tmp > a->env)
@@ -845,6 +840,7 @@
p->mempool = m;
LEAF* leaf = p->mempool->leaf;
+ p->invSampleRate = leaf->invSampleRate;
p->inBuffer = in;
p->bufSize = bufSize;
p->frameSize = frameSize;
@@ -865,7 +861,7 @@
p->alpha = 1.0f;
p->tolerance = 1.0f;
p->timeConstant = DEFTIMECONSTANT;
- p->radius = expf(-1000.0f * p->hopSize * leaf->invSampleRate / p->timeConstant);
+ p->radius = expf(-1000.0f * p->hopSize * p->invSampleRate / p->timeConstant);
p->fidelityThreshold = 0.95f;
}
@@ -878,7 +874,7 @@
mpool_free((char*)p, p->mempool);
}
-float tPeriodDetection_tick (tPeriodDetection* pd, float sample)
+float tPeriodDetection_tick (tPeriodDetection* const pd, float sample)
{
_tPeriodDetection* p = *pd;
@@ -913,43 +909,43 @@
return p->period;
}
-float tPeriodDetection_getPeriod(tPeriodDetection* pd)
+float tPeriodDetection_getPeriod(tPeriodDetection* const pd)
{
_tPeriodDetection* p = *pd;
return p->period;
}
-float tPeriodDetection_getFidelity(tPeriodDetection* pd)
+float tPeriodDetection_getFidelity(tPeriodDetection* const pd)
{
_tPeriodDetection* p = *pd;
return tSNAC_getFidelity(&p->snac);
}
-void tPeriodDetection_setHopSize(tPeriodDetection* pd, int hs)
+void tPeriodDetection_setHopSize(tPeriodDetection* const pd, int hs)
{
_tPeriodDetection* p = *pd;
p->hopSize = hs;
}
-void tPeriodDetection_setWindowSize(tPeriodDetection* pd, int ws)
+void tPeriodDetection_setWindowSize(tPeriodDetection* const pd, int ws)
{
_tPeriodDetection* p = *pd;
p->windowSize = ws;
}
-void tPeriodDetection_setFidelityThreshold(tPeriodDetection* pd, float threshold)
+void tPeriodDetection_setFidelityThreshold(tPeriodDetection* const pd, float threshold)
{
_tPeriodDetection* p = *pd;
p->fidelityThreshold = threshold;
}
-void tPeriodDetection_setAlpha (tPeriodDetection* pd, float alpha)
+void tPeriodDetection_setAlpha (tPeriodDetection* const pd, float alpha)
{
_tPeriodDetection* p = *pd;
p->alpha = LEAF_clip(0.0f, alpha, 1.0f);
}
-void tPeriodDetection_setTolerance (tPeriodDetection* pd, float tolerance)
+void tPeriodDetection_setTolerance (tPeriodDetection* const pd, float tolerance)
{
_tPeriodDetection* p = *pd;
if (tolerance < 0.0f) p->tolerance = 0.0f;
@@ -956,7 +952,15 @@
else p->tolerance = tolerance;
}
+void tPeriodDetection_setSampleRate (tPeriodDetection* const pd, float sr)
+{
+ _tPeriodDetection* p = *pd;
+ p->invSampleRate = 1.0f/sr;
+ p->radius = expf(-1000.0f * p->hopSize * p->invSampleRate / p->timeConstant);
+}
+//==========================================================================================
+
void tZeroCrossingInfo_init (tZeroCrossingInfo* const zc, LEAF* const leaf)
{
tZeroCrossingInfo_initToPool(zc, &leaf->mempool);
@@ -1522,8 +1526,12 @@
LEAF* leaf = p->mempool->leaf;
- tZeroCrossingCollector_initToPool(&p->_zc, (1.0f / lowestFreq) * leaf->sampleRate * 2.0f, hysteresis, mempool);
- p->_min_period = (1.0f / highestFreq) * leaf->sampleRate;
+ p->sampleRate = leaf->sampleRate;
+ p->lowestFreq = lowestFreq;
+ p->highestFreq = highestFreq;
+
+ tZeroCrossingCollector_initToPool(&p->_zc, (1.0f / lowestFreq) * p->sampleRate * 2.0f, hysteresis, mempool);
+ p->_min_period = (1.0f / highestFreq) * p->sampleRate;
p->_range = highestFreq / lowestFreq;
int windowSize = tZeroCrossingCollector_getWindowSize(&p->_zc);
@@ -1670,6 +1678,18 @@
return tZeroCrossingCollector_setHysteresis(&p->_zc, hysteresis);
}
+void tPeriodDetector_setSampleRate (tPeriodDetector* const detector, float sr)
+{
+ _tPeriodDetector* p = *detector;
+ _tMempool* m = p->mempool;
+ p->sampleRate = sr;
+ float hysteresis = p->_zc->_hysteresis;
+
+ tZeroCrossingCollector_free(&p->_zc);
+ tZeroCrossingCollector_initToPool(&p->_zc, (1.0f / p->lowestFreq) * p->sampleRate * 2.0f, hysteresis, &m);
+ p->_min_period = (1.0f / p->highestFreq) * p->sampleRate;
+}
+
static inline void set_bitstream(tPeriodDetector* const detector)
{
_tPeriodDetector* p = *detector;
@@ -1901,11 +1921,13 @@
_tMempool* m = *mempool;
_tPitchDetector* p = *detector = (_tPitchDetector*) mpool_alloc(sizeof(_tPitchDetector), m);
p->mempool = m;
+ LEAF* leaf = p->mempool->leaf;
tPeriodDetector_initToPool(&p->_pd, lowestFreq, highestFreq, -120.0f, mempool);
p->_current.frequency = 0.0f;
p->_current.periodicity = 0.0f;
p->_frames_after_shift = 0;
+ p->sampleRate = leaf->sampleRate;
}
void tPitchDetector_free (tPitchDetector* const detector)
@@ -1991,11 +2013,10 @@
float tPitchDetector_predictFrequency (tPitchDetector* const detector)
{
_tPitchDetector* p = *detector;
- LEAF* leaf = p->mempool->leaf;
float period = tPeriodDetector_predictPeriod(&p->_pd);
if (period > 0.0f)
- return leaf->sampleRate / period;
+ return p->sampleRate / period;
return 0.0f;
}
@@ -2009,18 +2030,23 @@
void tPitchDetector_setHysteresis (tPitchDetector* const detector, float hysteresis)
{
_tPitchDetector* p = *detector;
-
tPeriodDetector_setHysteresis(&p->_pd, hysteresis);
}
+void tPitchDetector_setSampleRate (tPitchDetector* const detector, float sr)
+{
+ _tPitchDetector* p = *detector;
+ p->sampleRate = sr;
+ tPeriodDetector_setSampleRate(&p->_pd, p->sampleRate);
+}
+
static inline float calculate_frequency(tPitchDetector* const detector)
{
_tPitchDetector* p = *detector;
- LEAF* leaf = p->mempool->leaf;
float period = p->_pd->_fundamental.period;
if (period > 0.0f)
- return leaf->sampleRate / period;
+ return p->sampleRate / period;
return 0.0f;
}
@@ -2131,9 +2157,12 @@
_tMempool* m = *mempool;
_tDualPitchDetector* p = *detector = (_tDualPitchDetector*) mpool_alloc(sizeof(_tDualPitchDetector), m);
p->mempool = m;
+ LEAF* leaf = p->mempool->leaf;
tPeriodDetection_initToPool(&p->_pd1, inBuffer, bufSize, bufSize / 2, mempool);
tPitchDetector_initToPool(&p->_pd2, lowestFreq, highestFreq, mempool);
+
+ p->sampleRate = leaf->sampleRate;
p->_current.frequency = 0.0f;
p->_current.periodicity = 0.0f;
@@ -2159,7 +2188,6 @@
int tDualPitchDetector_tick (tDualPitchDetector* const detector, float sample)
{
_tDualPitchDetector* p = *detector;
- LEAF* leaf = p->mempool->leaf;
tPeriodDetection_tick(&p->_pd1, sample);
int ready = tPitchDetector_tick(&p->_pd2, sample);
@@ -2172,7 +2200,7 @@
if (!pd2_indeterminate && period != 0.0f)
{
_pitch_info _i1;
- _i1.frequency = leaf->sampleRate / tPeriodDetection_getPeriod(&p->_pd1);
+ _i1.frequency = p->sampleRate / tPeriodDetection_getPeriod(&p->_pd1);
_i1.periodicity = tPeriodDetection_getFidelity(&p->_pd1);
_pitch_info _i2 = p->_pd2->_current;
@@ -2274,6 +2302,14 @@
_tDualPitchDetector* p = *detector;
p->thresh = thresh;
+}
+
+void tDualPitchDetector_setSampleRate (tDualPitchDetector* const detector, float sr)
+{
+ _tDualPitchDetector* p = *detector;
+ p->sampleRate = sr;
+ tPeriodDetection_setSampleRate(&p->_pd1, p->sampleRate);
+ tPitchDetector_setSampleRate(&p->_pd2, p->sampleRate);
}
static inline void compute_predicted_frequency(tDualPitchDetector* const detector)
--- a/leaf/Src/leaf-delay.c
+++ b/leaf/Src/leaf-delay.c
@@ -346,9 +346,6 @@
}
-
-
-
/// Hermite Interpolated Delay
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ LinearDelay ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
void tHermiteDelay_init (tHermiteDelay* const dl, float delay, uint32_t maxDelay, LEAF* const leaf)
--- a/leaf/Src/leaf-distortion.c
+++ b/leaf/Src/leaf-distortion.c
@@ -90,6 +90,7 @@
os->offset = offset;
os->maxRatio = maxRatio;
+ os->allowHighQuality = extraQuality;
os->ratio = os->maxRatio;
int idx = (int)(log2f(os->ratio))-1+os->offset;
os->numTaps = __leaf_tablesize_firNumTaps[idx];
@@ -318,12 +319,29 @@
else if (ratio == 2 || ratio == 4 || ratio == 8 ||
ratio == 16 || ratio == 32 || ratio == 64)
{
- os->ratio = os->ratio;
+ os->ratio = ratio;
int idx = (int)(log2f(os->ratio))-1+os->offset;
os->numTaps = __leaf_tablesize_firNumTaps[idx];
os->phaseLength = os->numTaps / os->ratio;
os->pCoeffs = (float*) __leaf_tableref_firCoeffs[idx];
}
+}
+
+void tOversampler_setQuality (tOversampler* const osr, int quality)
+{
+ _tOversampler* os = *osr;
+
+ if (!os->allowHighQuality) return;
+ int offset = 0;
+ if (quality > 0) offset = 6;
+ os->offset = offset;
+
+ if (os->ratio == 1) return;
+
+ int idx = (int)(log2f(os->ratio))-1+os->offset;
+ os->numTaps = __leaf_tablesize_firNumTaps[idx];
+ os->phaseLength = os->numTaps / os->ratio;
+ os->pCoeffs = (float*) __leaf_tableref_firCoeffs[idx];
}
int tOversampler_getLatency(tOversampler* const osr)
--- a/leaf/Src/leaf-dynamics.c
+++ b/leaf/Src/leaf-dynamics.c
@@ -51,6 +51,7 @@
_tMempool* m = *mp;
_tCompressor* c = *comp = (_tCompressor*) mpool_alloc(sizeof(_tCompressor), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
c->tauAttack = 100;
c->tauRelease = 100;
@@ -61,6 +62,8 @@
c->R = 0.5f; // compression Ratio
c->M = 3.0f; // decibel Width of knee transition
c->W = 1.0f; // decibel Make-up gain
+
+ c->sampleRate = leaf->sampleRate;
}
void tCompressor_free (tCompressor* const comp)
@@ -73,7 +76,6 @@
float tCompressor_tick(tCompressor* const comp, float in)
{
_tCompressor* c = *comp;
- LEAF* leaf = c->mempool->leaf;
float slope, overshoot;
float alphaAtt, alphaRel;
@@ -107,8 +109,8 @@
c->x_T[0] = out_db - in_db;
- alphaAtt = expf(-1.0f/(0.001f * c->tauAttack * leaf->sampleRate));
- alphaRel = expf(-1.0f/(0.001f * c->tauRelease * leaf->sampleRate));
+ alphaAtt = expf(-1.0f/(0.001f * c->tauAttack * c->sampleRate));
+ alphaRel = expf(-1.0f/(0.001f * c->tauRelease * c->sampleRate));
if (c->x_T[0] > c->y_T[1])
c->y_T[0] = alphaAtt * c->y_T[1] + (1-alphaAtt) * c->x_T[0];
--- a/leaf/Src/leaf-effects.c
+++ b/leaf/Src/leaf-effects.c
@@ -42,6 +42,7 @@
_tMempool* m = *mp;
_tTalkbox* v = *voc = (_tTalkbox*) mpool_alloc(sizeof(_tTalkbox), m);
v->mempool = m;
+ LEAF* leaf = v->mempool->leaf;
v->param[0] = 0.5f; //wet
v->param[1] = 0.0f; //dry
@@ -62,6 +63,8 @@
v->Rt = (double*) mpool_alloc(sizeof(double) * v->bufsize, m);
v->k = (float*) mpool_alloc(sizeof(float) * ORD_MAX, m);
+
+ v->sampleRate = leaf->sampleRate;
tTalkbox_update(voc);
tTalkbox_suspend(voc);
@@ -86,9 +89,8 @@
void tTalkbox_update(tTalkbox* const voc) ///update internal parameters...
{
_tTalkbox* v = *voc;
- LEAF* leaf = v->mempool->leaf;
- float fs = leaf->sampleRate;
+ float fs = v->sampleRate;
// if(fs < 8000.0f) fs = 8000.0f;
// if(fs > 96000.0f) fs = 96000.0f;
@@ -320,10 +322,9 @@
void tTalkbox_setQuality(tTalkbox* const voc, float quality)
{
_tTalkbox* v = *voc;
- LEAF* leaf = v->mempool->leaf;
v->param[3] = quality;
- v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * leaf->sampleRate);
+ v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * v->sampleRate);
if (v->O >= ORD_MAX)
{
v->O = ORD_MAX-1;
@@ -351,8 +352,13 @@
v->freeze = freeze;
}
+void tTalkbox_setSampleRate(tTalkbox* const voc, float sr)
+{
+ _tTalkbox* v = *voc;
+ v->sampleRate = sr;
+ tTalkbox_update(voc);
+}
-
////
// LPC vocoder adapted from MDA's excellent open source talkbox plugin code
@@ -374,6 +380,7 @@
_tMempool* m = *mp;
_tTalkboxFloat* v = *voc = (_tTalkboxFloat*) mpool_alloc(sizeof(_tTalkboxFloat), m);
v->mempool = m;
+ LEAF* leaf = v->mempool->leaf;
v->param[0] = 0.5f; //wet
v->param[1] = 0.0f; //dry
@@ -394,6 +401,8 @@
v->Rt = (float*) mpool_alloc(sizeof(float) * v->bufsize, m);
v->k = (float*) mpool_alloc(sizeof(float) * ORD_MAX, m);
+
+ v->sampleRate = leaf->sampleRate;
tTalkboxFloat_update(voc);
tTalkboxFloat_suspend(voc);
@@ -418,9 +427,8 @@
void tTalkboxFloat_update(tTalkboxFloat* const voc) ///update internal parameters...
{
_tTalkboxFloat* v = *voc;
- LEAF* leaf = v->mempool->leaf;
- float fs = leaf->sampleRate;
+ float fs = v->sampleRate;
// if(fs < 8000.0f) fs = 8000.0f;
// if(fs > 96000.0f) fs = 96000.0f;
@@ -656,10 +664,9 @@
void tTalkboxFloat_setQuality(tTalkboxFloat* const voc, float quality)
{
_tTalkboxFloat* v = *voc;
- LEAF* leaf = v->mempool->leaf;
v->param[3] = quality;
- v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * leaf->sampleRate);
+ v->O = (int32_t)((0.0001f + 0.0004f * v->param[3]) * v->sampleRate);
if (v->O >= ORD_MAX)
{
v->O = ORD_MAX-1;
@@ -687,6 +694,12 @@
v->freeze = freeze;
}
+void tTalkboxFloat_setSampleRate(tTalkboxFloat* const voc, float sr)
+{
+ _tTalkboxFloat* v = *voc;
+ v->sampleRate = sr;
+ tTalkboxFloat_update(voc);
+}
//============================================================================================================
// VOCODER
@@ -702,7 +715,10 @@
_tMempool* m = *mp;
_tVocoder* v = *voc = (_tVocoder*) mpool_alloc(sizeof(_tVocoder), m);
v->mempool = m;
+ LEAF* leaf = v->mempool->leaf;
+ v->invSampleRate = leaf->invSampleRate;
+
v->param[0] = 0.33f; //input select
v->param[1] = 0.50f; //output dB
v->param[2] = 0.40f; //hi thru
@@ -725,9 +741,8 @@
void tVocoder_update (tVocoder* const voc)
{
_tVocoder* v = *voc;
- LEAF* leaf = v->mempool->leaf;
- float tpofs = 6.2831853f * leaf->invSampleRate;
+ float tpofs = 6.2831853f * v->invSampleRate;
float rr, th;
@@ -871,7 +886,6 @@
if(fabs(o)>10.0f) tVocoder_suspend(voc); //catch instability
return o;
-
}
void tVocoder_suspend (tVocoder* const voc)
@@ -885,7 +899,14 @@
v->kval = 0;
}
+void tVocoder_setSampleRate (tVocoder* const voc, float sr)
+{
+ _tVocoder* v = *voc;
+ v->invSampleRate = 1.0f/sr;
+ tVocoder_update(voc);
+}
+
/// Glottal Pulse (Rosenberg model)
void tRosenbergGlottalPulse_init (tRosenbergGlottalPulse* const gp, LEAF* const leaf)
@@ -898,6 +919,9 @@
_tMempool* m = *mp;
_tRosenbergGlottalPulse* g = *gp = (_tRosenbergGlottalPulse*) mpool_alloc(sizeof(_tRosenbergGlottalPulse), m);
g->mempool = m;
+ LEAF* leaf = g->mempool->leaf;
+
+ g->invSampleRate = leaf->invSampleRate;
g->phase = 0.0f;
g->openLength = 0.0f;
@@ -972,10 +996,9 @@
void tRosenbergGlottalPulse_setFreq (tRosenbergGlottalPulse* const gp, float freq)
{
_tRosenbergGlottalPulse* g = *gp;
- LEAF* leaf = g->mempool->leaf;
g->freq = freq;
- g->inc = freq * leaf->invSampleRate;
+ g->inc = freq * g->invSampleRate;
g->inc -= (int) g->inc;
}
@@ -1001,6 +1024,12 @@
g->invPulseLengthMinusOpenLength = 1.0f / (g->pulseLength - g->openLength);
}
+void tRosenbergGlottalPulse_setSampleRate(tRosenbergGlottalPulse* const gp, float sr)
+{
+ _tRosenbergGlottalPulse* g = *gp;
+ g->invSampleRate = 1.0f/sr;
+ tRosenbergGlottalPulse_setFreq(gp, g->freq);
+}
//============================================================================================================
@@ -1140,6 +1169,13 @@
w->blocksize = INITPERIOD;
}
+void tSOLAD_setSampleRate(tSOLAD* const wp, float sr)
+{
+ _tSOLAD* w = *wp;
+ tAttackDetection_setSampleRate(&w->ad, sr);
+ tHighpass_setSampleRate(&w->hp, sr);
+}
+
/******************************************************************************/
/******************** private procedures **************************************/
/******************************************************************************/
@@ -1380,11 +1416,14 @@
_tMempool* m = *mp;
_tPitchShift* ps = *psr = (_tPitchShift*) mpool_alloc(sizeof(_tPitchShift), m);
ps->mempool = m;
+ LEAF* leaf = ps->mempool->leaf;
ps->pd = *dpd;
ps->bufSize = bufSize;
ps->pickiness = 0.0f;
+ ps->sampleRate = leaf->sampleRate;
+
tSOLAD_initToPool(&ps->sola, pow(2.0, ceil(log2(ps->bufSize * 2.0))), mp);
tSOLAD_setPitchFactor(&ps->sola, DEFPITCHRATIO);
}
@@ -1400,13 +1439,12 @@
void tPitchShift_shiftBy (tPitchShift* const psr, float factor, float* in, float* out)
{
_tPitchShift* ps = *psr;
- LEAF* leaf = ps->mempool->leaf;
float detected = tDualPitchDetector_getFrequency(&ps->pd);
float periodicity = tDualPitchDetector_getPeriodicity(&ps->pd);
if (detected > 0.0f && periodicity > ps->pickiness)
{
- float period = leaf->sampleRate / detected;
+ float period = ps->sampleRate / detected;
tSOLAD_setPeriod(&ps->sola, period);
tSOLAD_setPitchFactor(&ps->sola, factor);
}
@@ -1417,7 +1455,6 @@
void tPitchShift_shiftTo (tPitchShift* const psr, float freq, float* in, float* out)
{
_tPitchShift* ps = *psr;
- LEAF* leaf = ps->mempool->leaf;
float detected = tDualPitchDetector_getFrequency(&ps->pd);
float periodicity = tDualPitchDetector_getPeriodicity(&ps->pd);
@@ -1425,7 +1462,7 @@
{
float period = 1.0f / detected;
float factor = freq * period;
- tSOLAD_setPeriod(&ps->sola, leaf->sampleRate * period);
+ tSOLAD_setPeriod(&ps->sola, ps->sampleRate * period);
tSOLAD_setPitchFactor(&ps->sola, factor);
}
@@ -1435,11 +1472,16 @@
void tPitchShift_setPickiness (tPitchShift* const psr, float p)
{
_tPitchShift* ps = *psr;
-
ps->pickiness = p;
}
+void tPitchShift_setSampleRate(tPitchShift* const psr, float sr)
+{
+ _tPitchShift* ps = *psr;
+ tSOLAD_setSampleRate(&ps->sola, sr);
+}
+
//============================================================================================================
// SIMPLERETUNE
//============================================================================================================
@@ -1571,6 +1613,16 @@
return tDualPitchDetector_getFrequency(&r->dp);
}
+void tSimpleRetune_setSampleRate (tSimpleRetune* const rt, float sr)
+{
+ _tSimpleRetune* r = *rt;
+ tDualPitchDetector_setSampleRate(&r->dp, sr);
+ for (int i = 0; i < r->numVoices; ++i)
+ {
+ tPitchShift_setSampleRate(&r->ps[i], sr);
+ }
+}
+
//============================================================================================================
// RETUNE
//============================================================================================================
@@ -1708,6 +1760,16 @@
return tDualPitchDetector_getFrequency(&r->dp);
}
+void tRetune_setSampleRate(tRetune* const rt, float sr)
+{
+ _tRetune* r = *rt;
+ tDualPitchDetector_setSampleRate(&r->dp, sr);
+ for (int i = 0; i < r->numVoices; ++i)
+ {
+ tPitchShift_setSampleRate(&r->ps[i], sr);
+ }
+}
+
//============================================================================================================
// FORMANTSHIFTER
//============================================================================================================
@@ -1738,14 +1800,16 @@
fs->fbuff = (float*) mpool_calloc(sizeof(float*) * fs->ford, m);
+ fs->sampleRate = leaf->sampleRate;
+ fs->invSampleRate = leaf->invSampleRate;
- fs->falph = powf(0.001f, 10.0f * leaf->invSampleRate);
- fs->flamb = -(0.8517f*sqrtf(atanf(0.06583f * leaf->sampleRate)) - 0.1916f);
+ fs->falph = powf(0.001f, 10.0f * fs->invSampleRate);
+ fs->flamb = -(0.8517f*sqrtf(atanf(0.06583f * fs->sampleRate)) - 0.1916f);
fs->fhp = 0.0f;
fs->flp = 0.0f;
- fs->flpa = powf(0.001f, 10.0f * leaf->invSampleRate);
+ fs->flpa = powf(0.001f, 10.0f * fs->invSampleRate);
fs->fmute = 1.0f;
- fs->fmutealph = powf(0.001f, 1.0f * leaf->invSampleRate);
+ fs->fmutealph = powf(0.001f, 1.0f * fs->invSampleRate);
fs->cbi = 0;
fs->intensity = 1.0f;
fs->invIntensity = 1.0f;
@@ -1927,8 +1991,6 @@
{
_tFormantShifter* fs = *fsr;
-
-
fs->intensity = LEAF_clip(1.0f, intensity, 100.0f);
// tFeedbackLeveler_setTargetLevel(&fs->fbl1, fs->intensity);
@@ -1942,5 +2004,17 @@
{
fs->invIntensity = 1.0f;
}
+}
+void tFormantShifter_setSampleRate(tFormantShifter* const fsr, float sr)
+{
+ _tFormantShifter* fs = *fsr;
+ fs->sampleRate = sr;
+ fs->invSampleRate = 1.0f/fs->sampleRate;
+ fs->falph = powf(0.001f, 10.0f * fs->invSampleRate);
+ fs->flamb = -(0.8517f*sqrtf(atanf(0.06583f * fs->sampleRate)) - 0.1916f);
+ fs->flpa = powf(0.001f, 10.0f * fs->invSampleRate);
+ fs->fmutealph = powf(0.001f, 1.0f * fs->invSampleRate);
+ tHighpass_setSampleRate(&fs->hp, fs->sampleRate);
+ tHighpass_setSampleRate(&fs->hp2, fs->sampleRate);
}
--- a/leaf/Src/leaf-electrical.c
+++ b/leaf/Src/leaf-electrical.c
@@ -222,6 +222,16 @@
{
_tWDF* r = *wdf;
r->sample_rate = sample_rate;
+ if (r->type == Capacitor)
+ {
+ r->port_conductance_up = r->sample_rate * 2.0f * r->value;
+ r->port_resistance_up = 1.0f / r->port_conductance_up; //based on trapezoidal discretization
+ }
+ else if (r->type == Inductor)
+ {
+ r->port_resistance_up = r->sample_rate * 2.0f * r->value; //based on trapezoidal discretization
+ r->port_conductance_up = 1.0f / r->port_resistance_up;
+ }
}
uint8_t tWDF_isLeaf(tWDF* const wdf)
--- a/leaf/Src/leaf-envelopes.c
+++ b/leaf/Src/leaf-envelopes.c
@@ -118,7 +118,6 @@
env->loop = loop;
}
-
void tEnvelope_on(tEnvelope* const envlp, float velocity)
{
_tEnvelope* env = *envlp;
@@ -495,7 +494,6 @@
return (rate <= 0.0f) ? 0.0f : expf(-logf((1.0f + targetRatio) / targetRatio) / rate);
}
-
void tADSRS_init(tADSRS* const adsrenv, float attack, float decay, float sustain, float release, LEAF* const leaf)
{
tADSRS_initToPool(adsrenv, attack, decay, sustain, release, &leaf->mempool);
@@ -509,13 +507,16 @@
LEAF* leaf = adsr->mempool->leaf;
- adsr->sampleRateInMs = leaf->sampleRate * 0.001f;
+ adsr->sampleRate = leaf->sampleRate;
+ adsr->sampleRateInMs = adsr->sampleRate * 0.001f;
adsr->targetRatioA = 0.3f;
adsr->targetRatioDR = 0.0001f;
+ adsr->attack = attack;
adsr->attackRate = attack * adsr->sampleRateInMs;
adsr->attackCoef = calcADSR3Coef(attack * adsr->sampleRateInMs, adsr->targetRatioA);
adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef);
+ adsr->decay = decay;
adsr->decayRate = decay * adsr->sampleRateInMs;
adsr->decayCoef = calcADSR3Coef(decay * adsr->sampleRateInMs,adsr-> targetRatioDR);
adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
@@ -523,6 +524,7 @@
adsr->sustainLevel = sustain;
adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
+ adsr->release = release;
adsr->releaseRate = release * adsr->sampleRateInMs;
adsr->releaseCoef = calcADSR3Coef(release * adsr->sampleRateInMs, adsr->targetRatioDR);
adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef);
@@ -546,6 +548,7 @@
{
_tADSRS* adsr = *adsrenv;
+ adsr->attack = attack;
adsr->attackRate = attack * adsr->sampleRateInMs;
adsr->attackCoef = calcADSR3Coef(adsr->attackRate, adsr->targetRatioA);
adsr->attackBase = (1.0f + adsr->targetRatioA) * (1.0f - adsr->attackCoef);
@@ -555,6 +558,7 @@
{
_tADSRS* adsr = *adsrenv;
+ adsr->decay = decay;
adsr->decayRate = decay * adsr->sampleRateInMs;
adsr->decayCoef = calcADSR3Coef(adsr->decayRate,adsr-> targetRatioDR);
adsr->decayBase = (adsr->sustainLevel - adsr->targetRatioDR) * (1.0f - adsr->decayCoef);
@@ -572,6 +576,7 @@
{
_tADSRS* adsr = *adsrenv;
+ adsr->release = release;
adsr->releaseRate = release * adsr->sampleRateInMs;
adsr->releaseCoef = calcADSR3Coef(adsr->releaseRate, (float)adsr->targetRatioDR);
adsr->releaseBase = -adsr->targetRatioDR * (1.0f - adsr->releaseCoef);
@@ -581,7 +586,6 @@
void tADSRS_setLeakFactor(tADSRS* const adsrenv, float leakFactor)
{
_tADSRS* adsr = *adsrenv;
-
adsr->leakFactor = leakFactor;
}
@@ -606,7 +610,6 @@
{
_tADSRS* adsr = *adsrenv;
-
switch (adsr->state) {
case env_idle:
break;
@@ -641,7 +644,20 @@
return adsr->output * adsr->gain;
}
+void tADSRS_setSampleRate(tADSRS* const adsrenv, float sr)
+{
+ _tADSRS* adsr = *adsrenv;
+
+ adsr->sampleRate = sr;
+ adsr->sampleRateInMs = adsr->sampleRate * 0.001f;
+
+ tADSRS_setAttack(adsrenv, adsr->attack);
+ tADSRS_setDecay(adsrenv, adsr->decay);
+ tADSRS_setRelease(adsrenv, adsr->release);
+}
+//================================================================================
+
/* ADSR 4 */ // new version of our original table-based ADSR but with the table passed in by the user
// use this if the size of the big ADSR tables is too much.
void tADSRT_init (tADSRT* const adsrenv, float attack, float decay, float sustain, float release, float* expBuffer, int bufferSize, LEAF* const leaf)
@@ -663,7 +679,8 @@
adsr->buff_size = bufferSize;
adsr->buff_sizeMinusOne = bufferSize - 1;
- adsr->bufferSizeDividedBySampleRateInMs = bufferSize / (leaf->sampleRate * 0.001f);
+ adsr->sampleRate = leaf->sampleRate;
+ adsr->bufferSizeDividedBySampleRateInMs = adsr->buff_size / (adsr->sampleRate * 0.001f);
if (attack < 0.0f)
attack = 0.0f;
@@ -685,6 +702,9 @@
adsr->sustain = sustain;
+ adsr->attack = attack;
+ adsr->decay = decay;
+ adsr->release = release;
adsr->attackInc = adsr->bufferSizeDividedBySampleRateInMs / attack;
adsr->decayInc = adsr->bufferSizeDividedBySampleRateInMs / decay;
adsr->releaseInc = adsr->bufferSizeDividedBySampleRateInMs / release;
@@ -707,7 +727,7 @@
{
attack = 0.0f;
}
-
+ adsr->attack = attack;
adsr->attackInc = adsr->bufferSizeDividedBySampleRateInMs / attack;
}
@@ -719,6 +739,7 @@
{
decay = 0.0f;
}
+ adsr->decay = decay;
adsr->decayInc = adsr->bufferSizeDividedBySampleRateInMs / decay;
}
@@ -739,6 +760,7 @@
{
release = 0.0f;
}
+ adsr->release = release;
adsr->releaseInc = adsr->bufferSizeDividedBySampleRateInMs / release;
}
@@ -988,8 +1010,18 @@
return adsr->next;
}
+void tADSRT_setSampleRate (tADSRT* const adsrenv, float sr)
+{
+ _tADSRT* adsr = *adsrenv;
+
+ adsr->sampleRate = sr;
+ adsr->bufferSizeDividedBySampleRateInMs = adsr->buff_size / (adsr->sampleRate * 0.001f);
+ adsr->attackInc = adsr->bufferSizeDividedBySampleRateInMs / adsr->attack;
+ adsr->decayInc = adsr->bufferSizeDividedBySampleRateInMs / adsr->decay;
+ adsr->releaseInc = adsr->bufferSizeDividedBySampleRateInMs / adsr->release;
+ adsr->rampInc = adsr->bufferSizeDividedBySampleRateInMs / 8.0f;
+}
-
/////-----------------
/* Ramp */
void tRamp_init(tRamp* const r, float time, int samples_per_tick, LEAF* const leaf)
@@ -1005,7 +1037,8 @@
LEAF* leaf = ramp->mempool->leaf;
- ramp->inv_sr_ms = 1.0f/(leaf->sampleRate*0.001f);
+ ramp->sampleRate = leaf->sampleRate;
+ ramp->inv_sr_ms = 1.0f/(ramp->sampleRate*0.001f);
ramp->minimum_time = ramp->inv_sr_ms * samples_per_tick;
ramp->curr = 0.0f;
ramp->dest = 0.0f;
@@ -1026,7 +1059,6 @@
void tRamp_free (tRamp* const r)
{
_tRamp* ramp = *r;
-
mpool_free((char*)ramp, ramp->mempool);
}
@@ -1082,18 +1114,18 @@
return r->curr;
}
-void tRampSampleRateChanged(tRamp* const ramp)
+void tRamp_setSampleRate(tRamp* const ramp, float sr)
{
_tRamp* r = *ramp;
- LEAF* leaf = r->mempool->leaf;
- r->inv_sr_ms = 1.0f / (leaf->sampleRate * 0.001f);
+ r->sampleRate = sr;
+ r->inv_sr_ms = 1.0f / (r->sampleRate * 0.001f);
r->factor = (1.0f / r->time) * r->inv_sr_ms * (float)r->samples_per_tick;
r->inc = (r->dest - r->curr) * r->factor;
}
+//===========================================================================================
-
/* RampUpDown */
void tRampUpDown_init(tRampUpDown* const r, float upTime, float downTime, int samples_per_tick, LEAF* const leaf)
{
@@ -1108,7 +1140,8 @@
LEAF* leaf = ramp->mempool->leaf;
- ramp->inv_sr_ms = 1.0f/(leaf->sampleRate*0.001f);
+ ramp->sampleRate = leaf->sampleRate;
+ ramp->inv_sr_ms = 1.0f/(ramp->sampleRate*0.001f);
ramp->minimum_time = ramp->inv_sr_ms * samples_per_tick;
ramp->curr = 0.0f;
ramp->dest = 0.0f;
@@ -1139,7 +1172,6 @@
void tRampUpDown_free (tRampUpDown* const r)
{
_tRampUpDown* ramp = *r;
-
mpool_free((char*)ramp, ramp->mempool);
}
@@ -1258,7 +1290,6 @@
void tExpSmooth_free (tExpSmooth* const expsmooth)
{
_tExpSmooth* smooth = *expsmooth;
-
mpool_free((char*)smooth, smooth->mempool);
}
@@ -1340,7 +1371,6 @@
void tSlide_free (tSlide* const sl)
{
_tSlide* s = *sl;
-
mpool_free((char*)s, s->mempool);
}
--- a/leaf/Src/leaf-filters.c
+++ b/leaf/Src/leaf-filters.c
@@ -1,11 +1,11 @@
/*==============================================================================
+
+ leaf-filter.c
+ Created: 20 Jan 2017 12:01:10pm
+ Author: Michael R Mulshine
+
+ ==============================================================================*/
- leaf-filter.c
- Created: 20 Jan 2017 12:01:10pm
- Author: Michael R Mulshine
-
-==============================================================================*/
-
#if _WIN32 || _WIN64
#include "..\Inc\leaf-filters.h"
@@ -85,14 +85,17 @@
_tMempool* m = *mp;
_tOnePole* f = *ft = (_tOnePole*) mpool_alloc(sizeof(_tOnePole), m);
f->mempool = m;
+ LEAF* leaf = f->mempool->leaf;
f->gain = 1.0f;
f->a0 = 1.0;
- tOnePole_setFreq(ft, freq);
-
f->lastIn = 0.0f;
f->lastOut = 0.0f;
+
+ f->twoPiTimesInvSampleRate = leaf->twoPiTimesInvSampleRate;
+
+ tOnePole_setFreq(ft, freq);
}
void tOnePole_free (tOnePole* const ft)
@@ -131,9 +134,9 @@
void tOnePole_setFreq (tOnePole* const ft, float freq)
{
_tOnePole* f = *ft;
- LEAF* leaf = f->mempool->leaf;
- f->b0 = freq * leaf->twoPiTimesInvSampleRate;
+ f->freq = freq;
+ f->b0 = f->freq * f->twoPiTimesInvSampleRate;
f->b0 = LEAF_clip(0.0f, f->b0, 1.0f);
f->a1 = 1.0f - f->b0;
}
@@ -165,6 +168,15 @@
return out;
}
+void tOnePole_setSampleRate(tOnePole* const ft, float sr)
+{
+ _tOnePole* f = *ft;
+ f->twoPiTimesInvSampleRate = (1.0f/sr) * TWO_PI;
+ f->b0 = f->freq * f->twoPiTimesInvSampleRate;
+ f->b0 = LEAF_clip(0.0f, f->b0, 1.0f);
+ f->a1 = 1.0f - f->b0;
+}
+
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TwoPole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
void tTwoPole_init(tTwoPole* const ft, LEAF* const leaf)
{
@@ -176,6 +188,7 @@
_tMempool* m = *mp;
_tTwoPole* f = *ft = (_tTwoPole*) mpool_alloc(sizeof(_tTwoPole), m);
f->mempool = m;
+ LEAF* leaf = f->mempool->leaf;
f->gain = 1.0f;
f->a0 = 1.0;
@@ -183,12 +196,14 @@
f->lastOut[0] = 0.0f;
f->lastOut[1] = 0.0f;
+
+ f->sampleRate = leaf->sampleRate;
+ f->twoPiTimesInvSampleRate = leaf->twoPiTimesInvSampleRate;
}
void tTwoPole_free (tTwoPole* const ft)
{
_tTwoPole* f = *ft;
-
mpool_free((char*)f, f->mempool);
}
@@ -223,14 +238,12 @@
f->a2 = a2;
}
-
void tTwoPole_setResonance(tTwoPole* const ft, float frequency, float radius, int normalize)
{
_tTwoPole* f = *ft;
- LEAF* leaf = f->mempool->leaf;
- float sampleRate = leaf->sampleRate;
- float twoPiTimesInvSampleRate = leaf->twoPiTimesInvSampleRate;
+ float sampleRate = f->sampleRate;
+ float twoPiTimesInvSampleRate = f->twoPiTimesInvSampleRate;
if (frequency < 0.0f) frequency = 0.0f;
if (frequency > (sampleRate * 0.49f)) frequency = sampleRate * 0.49f;
@@ -267,21 +280,20 @@
f->gain = gain;
}
-void tTwoPoleSampleRateChanged (tTwoPole* const ft)
+void tTwoPole_setSampleRate (tTwoPole* const ft, float sr)
{
_tTwoPole* f = *ft;
- LEAF* leaf = f->mempool->leaf;
- float twoPiTimesInvSampleRate = leaf->twoPiTimesInvSampleRate;
+ f->twoPiTimesInvSampleRate = (1.0f/sr) * TWO_PI;
f->a2 = f->radius * f->radius;
- f->a1 = -2.0f * f->radius * cosf(f->frequency * twoPiTimesInvSampleRate);
+ f->a1 = -2.0f * f->radius * cosf(f->frequency * f->twoPiTimesInvSampleRate);
if ( f->normalize )
{
// Normalize the filter gain ... not terribly efficient.
- float real = 1 - f->radius + (f->a2 - f->radius) * cosf(2 * f->frequency * twoPiTimesInvSampleRate);
- float imag = (f->a2 - f->radius) * sinf(2 * f->frequency * twoPiTimesInvSampleRate);
+ float real = 1 - f->radius + (f->a2 - f->radius) * cosf(2 * f->frequency * f->twoPiTimesInvSampleRate);
+ float imag = (f->a2 - f->radius) * sinf(2 * f->frequency * f->twoPiTimesInvSampleRate);
f->b0 = sqrtf( powf(real, 2) + powf(imag, 2) );
}
}
@@ -297,10 +309,12 @@
_tMempool* m = *mp;
_tOneZero* f = *ft = (_tOneZero*) mpool_alloc(sizeof(_tOneZero), m);
f->mempool = m;
+ LEAF* leaf = f->mempool->leaf;
f->gain = 1.0f;
f->lastIn = 0.0f;
f->lastOut = 0.0f;
+ f->invSampleRate = leaf->invSampleRate;
tOneZero_setZero(ft, theZero);
}
@@ -307,7 +321,6 @@
void tOneZero_free (tOneZero* const ft)
{
_tOneZero* f = *ft;
-
mpool_free((char*)f, f->mempool);
}
@@ -363,13 +376,12 @@
float tOneZero_getPhaseDelay(tOneZero* const ft, float frequency )
{
_tOneZero* f = *ft;
- LEAF* leaf = f->mempool->leaf;
if ( frequency <= 0.0f) frequency = 0.05f;
f->frequency = frequency;
- float omegaT = 2 * PI * frequency * leaf->invSampleRate;
+ float omegaT = 2 * PI * frequency * f->invSampleRate;
float real = 0.0, imag = 0.0;
real += f->b0;
@@ -391,6 +403,12 @@
return phase / omegaT;
}
+void tOneZero_setSampleRate (tOneZero* const ft, float sr)
+{
+ _tOneZero* f = *ft;
+ f->invSampleRate = 1.0f/sr;
+}
+
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ TwoZero Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
void tTwoZero_init(tTwoZero* const ft, LEAF* const leaf)
{
@@ -402,7 +420,9 @@
_tMempool* m = *mp;
_tTwoZero* f = *ft = (_tTwoZero*) mpool_alloc(sizeof(_tTwoZero), m);
f->mempool = m;
+ LEAF* leaf = f->mempool->leaf;
+ f->twoPiTimesInvSampleRate = leaf->twoPiTimesInvSampleRate;
f->gain = 1.0f;
f->lastIn[0] = 0.0f;
f->lastIn[1] = 0.0f;
@@ -411,7 +431,6 @@
void tTwoZero_free (tTwoZero* const ft)
{
_tTwoZero* f = *ft;
-
mpool_free((char*)f, f->mempool);
}
@@ -431,7 +450,6 @@
void tTwoZero_setNotch(tTwoZero* const ft, float freq, float radius)
{
_tTwoZero* f = *ft;
- LEAF* leaf = f->mempool->leaf;
// Should also deal with frequency being > half sample rate / nyquist. See STK
if (freq < 0.0f) freq = 0.0f;
@@ -441,7 +459,7 @@
f->radius = radius;
f->b2 = radius * radius;
- f->b1 = -2.0f * radius * cosf(freq * leaf->twoPiTimesInvSampleRate); // OPTIMIZE with LOOKUP or APPROXIMATION
+ f->b1 = -2.0f * radius * cosf(freq * f->twoPiTimesInvSampleRate); // OPTIMIZE with LOOKUP or APPROXIMATION
// Normalize the filter gain. From STK.
if ( f->b1 > 0.0f ) // Maximum at z = 0.
@@ -479,10 +497,11 @@
f->gain = gain;
}
-void tTwoZeroSampleRateChanged(tTwoZero* const ft)
+void tTwoZero_setSampleRate(tTwoZero* const ft, float sr)
{
_tTwoZero* f = *ft;
+ f->twoPiTimesInvSampleRate = TWO_PI * (1.0f/sr);
tTwoZero_setNotch(ft, f->frequency, f->radius);
}
@@ -509,7 +528,6 @@
void tPoleZero_free (tPoleZero* const pzf)
{
_tPoleZero* f = *pzf;
-
mpool_free((char*)f, f->mempool);
}
@@ -611,6 +629,7 @@
_tMempool* m = *mp;
_tBiQuad* f = *ft = (_tBiQuad*) mpool_alloc(sizeof(_tBiQuad), m);
f->mempool = m;
+ LEAF* leaf = f->mempool->leaf;
f->gain = 1.0f;
@@ -621,12 +640,13 @@
f->lastIn[1] = 0.0f;
f->lastOut[0] = 0.0f;
f->lastOut[1] = 0.0f;
+
+ f->twoPiTimesInvSampleRate = leaf->twoPiTimesInvSampleRate;
}
void tBiQuad_free (tBiQuad* const ft)
{
_tBiQuad* f = *ft;
-
mpool_free((char*)f, f->mempool);
}
@@ -650,11 +670,10 @@
void tBiQuad_setResonance(tBiQuad* const ft, float freq, float radius, int normalize)
{
_tBiQuad* f = *ft;
- LEAF* leaf = f->mempool->leaf;
if (freq < 0.0f) freq = 0.0f;
- if (freq > (leaf->sampleRate * 0.49f))
- freq = leaf->sampleRate * 0.49f;
+ if (freq > (f->sampleRate * 0.49f))
+ freq = f->sampleRate * 0.49f;
if (radius < 0.0f) radius = 0.0f;
if (radius >= 1.0f) radius = 1.0f;
@@ -663,7 +682,7 @@
f->normalize = normalize;
f->a2 = radius * radius;
- f->a1 = -2.0f * radius * cosf(freq * leaf->twoPiTimesInvSampleRate);
+ f->a1 = -2.0f * radius * cosf(freq * f->twoPiTimesInvSampleRate);
if (normalize)
{
@@ -676,15 +695,14 @@
void tBiQuad_setNotch(tBiQuad* const ft, float freq, float radius)
{
_tBiQuad* f = *ft;
- LEAF* leaf = f->mempool->leaf;
if (freq < 0.0f) freq = 0.0f;
- if (freq > (leaf->sampleRate * 0.49f))
- freq = leaf->sampleRate * 0.49f;
+ if (freq > (f->sampleRate * 0.49f))
+ freq = f->sampleRate * 0.49f;
if (radius < 0.0f) radius = 0.0f;
f->b2 = radius * radius;
- f->b1 = -2.0f * radius * cosf(freq * leaf->twoPiTimesInvSampleRate); // OPTIMIZE with LOOKUP or APPROXIMATION
+ f->b1 = -2.0f * radius * cosf(freq * f->twoPiTimesInvSampleRate); // OPTIMIZE with LOOKUP or APPROXIMATION
// Does not attempt to normalize filter gain.
}
@@ -743,13 +761,15 @@
f->gain = gain;
}
-void tBiQuadSampleRateChanged(tBiQuad* const ft)
+void tBiQuad_setSampleRate(tBiQuad* const ft, float sr)
{
_tBiQuad* f = *ft;
- LEAF* leaf = f->mempool->leaf;
+ f->sampleRate = sr;
+ f->twoPiTimesInvSampleRate = TWO_PI * (1.0f/f->sampleRate);
+
f->a2 = f->radius * f->radius;
- f->a1 = -2.0f * f->radius * cosf(f->frequency * leaf->twoPiTimesInvSampleRate);
+ f->a1 = -2.0f * f->radius * cosf(f->frequency * f->twoPiTimesInvSampleRate);
if (f->normalize)
{
@@ -764,12 +784,10 @@
void tSVF_init(tSVF* const svff, SVFType type, float freq, float Q, LEAF* const leaf)
{
tSVF_initToPool (svff, type, freq, Q, &leaf->mempool);
-
// or maybe this?
/*
* hp=1 bp=A/Q (where A is 10^(G/40) and G is gain in decibels) and lp = 1
*/
-
}
void tSVF_initToPool (tSVF* const svff, SVFType type, float freq, float Q, tMempool* const mp)
@@ -779,14 +797,17 @@
svf->mempool = m;
LEAF* leaf = svf->mempool->leaf;
-
+
+ svf->sampleRate = leaf->sampleRate;
+ svf->invSampleRate = leaf->invSampleRate;
+
svf->type = type;
-
+
svf->ic1eq = 0;
svf->ic2eq = 0;
svf->Q = Q;
svf->cutoff = freq;
- svf->g = tanf(PI * freq * leaf->invSampleRate);
+ svf->g = tanf(PI * freq * svf->invSampleRate);
svf->k = 1.0f/Q;
svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
svf->a2 = svf->g*svf->a1;
@@ -796,7 +817,7 @@
svf->cB = 0.0f;
svf->cBK = 0.0f;
svf->cL = 1.0f;
-
+
if (type == SVFTypeLowpass)
{
svf->cH = 0.0f;
@@ -811,7 +832,7 @@
svf->cBK = 0.0f;
svf->cL = 0.0f;
}
-
+
else if (type == SVFTypeHighpass)
{
svf->cH = 1.0f;
@@ -819,7 +840,7 @@
svf->cBK = -1.0f;
svf->cL = -1.0f;
}
-
+
else if (type == SVFTypeNotch)
{
svf->cH = 1.0f;
@@ -827,7 +848,7 @@
svf->cBK = -1.0f;
svf->cL = 0.0f;
}
-
+
else if (type == SVFTypePeak)
{
svf->cH = 1.0f;
@@ -840,7 +861,6 @@
void tSVF_free (tSVF* const svff)
{
_tSVF* svf = *svff;
-
mpool_free((char*)svf, svf->mempool);
}
@@ -866,10 +886,9 @@
void tSVF_setFreq(tSVF* const svff, float freq)
{
_tSVF* svf = *svff;
- LEAF* leaf = svf->mempool->leaf;
- svf->cutoff = LEAF_clip(0.0f, freq, leaf->sampleRate * 0.5f);
- svf->g = tanf(PI * svf->cutoff * leaf->invSampleRate);
+ svf->cutoff = LEAF_clip(0.0f, freq, svf->sampleRate * 0.5f);
+ svf->g = tanf(PI * svf->cutoff * svf->invSampleRate);
svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
svf->a2 = svf->g * svf->a1;
svf->a3 = svf->g * svf->a2;
@@ -880,7 +899,7 @@
_tSVF* svf = *svff;
svf->Q = Q;
svf->k = 1.0f/Q;
-
+
svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
svf->a2 = svf->g * svf->a1;
svf->a3 = svf->g * svf->a2;
@@ -889,16 +908,23 @@
void tSVF_setFreqAndQ(tSVF* const svff, float freq, float Q)
{
_tSVF* svf = *svff;
- LEAF* leaf = svf->mempool->leaf;
- svf->cutoff = LEAF_clip(0.0f, freq, leaf->sampleRate * 0.5f);
+ svf->cutoff = LEAF_clip(0.0f, freq, svf->sampleRate * 0.5f);
svf->k = 1.0f/Q;
- svf->g = tanf(PI * svf->cutoff * leaf->invSampleRate);
+ svf->g = tanf(PI * svf->cutoff * svf->invSampleRate);
svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k));
svf->a2 = svf->g * svf->a1;
svf->a3 = svf->g * svf->a2;
}
+void tSVF_setSampleRate (tSVF* const svff, float sr)
+{
+ _tSVF* svf = *svff;
+ svf->sampleRate = sr;
+ svf->invSampleRate = 1.0f/svf->sampleRate;
+ tSVF_setFreq(svff, svf->cutoff);
+}
+
#if LEAF_INCLUDE_FILTERTAN_TABLE
// Efficient version of tSVF where frequency is set based on 12-bit integer input for lookup in tanh wavetable.
void tEfficientSVF_init(tEfficientSVF* const svff, SVFType type, uint16_t input, float Q, LEAF* const leaf)
@@ -927,7 +953,6 @@
void tEfficientSVF_free (tEfficientSVF* const svff)
{
_tEfficientSVF* svf = *svff;
-
mpool_free((char*)svf, svf->mempool);
}
@@ -983,10 +1008,10 @@
_tMempool* m = *mp;
_tHighpass* f = *ft = (_tHighpass*) mpool_calloc(sizeof(_tHighpass), m);
f->mempool = m;
-
LEAF* leaf = f->mempool->leaf;
- f->R = (1.0f - (freq * leaf->twoPiTimesInvSampleRate));
+ f->twoPiTimesInvSampleRate = leaf->twoPiTimesInvSampleRate;
+ f->R = (1.0f - (freq * f->twoPiTimesInvSampleRate));
f->ys = 0.0f;
f->xs = 0.0f;
@@ -996,7 +1021,6 @@
void tHighpass_free (tHighpass* const ft)
{
_tHighpass* f = *ft;
-
mpool_free((char*)f, f->mempool);
}
@@ -1003,11 +1027,9 @@
void tHighpass_setFreq(tHighpass* const ft, float freq)
{
_tHighpass* f = *ft;
- LEAF* leaf = f->mempool->leaf;
f->frequency = freq;
- f->R = (1.0f - (freq * leaf->twoPiTimesInvSampleRate));
-
+ f->R = (1.0f - (freq * f->twoPiTimesInvSampleRate));
}
float tHighpass_getFreq(tHighpass* const ft)
@@ -1025,12 +1047,11 @@
return f->ys;
}
-void tHighpassSampleRateChanged(tHighpass* const ft)
+void tHighpass_setSampleRate(tHighpass* const ft, float sr)
{
_tHighpass* f = *ft;
- LEAF* leaf = f->mempool->leaf;
-
- f->R = (1.0f-((f->frequency * 2.0f * 3.14f) * leaf->invSampleRate));
+ f->twoPiTimesInvSampleRate = TWO_PI * (1.0f/sr);
+ f->R = (1.0f - (f->frequency * f->twoPiTimesInvSampleRate));
}
void tButterworth_init(tButterworth* const ft, int order, float f1, float f2, LEAF* const leaf)
@@ -1068,8 +1089,7 @@
{
_tButterworth* f = *ft;
- for(int i = 0; i < f->numSVF; ++i)
- tSVF_free(&f->svf[i]);
+ for (int i = 0; i < f->numSVF; ++i) tSVF_free(&f->svf[i]);
mpool_free((char*)f->svf, f->mempool);
mpool_free((char*)f, f->mempool);
@@ -1080,7 +1100,7 @@
_tButterworth* f = *ft;
for(int i = 0; i < f->numSVF; ++i)
- samp = tSVF_tick(&f->svf[i], samp);
+ samp = tSVF_tick(&f->svf[i], samp);
return samp;
}
@@ -1109,18 +1129,18 @@
void tButterworth_setFreqs(tButterworth* const ft, float f1, float f2)
{
-// _tButterworth* f = *ft;
tButterworth_setF1(ft, f1);
- tButterworth_setF1(ft, f2);
-// f->f1 = f1;
-// f->f2 = f2;
-// for(int i = 0; i < ((f->N)/2); ++i)
-// {
-// tSVF_setFreq(&f->low[i], f1);
-// tSVF_setFreq(&f->high[i], f2);
-// }
+ tButterworth_setF2(ft, f2);
}
+void tButterworth_setSampleRate (tButterworth* const ft, float sr)
+{
+ _tButterworth* f = *ft;
+ for (int i = 0; i < f->numSVF; ++i) tSVF_setSampleRate(&f->svf[i], sr);
+}
+
+//================================================================================
+
void tFIR_init(tFIR* const firf, float* coeffs, int numTaps, LEAF* const leaf)
{
tFIR_initToPool(firf, coeffs, numTaps, &leaf->mempool);
@@ -1173,7 +1193,7 @@
_tMempool* m = *mp;
_tMedianFilter* f = *mf = (_tMedianFilter*) mpool_alloc(sizeof(_tMedianFilter), m);
f->mempool = m;
-
+
f->size = size;
f->middlePosition = size / 2;
f->last = size - 1;
@@ -1185,12 +1205,12 @@
f->val[i] = 0.0f;
f->age[i] = i;
}
-
+
}
void tMedianFilter_free (tMedianFilter* const mf)
{
_tMedianFilter* f = *mf;
-
+
mpool_free((char*)f->val, f->mempool);
mpool_free((char*)f->age, f->mempool);
mpool_free((char*)f, f->mempool);
@@ -1199,7 +1219,7 @@
float tMedianFilter_tick (tMedianFilter* const mf, float input)
{
_tMedianFilter* f = *mf;
-
+
for(int i=0; i<f->size; i++) {
int thisAge = f->age[i];
if(thisAge == f->last) {
@@ -1210,7 +1230,7 @@
f->age[i] = thisAge;
}
}
-
+
while( f->pos!=0 ) {
float test = f->val[f->pos-1];
if(input < test) {
@@ -1219,7 +1239,7 @@
f->pos -= 1;
} else {break;}
}
-
+
while(f->pos != f->last) {
float test = f->val[f->pos+1];
if( input > test) {
@@ -1228,10 +1248,10 @@
f->pos += 1;
} else {break;}
}
-
+
f->val[f->pos] = input;
f->age[f->pos] = 0;
-
+
return f->val[f->middlePosition];
}
@@ -1250,16 +1270,17 @@
LEAF* leaf = f->mempool->leaf;
- f->fc = LEAF_clip(0.0f, freq, 0.5f * leaf->sampleRate);
+ f->sampleRate = leaf->sampleRate;
+ f->invSampleRate = leaf->invSampleRate;
+ f->fc = LEAF_clip(0.0f, freq, 0.5f * f->sampleRate);
f->type = type;
f->G = ONE_OVER_SQRT2;
- f->invG = 1.0f/ONE_OVER_SQRT2;
+ f->invG = 1.0f/ONE_OVER_SQRT2;
f->B = bandWidth;
f->m = 0.0f;
f->s1 = 0.0f;
f->s2 = 0.0f;
- f->sr = leaf->sampleRate;
- f->inv_sr = leaf->invSampleRate;
+
tVZFilter_calcCoeffs(vf);
}
@@ -1269,194 +1290,179 @@
mpool_free((char*)f, f->mempool);
}
-void tVZFilter_setSampleRate (tVZFilter* const vf, float sampleRate)
-{
- _tVZFilter* f = *vf;
- f->sr = sampleRate;
- f->inv_sr = 1.0f/sampleRate;
-}
-
float tVZFilter_tick (tVZFilter* const vf, float in)
{
_tVZFilter* f = *vf;
-
+
float yL, yB, yH;
-
+
// compute highpass output via Eq. 5.1:
yH = (in - f->R2*f->s1 - f->g*f->s1 - f->s2) * f->h;
-
+
// compute bandpass output by applying 1st integrator to highpass output:
yB = tanhf(f->g*yH) + f->s1;
f->s1 = f->g*yH + yB; // state update in 1st integrator
-
+
// compute lowpass output by applying 2nd integrator to bandpass output:
yL = tanhf(f->g*yB) + f->s2;
f->s2 = f->g*yB + yL; // state update in 2nd integrator
-
+
//according to the Vadim paper, we could add saturation to this model by adding a tanh in the integration stage.
//
//seems like that might look like this:
// y = tanh(g*x) + s; // output computation
// s = g*x + y; // state update
-
+
//instead of this:
// y = g*x + s; // output computation
// s = g*x + y; // state update
-
+
return f->cL*yL + f->cB*yB + f->cH*yH;
-
}
float tVZFilter_tickEfficient (tVZFilter* const vf, float in)
{
_tVZFilter* f = *vf;
-
+
float yL, yB, yH;
-
+
// compute highpass output via Eq. 5.1:
yH = (in - f->R2*f->s1 - f->g*f->s1 - f->s2) * f->h;
-
+
// compute bandpass output by applying 1st integrator to highpass output:
yB = (f->g*yH) + f->s1;
f->s1 = f->g*yH + yB; // state update in 1st integrator
-
+
// compute lowpass output by applying 2nd integrator to bandpass output:
yL = (f->g*yB) + f->s2;
f->s2 = f->g*yB + yL; // state update in 2nd integrator
-
+
//according to the Vadim paper, we could add saturation to this model by adding a tanh in the integration stage.
//
//seems like that might look like this:
// y = tanh(g*x) + s; // output computation
// s = g*x + y; // state update
-
+
//instead of this:
// y = g*x + s; // output computation
// s = g*x + y; // state update
-
+
return f->cL*yL + f->cB*yB + f->cH*yH;
-
}
-
void tVZFilter_calcCoeffs (tVZFilter* const vf)
{
-
_tVZFilter* f = *vf;
- f->g = tanf(PI * f->fc * f->inv_sr); // embedded integrator gain (Fig 3.11)
-
- switch( f->type )
- {
- case Bypass:
+ f->g = tanf(PI * f->fc * f->invSampleRate); // embedded integrator gain (Fig 3.11)
+
+ switch( f->type )
+ {
+ case Bypass:
{
- f->R2 = f->invG; // can we use an arbitrary value here, for example R2 = 1?
- f->cL = 1.0f;
- f->cB = f->R2;
- f->cH = 1.0f;
+ f->R2 = f->invG; // can we use an arbitrary value here, for example R2 = 1?
+ f->cL = 1.0f;
+ f->cB = f->R2;
+ f->cH = 1.0f;
}
- break;
- case Lowpass:
+ break;
+ case Lowpass:
{
f->R2 = f->invG;
f->cL = 1.0f; f->cB = 0.0f; f->cH = 0.0f;
}
- break;
- case Highpass:
+ break;
+ case Highpass:
{
f->R2 = f->invG;
f->cL = 0.0f; f->cB = 0.0f; f->cH = 1.0f;
}
- break;
- case BandpassSkirt:
+ break;
+ case BandpassSkirt:
{
f->R2 = f->invG;
f->cL = 0.0f; f->cB = 1.0f; f->cH = 0.0f;
}
- break;
- case BandpassPeak:
+ break;
+ case BandpassPeak:
{
f->R2 = 2.0f*tVZFilter_BandwidthToR(vf, f->B);
f->cL = 0.0f; f->cB = f->R2; f->cH = 0.0f;
}
- break;
- case BandReject:
+ break;
+ case BandReject:
{
f->R2 = 2.0f*tVZFilter_BandwidthToR(vf, f->B);
f->cL = 1.0f; f->cB = 0.0f; f->cH = 1.0f;
}
- break;
- case Bell:
+ break;
+ case Bell:
{
float fl = f->fc*powf(2.0f, (-f->B)*0.5f); // lower bandedge frequency (in Hz)
- float wl = tanf(PI*fl*f->inv_sr); // warped radian lower bandedge frequency /(2*fs)
+ float wl = tanf(PI*fl*f->invSampleRate); // warped radian lower bandedge frequency /(2*fs)
float r = f->g/wl;
r *= r; // warped frequency ratio wu/wl == (wc/wl)^2 where wu is the
- // warped upper bandedge, wc the center
+ // warped upper bandedge, wc the center
f->R2 = 2.0f*sqrtf(((r*r+1.0f)/r-2.0f)/(4.0f*f->G));
f->cL = 1.0f; f->cB = f->R2*f->G; f->cH = 1.0f;
}
- break;
- case Lowshelf:
+ break;
+ case Lowshelf:
{
float A = sqrtf(f->G);
- f->g /= sqrtf(A); // scale SVF-cutoff frequency for shelvers
- f->R2 = 2*sinhf(f->B*logf(2.0f)*0.5f);
- f->cL = f->G; f->cB = f->R2*A; f->cH = 1.0f;
+ f->g /= sqrtf(A); // scale SVF-cutoff frequency for shelvers
+ f->R2 = 2*sinhf(f->B*logf(2.0f)*0.5f);
+ f->cL = f->G; f->cB = f->R2*A; f->cH = 1.0f;
}
- break;
- case Highshelf:
+ break;
+ case Highshelf:
{
- float A = sqrtf(f->G);
- f->g *= sqrtf(A); // scale SVF-cutoff frequency for shelvers
- f->R2 = 2.0f*sinhf(f->B*logf(2.0f)*0.5f);
- f->cL = 1.0f; f->cB = f->R2*A; f->cH = f->G;
+ float A = sqrtf(f->G);
+ f->g *= sqrtf(A); // scale SVF-cutoff frequency for shelvers
+ f->R2 = 2.0f*sinhf(f->B*logf(2.0f)*0.5f);
+ f->cL = 1.0f; f->cB = f->R2*A; f->cH = f->G;
}
- break;
- case Allpass:
+ break;
+ case Allpass:
{
f->R2 = 2.0f*tVZFilter_BandwidthToR(vf, f->B);
f->cL = 1.0f; f->cB = -f->R2; f->cH = 1.0f;
}
- break;
-
- // experimental - maybe we must find better curves for cL, cB, cH:
- case Morph:
+ break;
+
+ // experimental - maybe we must find better curves for cL, cB, cH:
+ case Morph:
{
f->R2 = f->invG;
- float x = 2.0f*f->m-1.0f;
-
- f->cL = maximum(-x, 0.0f); /*cL *= cL;*/
- f->cH = minimum( x, 0.0f); /*cH *= cH;*/
- f->cB = 1.0f-x*x;
-
+ float x = 2.0f*f->m-1.0f;
+
+ f->cL = maximum(-x, 0.0f); /*cL *= cL;*/
+ f->cH = minimum( x, 0.0f); /*cH *= cH;*/
+ f->cB = 1.0f-x*x;
+
// bottom line: we need to test different versions for how they feel when tweaking the
// morph parameter
-
- // this scaling ensures constant magnitude at the cutoff point (we divide the coefficients by
- // the magnitude response value at the cutoff frequency and scale back by the gain):
- float s = f->G * sqrtf((f->R2*f->R2) / (f->cL*f->cL + f->cB*f->cB + f->cH*f->cH - 2.0f*f->cL*f->cH));
- f->cL *= s; f->cB *= s; f->cH *= s;
+
+ // this scaling ensures constant magnitude at the cutoff point (we divide the coefficients by
+ // the magnitude response value at the cutoff frequency and scale back by the gain):
+ float s = f->G * sqrtf((f->R2*f->R2) / (f->cL*f->cL + f->cB*f->cB + f->cH*f->cH - 2.0f*f->cL*f->cH));
+ f->cL *= s; f->cB *= s; f->cH *= s;
}
- break;
-
- }
-
- f->h = 1.0f / (1.0f + f->R2*f->g + f->g*f->g); // factor for feedback precomputation
+ break;
+
+ }
+
+ f->h = 1.0f / (1.0f + f->R2*f->g + f->g*f->g); // factor for feedback precomputation
}
void tVZFilter_calcCoeffsEfficientBP (tVZFilter* const vf)
{
-
_tVZFilter* f = *vf;
- f->g = fastertanf(PI * f->fc * f->inv_sr); // embedded integrator gain (Fig 3.11)
+ f->g = fastertanf(PI * f->fc * f->invSampleRate); // embedded integrator gain (Fig 3.11)
f->R2 = 2.0f*tVZFilter_BandwidthToR(vf, f->B);
f->cB = f->R2;
f->h = 1.0f / (1.0f + f->R2*f->g + f->g*f->g); // factor for feedback precomputation
}
-
-
-
void tVZFilter_setBandwidth (tVZFilter* const vf, float B)
{
_tVZFilter* f = *vf;
@@ -1466,18 +1472,16 @@
void tVZFilter_setFreq (tVZFilter* const vf, float freq)
{
_tVZFilter* f = *vf;
- LEAF* leaf = f->mempool->leaf;
- f->fc = LEAF_clip(0.0f, freq, 0.5f * leaf->sampleRate);
+ f->fc = LEAF_clip(0.0f, freq, 0.5f * f->sampleRate);
tVZFilter_calcCoeffs(vf);
}
void tVZFilter_setFreqAndBandwidth (tVZFilter* const vf, float freq, float bw)
{
_tVZFilter* f = *vf;
- LEAF* leaf = f->mempool->leaf;
f->B = LEAF_clip(0.0f,bw, 100.0f);
- f->fc = LEAF_clip(0.0f, freq, 0.5f * leaf->sampleRate);
+ f->fc = LEAF_clip(0.0f, freq, 0.5f * f->sampleRate);
tVZFilter_calcCoeffs(vf);
}
@@ -1484,15 +1488,12 @@
void tVZFilter_setFreqAndBandwidthEfficientBP (tVZFilter* const vf, float freq, float bw)
{
_tVZFilter* f = *vf;
- LEAF* leaf = f->mempool->leaf;
-
+
f->B = LEAF_clip(0.0f,bw, 100.0f);
- f->fc = LEAF_clip(0.0f, freq, 0.5f * leaf->sampleRate);
+ f->fc = LEAF_clip(0.0f, freq, 0.5f * f->sampleRate);
tVZFilter_calcCoeffsEfficientBP(vf);
}
-
-
void tVZFilter_setGain (tVZFilter* const vf, float gain)
{
_tVZFilter* f = *vf;
@@ -1501,8 +1502,6 @@
tVZFilter_calcCoeffs(vf);
}
-
-
void tVZFilter_setMorph (tVZFilter* const vf, float morph)
{
_tVZFilter* f = *vf;
@@ -1520,25 +1519,32 @@
float tVZFilter_BandwidthToR(tVZFilter* const vf, float B)
{
_tVZFilter* f = *vf;
- float fl = f->fc*powf(2.0f, -B*0.5f); // lower bandedge frequency (in Hz)
- float gl = tanf(PI*fl*f->inv_sr); // warped radian lower bandedge frequency /(2*fs)
- float r = gl/f->g; // ratio between warped lower bandedge- and center-frequencies
- // unwarped: r = pow(2, -B/2) -> approximation for low
- // center-frequencies
- return sqrtf((1.0f-r*r)*(1.0f-r*r)/(4.0f*r*r));
+ float fl = f->fc*powf(2.0f, -B*0.5f); // lower bandedge frequency (in Hz)
+ float gl = tanf(PI*fl*f->invSampleRate); // warped radian lower bandedge frequency /(2*fs)
+ float r = gl/f->g; // ratio between warped lower bandedge- and center-frequencies
+ // unwarped: r = pow(2, -B/2) -> approximation for low
+ // center-frequencies
+ return sqrtf((1.0f-r*r)*(1.0f-r*r)/(4.0f*r*r));
}
float tVZFilter_BandwidthToREfficientBP(tVZFilter* const vf, float B)
{
_tVZFilter* f = *vf;
- float fl = f->fc*fastPowf(2.0f, -B * 0.5f); // lower bandedge frequency (in Hz)
- float gl = fastertanf(PI*fl*f->inv_sr); // warped radian lower bandedge frequency /(2*fs)
- float r = gl/f->g; // ratio between warped lower bandedge- and center-frequencies
- // unwarped: r = pow(2, -B/2) -> approximation for low
- // center-frequencies
- return fastsqrtf((1.0f-r*r)*(1.0f-r*r)/(4.0f*r*r));
+ float fl = f->fc*fastPowf(2.0f, -B * 0.5f); // lower bandedge frequency (in Hz)
+ float gl = fastertanf(PI*fl*f->invSampleRate); // warped radian lower bandedge frequency /(2*fs)
+ float r = gl/f->g; // ratio between warped lower bandedge- and center-frequencies
+ // unwarped: r = pow(2, -B/2) -> approximation for low
+ // center-frequencies
+ return fastsqrtf((1.0f-r*r)*(1.0f-r*r)/(4.0f*r*r));
}
+void tVZFilter_setSampleRate (tVZFilter* const vf, float sr)
+{
+ _tVZFilter* f = *vf;
+ f->sampleRate = sr;
+ f->invSampleRate = 1.0f/f->sampleRate;
+ tVZFilter_calcCoeffs(vf);
+}
@@ -1549,26 +1555,28 @@
void tDiodeFilter_initToPool (tDiodeFilter* const vf, float cutoff, float resonance, tMempool* const mp)
{
- _tMempool* m = *mp;
- _tDiodeFilter* f = *vf = (_tDiodeFilter*) mpool_alloc(sizeof(_tDiodeFilter), m);
- f->mempool = m;
+ _tMempool* m = *mp;
+ _tDiodeFilter* f = *vf = (_tDiodeFilter*) mpool_alloc(sizeof(_tDiodeFilter), m);
+ f->mempool = m;
LEAF* leaf = f->mempool->leaf;
- // initialization (the resonance factor is between 0 and 8 according to the article)
- f->f = (float)tan((double)(PI * cutoff/leaf->sampleRate));
- f->r = (7.f * resonance + 0.5f);
- f->Vt = 0.5f;
- f->n = 1.836f;
- f->zi = 0.0f; //previous input value
- f->gamma = f->Vt*f->n;
- f->s0 = 0.01f;
- f->s1 = 0.02f;
- f->s2 = 0.03f;
- f->s3 = 0.04f;
- f->g0inv = 1.f/(2.f*f->Vt);
- f->g1inv = 1.f/(2.f*f->gamma);
- f->g2inv = 1.f/(6.f*f->gamma);
+ f->invSampleRate = leaf->invSampleRate;
+ f->cutoff = cutoff;
+ // initialization (the resonance factor is between 0 and 8 according to the article)
+ f->f = (float)tan((double)(PI * cutoff * f->invSampleRate));
+ f->r = (7.f * resonance + 0.5f);
+ f->Vt = 0.5f;
+ f->n = 1.836f;
+ f->zi = 0.0f; //previous input value
+ f->gamma = f->Vt*f->n;
+ f->s0 = 0.01f;
+ f->s1 = 0.02f;
+ f->s2 = 0.03f;
+ f->s3 = 0.04f;
+ f->g0inv = 1.f/(2.f*f->Vt);
+ f->g1inv = 1.f/(2.f*f->gamma);
+ f->g2inv = 1.f/(6.f*f->gamma);
}
void tDiodeFilter_free (tDiodeFilter* const vf)
@@ -1583,11 +1591,11 @@
// IIRC I got this as Pade-approx for tanh(sqrt(x))/sqrt(x)
float testVal = ((15.0f*a + 420.0f)*a + 945.0f);
float output = 1.0f;
-
+
if (testVal!= 0.0f)
{
- output = testVal;
-
+ output = testVal;
+
}
return ((a + 105.0f)*a + 945.0f) / output;
}
@@ -1595,12 +1603,12 @@
float tDiodeFilter_tick (tDiodeFilter* const vf, float in)
{
_tDiodeFilter* f = *vf;
-
+
int errorCheck = 0;
// the input x[n+1] is given by 'in', and x[n] by zi
// input with half delay
float ih = 0.5f * (in + f->zi);
-
+
// evaluate the non-linear factors
float t0 = f->f*tanhXdX((ih - f->r * f->s3)*f->g0inv)*f->g0inv;
float t1 = f->f*tanhXdX((f->s1-f->s0)*f->g1inv)*f->g1inv;
@@ -1607,19 +1615,17 @@
float t2 = f->f*tanhXdX((f->s2-f->s1)*f->g1inv)*f->g1inv;
float t3 = f->f*tanhXdX((f->s3-f->s2)*f->g1inv)*f->g1inv;
float t4 = f->f*tanhXdX((f->s3)*f->g2inv)*f->g2inv;
-
-
-
+
// This formula gives the result for y3 thanks to MATLAB
float y3 = (f->s2 + f->s3 + t2*(f->s1 + f->s2 + f->s3 + t1*(f->s0 + f->s1 + f->s2 + f->s3 + t0*in)) + t1*(2.0f*f->s2 + 2.0f*f->s3))*t3 + f->s3 + 2.0f*f->s3*t1 + t2*(2.0f*f->s3 + 3.0f*f->s3*t1);
if (isnan(y3))
{
- errorCheck = 1;
+ errorCheck = 1;
}
float tempy3denom = (t4 + t1*(2.0f*t4 + 4.0f) + t2*(t4 + t1*(t4 + f->r*t0 + 4.0f) + 3.0f) + 2.0f)*t3 + t4 + t1*(2.0f*t4 + 2.0f) + t2*(2.0f*t4 + t1*(3.0f*t4 + 3.0f) + 2.0f) + 1.0f;
if (isnan(tempy3denom))
{
- errorCheck = 2;
+ errorCheck = 2;
}
if (tempy3denom == 0.0f)
{
@@ -1628,7 +1634,7 @@
y3 = y3 / tempy3denom;
if (isnan(y3))
{
- errorCheck = 3;
+ errorCheck = 3;
}
if (t1 == 0.0f)
{
@@ -1647,42 +1653,45 @@
float y1 = (f->s2 - (1+t3+t2)*y2 + t3*y3) / (-t2);
float y0 = (f->s1 - (1+t2+t1)*y1 + t2*y2) / (-t1);
float xx = (in - f->r*y3);
-
+
// update state
f->s0 += 2.0f * (t0*xx + t1*(y1-y0));
if (isnan(f->s0))
{
- errorCheck = 4;
+ errorCheck = 4;
}
-
+
if (isinf(f->s0))
{
- errorCheck = 5;
+ errorCheck = 5;
}
f->s1 += 2.0f * (t2*(y2-y1) - t1*(y1-y0));
f->s2 += 2.0f * (t3*(y3-y2) - t2*(y2-y1));
f->s3 += 2.0f * (-t4*(y3) - t3*(y3-y2));
-
+
f->zi = in;
return y3*f->r;
-
}
-
-
void tDiodeFilter_setFreq (tDiodeFilter* const vf, float cutoff)
{
- _tDiodeFilter* f = *vf;
- LEAF* leaf = f->mempool->leaf;
+ _tDiodeFilter* f = *vf;
- f->f = tanf(PI * LEAF_clip(10.0f, cutoff, 20000.0f) * leaf->invSampleRate);
+ f->cutoff = LEAF_clip(10.0f, cutoff, 20000.0f);
+ f->f = tanf(PI * f->cutoff * f->invSampleRate);
}
-
void tDiodeFilter_setQ (tDiodeFilter* const vf, float resonance)
{
- _tDiodeFilter* f = *vf;
- f->r = LEAF_clip(0.5, (7.f * resonance + 0.5f), 8.0f);
+ _tDiodeFilter* f = *vf;
+ f->r = LEAF_clip(0.5, (7.f * resonance + 0.5f), 8.0f);
+}
+void tDiodeFilter_setSampleRate(tDiodeFilter* const vf, float sr)
+{
+ _tDiodeFilter* f = *vf;
+
+ f->invSampleRate = 1.0f/sr;
+ f->f = tanf(PI * f->cutoff * f->invSampleRate);
}
--- a/leaf/Src/leaf-instruments.c
+++ b/leaf/Src/leaf-instruments.c
@@ -141,6 +141,17 @@
cowbell->useStick = useStick;
}
+void t808Cowbell_setSampleRate(t808Cowbell* const cowbellInst, float sr)
+{
+ _t808Cowbell* cowbell = *cowbellInst;
+
+ tSquare_setSampleRate(&cowbell->p[0], sr);
+ tSquare_setSampleRate(&cowbell->p[1], sr);
+ tSVF_setSampleRate(&cowbell->bandpassOsc, sr);
+ tSVF_setSampleRate(&cowbell->bandpassStick, sr);
+ tHighpass_setSampleRate(&cowbell->highpass, sr);
+}
+
// ----------------- HIHAT ----------------------------//
void t808Hihat_init(t808Hihat* const hihatInst, LEAF* const leaf)
@@ -309,6 +320,22 @@
hihat->freq = freq;
}
+void t808Hihat_setSampleRate(t808Hihat* const hihatInst, float sr)
+{
+ _t808Hihat* hihat = *hihatInst;
+
+ for (int i = 0; i < 6; i++)
+ {
+ tSquare_setSampleRate(&hihat->p[i], sr);
+ }
+
+ // need to fix SVF to be generic
+ tSVF_setSampleRate(&hihat->bandpassStick, sr);
+ tSVF_setSampleRate(&hihat->bandpassOsc, sr);
+
+ tHighpass_setSampleRate(&hihat->highpass, sr);
+}
+
// ----------------- SNARE ----------------------------//
void t808Snare_init (t808Snare* const snareInst, LEAF* const leaf)
@@ -456,6 +483,18 @@
return sample;
}
+void t808Snare_setSampleRate(t808Snare* const snareInst, float sr)
+{
+ _t808Snare* snare = *snareInst;
+
+ for (int i = 0; i < 2; i++)
+ {
+ tTriangle_setSampleRate(&snare->tone[i], sr);
+ tSVF_setSampleRate(&snare->toneLowpass[i], sr);
+ }
+ tSVF_setSampleRate(&snare->noiseLowpass, sr);
+}
+
// ----------------- KICK ----------------------------//
void t808Kick_init (t808Kick* const kickInst, LEAF* const leaf)
@@ -539,5 +578,13 @@
void t808Kick_setToneNoiseMix (t808Kick* const kickInst, float toneNoiseMix);
void t808Kick_setNoiseFilterFreq (t808Kick* const kickInst, float noiseFilterFreq);
void t808Kick_setNoiseFilterQ (t808Kick* const kickInst, float noiseFilterQ);
+
+void t808Kick_setSampleRate (t808Kick* const kickInst, float sr)
+{
+ _t808Kick* kick = *kickInst;
+
+ tCycle_setSampleRate(&kick->tone, sr);
+ tSVF_setSampleRate(&kick->toneLowpass, sr);
+}
--- a/leaf/Src/leaf-midi.c
+++ b/leaf/Src/leaf-midi.c
@@ -605,7 +605,15 @@
return (poly->voices[voice][0] > 0) ? 1 : 0;
}
-
+void tPoly_setSampleRate(tPoly* const polyh, float sr)
+{
+ _tPoly* poly = *polyh;
+ for (int i = 0; i < poly->maxNumVoices; i++)
+ {
+ tRamp_setSampleRate(&poly->ramps[i], sr);
+ }
+ tRamp_setSampleRate(&poly->pitchBendRamp, sr);
+}
//tSimplePoly = much more efficient implementation without ramps and glide
--- a/leaf/Src/leaf-oscillators.c
+++ b/leaf/Src/leaf-oscillators.c
@@ -28,9 +28,11 @@
_tMempool* m = *mp;
_tCycle* c = *cy = (_tCycle*) mpool_alloc(sizeof(_tCycle), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
c->inc = 0.0f;
c->phase = 0.0f;
+ c->invSampleRate = leaf->invSampleRate;
}
void tCycle_free (tCycle* const cy)
@@ -43,13 +45,12 @@
void tCycle_setFreq(tCycle* const cy, float freq)
{
_tCycle* c = *cy;
- LEAF* leaf = c->mempool->leaf;
if (!isfinite(freq)) return;
c->freq = freq;
- c->inc = freq * leaf->invSampleRate;
+ c->inc = freq * c->invSampleRate;
c->inc -= (int)c->inc;
}
@@ -80,13 +81,12 @@
return (samp0 + (samp1 - samp0) * frac);
}
-void tCycleSampleRateChanged (tCycle* const cy)
+void tCycle_setSampleRate (tCycle* const cy, float sr)
{
_tCycle* c = *cy;
- LEAF* leaf = c->mempool->leaf;
- c->inc = c->freq * leaf->invSampleRate;
- c->inc -= (int)c->inc;
+ c->invSampleRate = 1.0f/sr;
+ tCycle_setFreq(cy, c->freq);
}
#endif // LEAF_INCLUDE_SINE_TABLE
@@ -103,9 +103,11 @@
_tMempool* m = *mp;
_tTriangle* c = *cy = (_tTriangle*) mpool_alloc(sizeof(_tTriangle), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
c->inc = 0.0f;
c->phase = 0.0f;
+ c->invSampleRate = leaf->invSampleRate;
tTriangle_setFreq(cy, 220);
}
@@ -119,15 +121,14 @@
void tTriangle_setFreq(tTriangle* const cy, float freq)
{
_tTriangle* c = *cy;
- LEAF* leaf = c->mempool->leaf;
- c->freq = freq;
+ c->freq = freq;
- c->inc = c->freq * leaf->invSampleRate;
+ c->inc = c->freq * c->invSampleRate;
c->inc -= (int)c->inc;
// abs for negative frequencies
- c->w = fabsf(c->freq * (TRI_TABLE_SIZE * leaf->invSampleRate));
+ c->w = fabsf(c->freq * (TRI_TABLE_SIZE * c->invSampleRate));
c->w = log2f_approx(c->w);//+ LEAF_SQRT2 - 1.0f; adding an offset here will shift our table selection upward, reducing aliasing but lower high freq fidelity. +1.0f should remove all aliasing
if (c->w < 0.0f) c->w = 0.0f;
@@ -173,13 +174,12 @@
return oct0 + (oct1 - oct0) * c->w;
}
-void tTriangleSampleRateChanged (tTriangle* const cy)
+void tTriangle_setSampleRate (tTriangle* const cy, float sr)
{
_tTriangle* c = *cy;
- LEAF* leaf = c->mempool->leaf;
- c->inc = c->freq * leaf->invSampleRate;
- c->inc -= (int)c->inc;
+ c->invSampleRate = 1.0f/sr;
+ tTriangle_setFreq(cy, c->freq);
}
#endif // LEAF_INCLUDE_TRIANGLE_TABLE
@@ -196,9 +196,11 @@
_tMempool* m = *mp;
_tSquare* c = *cy = (_tSquare*) mpool_alloc(sizeof(_tSquare), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
c->inc = 0.0f;
c->phase = 0.0f;
+ c->invSampleRate = leaf->invSampleRate;
tSquare_setFreq(cy, 220);
}
@@ -212,15 +214,14 @@
void tSquare_setFreq(tSquare* const cy, float freq)
{
_tSquare* c = *cy;
- LEAF* leaf = c->mempool->leaf;
c->freq = freq;
- c->inc = c->freq * leaf->invSampleRate;
+ c->inc = c->freq * c->invSampleRate;
c->inc -= (int)c->inc;
// abs for negative frequencies
- c->w = fabsf(c->freq * (SQR_TABLE_SIZE * leaf->invSampleRate));
+ c->w = fabsf(c->freq * (SQR_TABLE_SIZE * c->invSampleRate));
c->w = log2f_approx(c->w);//+ LEAF_SQRT2 - 1.0f; adding an offset here will shift our table selection upward, reducing aliasing but lower high freq fidelity. +1.0f should remove all aliasing
if (c->w < 0.0f) c->w = 0.0f;
@@ -265,13 +266,12 @@
return oct0 + (oct1 - oct0) * c->w;
}
-void tSquareSampleRateChanged (tSquare* const cy)
+void tSquare_setSampleRate (tSquare* const cy, float sr)
{
_tSquare* c = *cy;
- LEAF* leaf = c->mempool->leaf;
- c->inc = c->freq * leaf->invSampleRate;
- c->inc -= (int)c->inc;
+ c->invSampleRate = 1.0f/sr;
+ tSquare_setFreq(cy, c->freq);
}
#endif // LEAF_INCLUDE_SQUARE_TABLE
@@ -288,9 +288,11 @@
_tMempool* m = *mp;
_tSawtooth* c = *cy = (_tSawtooth*) mpool_alloc(sizeof(_tSawtooth), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
c->inc = 0.0f;
c->phase = 0.0f;
+ c->invSampleRate = leaf->invSampleRate;
tSawtooth_setFreq(cy, 220);
}
@@ -304,15 +306,14 @@
void tSawtooth_setFreq(tSawtooth* const cy, float freq)
{
_tSawtooth* c = *cy;
- LEAF* leaf = c->mempool->leaf;
c->freq = freq;
- c->inc = c->freq * leaf->invSampleRate;
+ c->inc = c->freq * c->invSampleRate;
c->inc -= (int)c->inc;
// abs for negative frequencies
- c->w = fabsf(c->freq * (SAW_TABLE_SIZE * leaf->invSampleRate));
+ c->w = fabsf(c->freq * (SAW_TABLE_SIZE * c->invSampleRate));
c->w = log2f_approx(c->w);//+ LEAF_SQRT2 - 1.0f; adding an offset here will shift our table selection upward, reducing aliasing but lower high freq fidelity. +1.0f should remove all aliasing
if (c->w < 0.0f) c->w = 0.0f; // If c->w is < 0.0f, then freq is less than our base freq
@@ -357,13 +358,12 @@
return oct0 + (oct1 - oct0) * c->w;
}
-void tSawtoothSampleRateChanged (tSawtooth* const cy)
+void tSawtooth_setSampleRate (tSawtooth* const cy, float sr)
{
_tSawtooth* c = *cy;
- LEAF* leaf = c->mempool->leaf;
- c->inc = c->freq * leaf->invSampleRate;
- c->inc -= (int)c->inc;
+ c->invSampleRate = 1.0f/sr;
+ tSawtooth_setFreq(cy, c->freq);
}
#endif // LEAF_INCLUDE_SAWTOOTH_TABLE
@@ -380,7 +380,9 @@
_tMempool* m = *mp;
_tPBTriangle* c = *osc = (_tPBTriangle*) mpool_alloc(sizeof(_tPBTriangle), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
+ c->invSampleRate = leaf->invSampleRate;
c->inc = 0.0f;
c->phase = 0.0f;
c->skew = 0.5f;
@@ -428,10 +430,9 @@
void tPBTriangle_setFreq (tPBTriangle* const osc, float freq)
{
_tPBTriangle* c = *osc;
- LEAF* leaf = c->mempool->leaf;
c->freq = freq;
- c->inc = freq * leaf->invSampleRate;
+ c->inc = freq * c->invSampleRate;
}
void tPBTriangle_setSkew (tPBTriangle* const osc, float skew)
@@ -440,7 +441,15 @@
c->skew = (skew + 1.0f) * 0.5f;
}
+void tPBTriangle_setSampleRate (tPBTriangle* const osc, float sr)
+{
+ _tPBTriangle* c = *osc;
+
+ c->invSampleRate = 1.0f/sr;
+ tPBTriangle_setFreq(osc, c->freq);
+}
+
//==============================================================================
/* tPulse: Anti-aliased pulse waveform. */
@@ -454,7 +463,9 @@
_tMempool* m = *mp;
_tPBPulse* c = *osc = (_tPBPulse*) mpool_alloc(sizeof(_tPBPulse), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
+ c->invSampleRate = leaf->invSampleRate;
c->inc = 0.0f;
c->phase = 0.0f;
c->width = 0.5f;
@@ -487,10 +498,9 @@
void tPBPulse_setFreq (tPBPulse* const osc, float freq)
{
_tPBPulse* c = *osc;
- LEAF* leaf = c->mempool->leaf;
c->freq = freq;
- c->inc = freq * leaf->invSampleRate;
+ c->inc = freq * c->invSampleRate;
}
void tPBPulse_setWidth (tPBPulse* const osc, float width)
@@ -499,6 +509,13 @@
c->width = width;
}
+void tPBPulse_setSampleRate (tPBPulse* const osc, float sr)
+{
+ _tPBPulse* c = *osc;
+
+ c->invSampleRate = 1.0f/sr;
+ tPBPulse_setFreq(osc, c->freq);
+}
//==============================================================================
@@ -513,9 +530,11 @@
_tMempool* m = *mp;
_tPBSaw* c = *osc = (_tPBSaw*) mpool_alloc(sizeof(_tPBSaw), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
c->inc = 0.0f;
c->phase = 0.0f;
+ c->invSampleRate = leaf->invSampleRate;
}
void tPBSaw_free (tPBSaw* const osc)
@@ -542,22 +561,21 @@
void tPBSaw_setFreq (tPBSaw* const osc, float freq)
{
_tPBSaw* c = *osc;
- LEAF* leaf = c->mempool->leaf;
c->freq = freq;
+ c->inc = freq * c->invSampleRate;
+}
+
+void tPBSaw_setSampleRate (tPBSaw* const osc, float sr)
+{
+ _tPBSaw* c = *osc;
- c->inc = freq * leaf->invSampleRate;
+ c->invSampleRate = 1.0f/sr;
+ tPBSaw_setFreq(osc, c->freq);
}
//========================================================================
/* Phasor */
-void tPhasorSampleRateChanged (tPhasor* const ph)
-{
- _tPhasor* p = *ph;
- LEAF* leaf = p->mempool->leaf;
-
- p->inc = p->freq * leaf->invSampleRate;
-};
void tPhasor_init(tPhasor* const ph, LEAF* const leaf)
{
@@ -569,10 +587,12 @@
_tMempool* m = *mp;
_tPhasor* p = *ph = (_tPhasor*) mpool_alloc(sizeof(_tPhasor), m);
p->mempool = m;
+ LEAF* leaf = p->mempool->leaf;
p->phase = 0.0f;
p->inc = 0.0f;
p->phaseDidReset = 0;
+ p->invSampleRate = leaf->invSampleRate;
}
void tPhasor_free (tPhasor* const ph)
@@ -585,11 +605,10 @@
void tPhasor_setFreq(tPhasor* const ph, float freq)
{
_tPhasor* p = *ph;
- LEAF* leaf = p->mempool->leaf;
p->freq = freq;
- p->inc = freq * leaf->invSampleRate;
+ p->inc = freq * p->invSampleRate;
p->inc -= (int)p->inc;
}
@@ -614,6 +633,15 @@
return p->phase;
}
+void tPhasor_setSampleRate (tPhasor* const ph, float sr)
+{
+ _tPhasor* p = *ph;
+
+ p->invSampleRate = 1.0f/sr;
+ tPhasor_setFreq(ph, p->freq);
+};
+
+//========================================================================
/* Noise */
void tNoise_init(tNoise* const ns, NoiseType type, LEAF* const leaf)
{
@@ -662,11 +690,6 @@
//=================================================================================
/* Neuron */
-void tNeuronSampleRateChanged(tNeuron* nr)
-{
-
-}
-
void tNeuron_init(tNeuron* const nr, LEAF* const leaf)
{
tNeuron_initToPool(nr, &leaf->mempool);
@@ -677,7 +700,7 @@
_tMempool* m = *mp;
_tNeuron* n = *nr = (_tNeuron*) mpool_alloc(sizeof(_tNeuron), m);
n->mempool = m;
-
+
tPoleZero_initToPool(&n->f, mp);
tPoleZero_setBlockZero(&n->f, 0.99f);
@@ -748,7 +771,6 @@
n->V[0] = V1;
}
-
void tNeuron_setV2(tNeuron* const nr, float V2)
{
_tNeuron* n = *nr;
@@ -881,8 +903,6 @@
n->current = current;
}
-
-
//----------------------------------------------------------------------------------------------------------
void tMBPulse_init(tMBPulse* const osc, LEAF* const leaf)
@@ -895,7 +915,10 @@
_tMempool* m = *pool;
_tMBPulse* c = *osc = (_tMBPulse*) mpool_alloc(sizeof(_tMBPulse), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
+ c->invSampleRate = leaf->invSampleRate;
+
c->_init = true;
c->amp = 1.0f;
c->freq = 440.f;
@@ -918,7 +941,6 @@
float tMBPulse_tick(tMBPulse* const osc)
{
_tMBPulse* c = *osc;
- LEAF* leaf = c->mempool->leaf;
int j, k;
float freq, sync;
@@ -937,7 +959,7 @@
if (c->_init) {
p = 0.0f;
- w = freq * leaf->invSampleRate;
+ w = freq * c->invSampleRate;
b = 0.5f * (1.0f + c->waveform );
/* for variable-width rectangular wave, we could do DC compensation with:
@@ -955,7 +977,7 @@
// a = 0.2 + 0.8 * vco->_port [FILT];
a = 0.5f; // when a = 1, LPfilter is disabled
- w = freq * leaf->invSampleRate;
+ w = freq * c->invSampleRate;
b = 0.5f * (1.0f + c->waveform);
if (sync > 0.0f && c->softsync > 0) c->syncdir = -c->syncdir;
@@ -1177,6 +1199,12 @@
c->softsync = hardOrSoft > 0 ? 1 : 0;
}
+void tMBPulse_setSampleRate(tMBPulse* const osc, float sr)
+{
+ _tMBPulse* c = *osc;
+ c->invSampleRate = 1.0f/sr;
+}
+
//==========================================================================================================
//==========================================================================================================
@@ -1190,7 +1218,9 @@
_tMempool* m = *pool;
_tMBTriangle* c = *osc = (_tMBTriangle*) mpool_alloc(sizeof(_tMBTriangle), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
+ c->invSampleRate = leaf->invSampleRate;
c->amp = 1.0f;
c->freq = 440.f;
c->lastsyncin = 0.0f;
@@ -1213,7 +1243,6 @@
float tMBTriangle_tick(tMBTriangle* const osc)
{
_tMBTriangle* c = *osc;
- LEAF* leaf = c->mempool->leaf;
int j, k, dir;
float freq, sync;
@@ -1232,7 +1261,7 @@
if (c->_init) {
// w = (exp2ap (freq[1] + vco->_port[OCTN] + vco->_port[TUNE] + expm[1] * vco->_port[EXPG] + 8.03136)
// + 1e3 * linm[1] * vco->_port[LING]) / SAMPLERATE;
- w = freq * leaf->invSampleRate;
+ w = freq * c->invSampleRate;
b = 0.5f * (1.0f + c->waveform);
p = 0.5f * b;
/* if we valued alias-free startup over low startup time, we could do:
@@ -1245,7 +1274,7 @@
// a = 0.2 + 0.8 * vco->_port [FILT];
a = 0.5f; // when a = 1, LPfilter is disabled
- w = freq * leaf->invSampleRate;
+ w = freq * c->invSampleRate;
b = 0.5f * (1.0f + c->waveform);
b1 = 1.0f - b;
@@ -1472,6 +1501,12 @@
c->softsync = hardOrSoft > 0 ? 1 : 0;
}
+void tMBTriangle_setSampleRate(tMBTriangle* const osc, float sr)
+{
+ _tMBTriangle* c = *osc;
+ c->invSampleRate = 1.0f/sr;
+}
+
//==========================================================================================================
//==========================================================================================================
@@ -1485,7 +1520,9 @@
_tMempool* m = *pool;
_tMBSaw* c = *osc = (_tMBSaw*) mpool_alloc(sizeof(_tMBSaw), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
+ c->invSampleRate = leaf->invSampleRate;
c->_init = true;
c->amp = 1.0f;
c->freq = 440.f;
@@ -1507,7 +1544,6 @@
float tMBSaw_tick(tMBSaw* const osc)
{
_tMBSaw* c = *osc;
- LEAF* leaf = c->mempool->leaf;
int j;
float freq, sync;
@@ -1523,7 +1559,7 @@
if (c->_init) {
p = 0.5f;
- w = freq * leaf->invSampleRate;
+ w = freq * c->invSampleRate;
/* if we valued alias-free startup over low startup time, we could do:
* p -= w;
@@ -1534,7 +1570,7 @@
//a = 0.2 + 0.8 * vco->_port [FILT];
a = 0.5f; // when a = 1, LPfilter is disabled
- w = freq * leaf->invSampleRate;
+ w = freq * c->invSampleRate;
if (sync > 0.0f && c->softsync > 0) c->syncdir = -c->syncdir;
// Should insert minblep for softsync?
@@ -1631,7 +1667,13 @@
c->softsync = hardOrSoft > 0 ? 1 : 0;
}
+void tMBSaw_setSampleRate(tMBSaw* const osc, float sr)
+{
+ _tMBSaw* c = *osc;
+ c->invSampleRate = 1.0f/sr;
+}
+
// WaveTable
void tTable_init(tTable* const cy, float* waveTable, int size, LEAF* const leaf)
{
@@ -1643,11 +1685,13 @@
_tMempool* m = *mp;
_tTable* c = *cy = (_tTable*)mpool_alloc(sizeof(_tTable), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
c->waveTable = waveTable;
c->size = size;
c->inc = 0.0f;
c->phase = 0.0f;
+ c->invSampleRate = leaf->invSampleRate;
}
void tTable_free(tTable* const cy)
@@ -1660,12 +1704,11 @@
void tTable_setFreq(tTable* const cy, float freq)
{
_tTable* c = *cy;
- LEAF* leaf = c->mempool->leaf;
if (!isfinite(freq)) return;
c->freq = freq;
- c->inc = freq * leaf->invSampleRate;
+ c->inc = freq * c->invSampleRate;
c->inc -= (int)c->inc;
}
@@ -1695,13 +1738,11 @@
return (samp0 + (samp1 - samp0) * fracPart);
}
-void tTableSampleRateChanged(tTable* const cy)
+void tTable_setSampleRate(tTable* const cy, float sr)
{
_tTable* c = *cy;
- LEAF* leaf = c->mempool->leaf;
-
- c->inc = c->freq * leaf->invSampleRate;
- c->inc -= (int)c->inc;
+ c->invSampleRate = 1.0f/sr;
+ tTable_setFreq(cy, c->freq);
}
void tWaveTable_init(tWaveTable* const cy, float* table, int size, float maxFreq, LEAF* const leaf)
@@ -1714,9 +1755,14 @@
_tMempool* m = *mp;
_tWaveTable* c = *cy = (_tWaveTable*) mpool_alloc(sizeof(_tWaveTable), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
+ c->sampleRate = leaf->sampleRate;
+
+ c->maxFreq = maxFreq;
+
// Determine base frequency
- c->baseFreq = m->leaf->sampleRate / (float) size;
+ c->baseFreq = c->sampleRate / (float) size;
c->invBaseFreq = 1.0f / c->baseFreq;
// Determine how many tables we need
@@ -1723,7 +1769,7 @@
// Assume we need at least 2, the fundamental + one to account for setting extra anti aliasing
c->numTables = 2;
float f = c->baseFreq;
- while (f < maxFreq)
+ while (f < c->maxFreq)
{
c->numTables++;
f *= 2.0f; // pass this multiplier in to set spacing of tables? would need to change setFreq too
@@ -1732,20 +1778,22 @@
c->size = size;
// Allocate memory for the tables
- c->tables = (float**) mpool_alloc(sizeof(float*) * c->numTables, m);
- for (int t = 0; t < c->numTables; ++t)
+ c->tables = (float**) mpool_alloc(sizeof(float*) * c->numTables, c->mempool);
+ c->baseTable = (float*) mpool_alloc(sizeof(float) * c->size, c->mempool);
+ c->tables[0] = c->baseTable;
+ for (int t = 1; t < c->numTables; ++t)
{
- c->tables[t] = (float*) mpool_alloc(sizeof(float) * c->size, m);
+ c->tables[t] = (float*) mpool_alloc(sizeof(float) * c->size, c->mempool);
}
// Copy table
for (int i = 0; i < c->size; ++i)
{
- c->tables[0][i] = table[i];
+ c->baseTable[i] = table[i];
}
// Make bandlimited copies
- f = m->leaf->sampleRate * 0.25; //start at half nyquist
+ f = c->sampleRate * 0.25; //start at half nyquist
// Not worth going over order 8 I think, and even 8 is only marginally better than 4.
tButterworth_initToPool(&c->bl, 8, -1.0f, f, mp);
for (int t = 1; t < c->numTables; ++t)
@@ -1778,6 +1826,64 @@
mpool_free((char*)c, c->mempool);
}
+void tWaveTable_setSampleRate(tWaveTable* const cy, float sr)
+{
+ _tWaveTable* c = *cy;
+
+ // Changing the sample rate of a wavetable requires up to partially reinitialize
+ for (int t = 1; t < c->numTables; ++t)
+ {
+ mpool_free((char*)c->tables[t], c->mempool);
+ }
+ mpool_free((char*)c->tables, c->mempool);
+
+ c->sampleRate = sr;
+
+ // Determine base frequency
+ c->baseFreq = c->sampleRate / (float) c->size;
+ c->invBaseFreq = 1.0f / c->baseFreq;
+
+ // Determine how many tables we need
+ // Assume we need at least 2, the fundamental + one to account for setting extra anti aliasing
+ c->numTables = 2;
+ float f = c->baseFreq;
+ while (f < c->maxFreq)
+ {
+ c->numTables++;
+ f *= 2.0f; // pass this multiplier in to set spacing of tables? would need to change setFreq too
+ }
+
+ // Allocate memory for the tables
+ c->tables = (float**) mpool_alloc(sizeof(float*) * c->numTables, c->mempool);
+ c->tables[0] = c->baseTable;
+ for (int t = 1; t < c->numTables; ++t)
+ {
+ c->tables[t] = (float*) mpool_alloc(sizeof(float) * c->size, c->mempool);
+ }
+
+ // Make bandlimited copies
+ f = c->sampleRate * 0.25; //start at half nyquist
+ // Not worth going over order 8 I think, and even 8 is only marginally better than 4.
+ tButterworth_initToPool(&c->bl, 8, -1.0f, f, &c->mempool);
+ tButterworth_setSampleRate(&c->bl, c->sampleRate);
+ for (int t = 1; t < c->numTables; ++t)
+ {
+ tButterworth_setF2(&c->bl, f);
+ // Do several passes here to prevent errors at the beginning of the waveform
+ // Not sure how many passes to do, seem to need more as the filter cutoff goes down
+ // 12 might be excessive but seems to work for now.
+ for (int p = 0; p < 12; ++p)
+ {
+ for (int i = 0; i < c->size; ++i)
+ {
+ c->tables[t][i] = tButterworth_tick(&c->bl, c->tables[t-1][i]);
+ }
+ }
+ f *= 0.5f; //halve the cutoff for next pass
+ }
+ tButterworth_free(&c->bl);
+}
+
//=======================================================================================
//=======================================================================================
@@ -1791,6 +1897,7 @@
_tMempool* m = *mp;
_tWaveOsc* c = *cy = (_tWaveOsc*) mpool_alloc(sizeof(_tWaveOsc), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
c->table = *table;
@@ -1799,6 +1906,8 @@
c->phaseOffset = 0.0f;
c->aa = 0.5f;
+ c->invSampleRate = leaf->invSampleRate;
+
tWaveOsc_setFreq(cy, 220);
}
@@ -1851,11 +1960,9 @@
{
_tWaveOsc* c = *cy;
- LEAF* leaf = c->mempool->leaf;
-
c->freq = freq;
- c->inc = c->freq * leaf->invSampleRate;
+ c->inc = c->freq * c->invSampleRate;
c->inc -= (int)c->inc;
// abs for negative frequencies
@@ -1885,6 +1992,13 @@
c->phaseOffset = phase - (int)phase;
}
+void tWaveOsc_setSampleRate(tWaveOsc* const cy, float sr)
+{
+ _tWaveOsc* c = *cy;
+ c->invSampleRate = 1.0f/sr;
+ tWaveOsc_setFreq(cy, c->freq);
+}
+
//================================================================================================
//================================================================================================
@@ -2039,18 +2153,16 @@
}
}
-//void tWaveSynth_setIndexTable(tWaveSynth* const cy, int i, float* table, int size)
-//{
-// _tWaveSynth* c = *cy;
-// if (i >= c->numTables) return;
-// if (
-// tWaveTable_free(&c->tables[i]);
-// tWaveTable_initToPool(&c->tables[i], table, size, c->maxFreq, &c->mempool);
-// for (int v = 0; v < c->numVoices; ++v)
-// {
-// tWaveOsc_setFreq(&c->oscs[i][v], c->oscs[i][v]->freq);
-// }
-//}
+void tWaveSynth_setSampleRate(tWaveSynth* const cy, float sr)
+{
+ _tWaveSynth* c = *cy;
+
+ for (int i = 0; i < c->numTables; ++i)
+ {
+ tWaveTable_setSampleRate(&c->tables[i], sr);
+ for (int v = 0; v < c->numVoices; ++v) tWaveOsc_setSampleRate(&c->oscs[i][v], sr);
+ }
+}
//=======================================================================================
//=======================================================================================
@@ -2065,9 +2177,14 @@
_tMempool* m = *mp;
_tWaveTableS* c = *cy = (_tWaveTableS*) mpool_alloc(sizeof(_tWaveTableS), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
+ c->sampleRate = leaf->sampleRate;
+
+ c->maxFreq = maxFreq;
+
// Determine base frequency
- c->baseFreq = m->leaf->sampleRate / (float) size;
+ c->baseFreq = c->sampleRate / (float) size;
c->invBaseFreq = 1.0f / c->baseFreq;
// Determine how many tables we need
@@ -2082,23 +2199,24 @@
// Allocate memory for the tables
c->tables = (float**) mpool_alloc(sizeof(float*) * c->numTables, c->mempool);
c->sizes = (int*) mpool_alloc(sizeof(int) * c->numTables, c->mempool);
- int n = size;
- for (int t = 0; t < c->numTables; ++t)
+ c->sizes[0] = size;
+ c->baseTable = (float*) mpool_alloc(sizeof(float) * c->sizes[0], c->mempool);
+ c->tables[0] = c->baseTable;
+ for (int t = 1; t < c->numTables; ++t)
{
- c->sizes[t] = n;
- c->tables[t] = (float*) mpool_alloc(sizeof(float) * c->sizes[t], m);
- n = c->sizes[t] / 2;
+ c->sizes[t] = c->sizes[t-1] / 2;
+ c->tables[t] = (float*) mpool_alloc(sizeof(float) * c->sizes[t], c->mempool);
}
// Copy table
for (int i = 0; i < c->sizes[0]; ++i)
{
- c->tables[0][i] = table[i];
+ c->baseTable[i] = table[i];
}
// Make bandlimited copies
// Not worth going over order 8 I think, and even 8 is only marginally better than 4.
- tButterworth_initToPool(&c->bl, 8, -1.0f, m->leaf->sampleRate * 0.25f, mp);
+ tButterworth_initToPool(&c->bl, 8, -1.0f, c->sampleRate * 0.25f, mp);
tOversampler_initToPool(&c->ds, 2, 1, mp);
for (int t = 1; t < c->numTables; ++t)
{
@@ -2130,6 +2248,67 @@
mpool_free((char*)c, c->mempool);
}
+void tWaveTableS_setSampleRate(tWaveTableS* const cy, float sr)
+{
+ _tWaveTableS* c = *cy;
+
+ int size = c->sizes[0];
+
+ for (int t = 1; t < c->numTables; ++t)
+ {
+ mpool_free((char*)c->tables[t], c->mempool);
+ }
+ mpool_free((char*)c->tables, c->mempool);
+ mpool_free((char*)c->sizes, c->mempool);
+
+ c->sampleRate = sr;
+
+ // Determine base frequency
+ c->baseFreq = c->sampleRate / (float) size;
+ c->invBaseFreq = 1.0f / c->baseFreq;
+
+ // Determine how many tables we need
+ c->numTables = 2;
+ float f = c->baseFreq;
+ while (f < c->maxFreq)
+ {
+ c->numTables++;
+ f *= 2.0f; // pass this multiplier in to set spacing of tables?
+ }
+
+ // Allocate memory for the tables
+ c->tables = (float**) mpool_alloc(sizeof(float*) * c->numTables, c->mempool);
+ c->sizes = (int*) mpool_alloc(sizeof(int) * c->numTables, c->mempool);
+ c->tables[0] = c->baseTable;
+ c->sizes[0] = size;
+ for (int t = 1; t < c->numTables; ++t)
+ {
+ c->sizes[t] = c->sizes[t-1] / 2;
+ c->tables[t] = (float*) mpool_alloc(sizeof(float) * c->sizes[t], c->mempool);
+ }
+
+ // Make bandlimited copies
+ // Not worth going over order 8 I think, and even 8 is only marginally better than 4.
+ tButterworth_initToPool(&c->bl, 8, -1.0f, c->sampleRate * 0.25f, &c->mempool);
+ tButterworth_setSampleRate(&c->bl, c->sampleRate);
+ tOversampler_initToPool(&c->ds, 2, 1, &c->mempool);
+ for (int t = 1; t < c->numTables; ++t)
+ {
+ // Similar to tWaveTable, doing multiple passes here helps, but not sure what number is optimal
+ for (int p = 0; p < 12; ++p)
+ {
+ for (int i = 0; i < c->sizes[t]; ++i)
+ {
+ c->dsBuffer[0] = tButterworth_tick(&c->bl, c->tables[t-1][i*2]);
+ c->dsBuffer[1] = tButterworth_tick(&c->bl, c->tables[t-1][(i*2)+1]);
+ c->tables[t][i] = tOversampler_downsample(&c->ds, c->dsBuffer);
+ }
+ }
+ }
+ tOversampler_free(&c->ds);
+ tButterworth_free(&c->bl);
+}
+
//================================================================================================
//================================================================================================
@@ -2143,7 +2322,9 @@
_tMempool* m = *mp;
_tWaveOscS* c = *cy = (_tWaveOscS*) mpool_alloc(sizeof(_tWaveOscS), m);
c->mempool = m;
+ LEAF* leaf = c->mempool->leaf;
+ c->invSampleRate = leaf->invSampleRate;
c->inc = 0.0f;
c->phase = 0.0f;
c->phaseOffset = 0.0f;
@@ -2201,12 +2382,10 @@
void tWaveOscS_setFreq(tWaveOscS* const cy, float freq)
{
_tWaveOscS* c = *cy;
-
- LEAF* leaf = c->mempool->leaf;
-
+
c->freq = freq;
- c->inc = c->freq * leaf->invSampleRate;
+ c->inc = c->freq * c->invSampleRate;
c->inc -= (int)c->inc;
// abs for negative frequencies
@@ -2233,6 +2412,13 @@
c->phaseOffset = phase - (int)phase;
}
+void tWaveOscS_setSampleRate(tWaveOscS* const cy, float sr)
+{
+ _tWaveOscS* c = *cy;
+ c->invSampleRate = 1.0f/sr;
+ tWaveOscS_setFreq(cy, c->freq);
+}
+
//================================================================================================
//================================================================================================
@@ -2384,6 +2570,16 @@
for (int v = 0; v < c->numVoices; ++v)
{
tWaveOscS_setPhaseOffset(&c->oscs[i][v], phase);
+ }
+}
+
+void tWaveSynthS_setSampleRate(tWaveSynthS* const cy, float sr)
+{
+ _tWaveSynthS* c = *cy;
+ for (int i = 0; i < c->numTables; ++i)
+ {
+ tWaveTableS_setSampleRate(&c->tables[i], sr);
+ for (int v = 0; v < c->numVoices; ++v) tWaveOscS_setSampleRate(&c->oscs[i][v], sr);
}
}
//
--- a/leaf/Src/leaf-physical.c
+++ b/leaf/Src/leaf-physical.c
@@ -29,6 +29,8 @@
p->mempool = m;
LEAF* leaf = p->mempool->leaf;
+ p->sampleRate = leaf->sampleRate;
+
if ( lowestFrequency <= 0.0f ) lowestFrequency = 10.0f;
tNoise_initToPool(&p->noise, WhiteNoise, mp);
@@ -37,7 +39,7 @@
tOneZero_initToPool(&p->loopFilter, 0.0f, mp);
- tAllpassDelay_initToPool(&p->delayLine, 0.0f, leaf->sampleRate * 2, mp);
+ tAllpassDelay_initToPool(&p->delayLine, 0.0f, p->sampleRate * 2, mp);
tAllpassDelay_clear(&p->delayLine);
tPluck_setFrequency(pl, 220.0f);
@@ -106,12 +108,11 @@
void tPluck_setFrequency (tPluck* const pl, float frequency )
{
_tPluck* p = *pl;
- LEAF* leaf = p->mempool->leaf;
if ( frequency <= 0.0f ) frequency = 0.001f;
// Delay = length - filter delay.
- float delay = ( leaf->sampleRate / frequency ) - tOneZero_getPhaseDelay(&p->loopFilter, frequency );
+ float delay = ( p->sampleRate / frequency ) - tOneZero_getPhaseDelay(&p->loopFilter, frequency );
tAllpassDelay_setDelay(&p->delayLine, delay );
@@ -118,7 +119,6 @@
p->loopGain = 0.99f + (frequency * 0.000005f);
if ( p->loopGain >= 0.999f ) p->loopGain = 0.999f;
-
}
// Perform the control change specified by \e number and \e value (0.0 - 128.0).
@@ -127,10 +127,18 @@
return;
}
-void tPluckSampleRateChanged(tPluck* const pl)
+void tPluck_setSampleRate(tPluck* const pl, float sr)
{
_tPluck* p = *pl;
+ p->sampleRate = sr;
+
+ tAllpassDelay_free(&p->delayLine);
+ tAllpassDelay_initToPool(&p->delayLine, 0.0f, p->sampleRate * 2, &p->mempool);
+ tAllpassDelay_clear(&p->delayLine);
+
tPluck_setFrequency(pl, p->lastFreq);
+ tOnePole_setSampleRate(&p->pickFilter, p->sampleRate);
+ tOneZero_setSampleRate(&p->loopFilter, p->sampleRate);
}
/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ tKarplusStrong ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
@@ -146,12 +154,14 @@
p->mempool = m;
LEAF* leaf = p->mempool->leaf;
+ p->sampleRate = leaf->sampleRate;
+
if ( lowestFrequency <= 0.0f ) lowestFrequency = 8.0f;
- tAllpassDelay_initToPool(&p->delayLine, 0.0f, leaf->sampleRate * 2, mp);
+ tAllpassDelay_initToPool(&p->delayLine, 0.0f, p->sampleRate * 2, mp);
tAllpassDelay_clear(&p->delayLine);
- tLinearDelay_initToPool(&p->combDelay, 0.0f, leaf->sampleRate * 2, mp);
+ tLinearDelay_initToPool(&p->combDelay, 0.0f, p->sampleRate * 2, mp);
tLinearDelay_clear(&p->combDelay);
tOneZero_initToPool(&p->filter, 0.0f, mp);
@@ -254,12 +264,11 @@
void tKarplusStrong_setFrequency (tKarplusStrong* const pl, float frequency )
{
_tKarplusStrong* p = *pl;
- LEAF* leaf = p->mempool->leaf;
if ( frequency <= 0.0f ) frequency = 0.001f;
p->lastFrequency = frequency;
- p->lastLength = leaf->sampleRate / p->lastFrequency;
+ p->lastLength = p->sampleRate / p->lastFrequency;
float delay = p->lastLength - 0.5f;
tAllpassDelay_setDelay(&p->delayLine, delay);
@@ -270,7 +279,6 @@
tKarplusStrong_setStretch(pl, p->stretching);
tLinearDelay_setDelay(&p->combDelay, 0.5f * p->pickupPosition * p->lastLength );
-
}
// Set the stretch "factor" of the string (0.0 - 1.0).
@@ -277,12 +285,11 @@
void tKarplusStrong_setStretch (tKarplusStrong* const pl, float stretch)
{
_tKarplusStrong* p = *pl;
- LEAF* leaf = p->mempool->leaf;
p->stretching = stretch;
float coefficient;
float freq = p->lastFrequency * 2.0f;
- float dFreq = ( (0.5f * leaf->sampleRate) - freq ) * 0.25f;
+ float dFreq = ( (0.5f * p->sampleRate) - freq ) * 0.25f;
float temp = 0.5f + (stretch * 0.5f);
if ( temp > 0.9999f ) temp = 0.9999f;
@@ -293,7 +300,7 @@
tBiQuad_setB0(&p->biquad[i], coefficient);
tBiQuad_setB2(&p->biquad[i], 1.0f);
- coefficient = -2.0f * temp * cosf(TWO_PI * freq / leaf->sampleRate);
+ coefficient = -2.0f * temp * cosf(TWO_PI * freq / p->sampleRate);
tBiQuad_setA1(&p->biquad[i], coefficient);
tBiQuad_setB1(&p->biquad[i], coefficient);
@@ -339,12 +346,26 @@
tKarplusStrong_setStretch( pl, 0.91f + (0.09f * (1.0f - normalizedValue)) );
}
-void tKarplusStrongSampleRateChanged (tKarplusStrong* const pl)
+void tKarplusStrong_setSampleRate (tKarplusStrong* const pl, float sr)
{
_tKarplusStrong* p = *pl;
+ p->sampleRate = sr;
+ tAllpassDelay_free(&p->delayLine);
+ tAllpassDelay_initToPool(&p->delayLine, 0.0f, p->sampleRate * 2, &p->mempool);
+ tAllpassDelay_clear(&p->delayLine);
+
+ tLinearDelay_free(&p->combDelay);
+ tLinearDelay_initToPool(&p->combDelay, 0.0f, p->sampleRate * 2, &p->mempool);
+ tLinearDelay_clear(&p->combDelay);
+
tKarplusStrong_setFrequency(pl, p->lastFrequency);
- tKarplusStrong_setStretch(pl, p->stretching);
+ tOneZero_setSampleRate(&p->filter, p->sampleRate);
+
+ for (int i = 0; i < 4; i++)
+ {
+ tBiQuad_setSampleRate(&p->biquad[i], p->sampleRate);
+ }
}
/* Simple Living String*/
@@ -365,8 +386,9 @@
p->mempool = m;
LEAF* leaf = p->mempool->leaf;
+ p->sampleRate = leaf->sampleRate;
p->curr=0.0f;
- tExpSmooth_initToPool(&p->wlSmooth, leaf->sampleRate/freq, 0.01f, mp); // smoother for string wavelength (not freq, to avoid expensive divisions)
+ tExpSmooth_initToPool(&p->wlSmooth, p->sampleRate/freq, 0.01f, mp); // smoother for string wavelength (not freq, to avoid expensive divisions)
tSimpleLivingString_setFreq(pl, freq);
tLinearDelay_initToPool(&p->delayLine,p->waveLengthInSamples, 2400, mp);
tLinearDelay_clear(&p->delayLine);
@@ -393,11 +415,10 @@
void tSimpleLivingString_setFreq(tSimpleLivingString* const pl, float freq)
{
_tSimpleLivingString* p = *pl;
- LEAF* leaf = p->mempool->leaf;
if (freq<20) freq=20;
else if (freq>10000) freq=10000;
- p->waveLengthInSamples = leaf->sampleRate/freq;
+ p->waveLengthInSamples = p->sampleRate/freq;
tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
}
@@ -466,6 +487,17 @@
return p->curr;
}
+void tSimpleLivingString_setSampleRate(tSimpleLivingString* const pl, float sr)
+{
+ _tSimpleLivingString* p = *pl;
+ float freq = p->sampleRate/p->waveLengthInSamples;
+ p->sampleRate = sr;
+ p->waveLengthInSamples = p->sampleRate/freq;
+ tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
+ tOnePole_setSampleRate(&p->bridgeFilter, p->sampleRate);
+ tHighpass_setSampleRate(&p->DCblocker, p->sampleRate);
+}
+
/* Living String*/
void tLivingString_init(tLivingString* const pl, float freq, float pickPos, float prepIndex,
@@ -484,8 +516,9 @@
p->mempool = m;
LEAF* leaf = p->mempool->leaf;
+ p->sampleRate = leaf->sampleRate;
p->curr=0.0f;
- tExpSmooth_initToPool(&p->wlSmooth, leaf->sampleRate/freq, 0.01f, mp); // smoother for string wavelength (not freq, to avoid expensive divisions)
+ tExpSmooth_initToPool(&p->wlSmooth, p->sampleRate/freq, 0.01f, mp); // smoother for string wavelength (not freq, to avoid expensive divisions)
tLivingString_setFreq(pl, freq);
p->freq = freq;
tExpSmooth_initToPool(&p->ppSmooth, pickPos, 0.01f, mp); // smoother for pick position
@@ -538,11 +571,10 @@
void tLivingString_setFreq(tLivingString* const pl, float freq)
{ // NOTE: It is faster to set wavelength in samples directly
_tLivingString* p = *pl;
- LEAF* leaf = p->mempool->leaf;
if (freq<20.f) freq=20.f;
else if (freq>10000.f) freq=10000.f;
- p->waveLengthInSamples = leaf->sampleRate/freq;
+ p->waveLengthInSamples = p->sampleRate/freq;
tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
}
@@ -658,7 +690,22 @@
return p->curr;
}
+void tLivingString_setSampleRate(tLivingString* const pl, float sr)
+{
+ _tLivingString* p = *pl;
+ float freq = p->sampleRate/p->waveLengthInSamples;
+ p->sampleRate = sr;
+ p->waveLengthInSamples = p->sampleRate/freq;
+ tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
+ tOnePole_setSampleRate(&p->bridgeFilter, p->sampleRate);
+ tOnePole_setSampleRate(&p->nutFilter, p->sampleRate);
+ tOnePole_setSampleRate(&p->prepFilterU, p->sampleRate);
+ tOnePole_setSampleRate(&p->prepFilterL, p->sampleRate);
+ tHighpass_setSampleRate(&p->DCblockerU, p->sampleRate);
+ tHighpass_setSampleRate(&p->DCblockerL, p->sampleRate);
+}
+
//////////---------------------------
/* Version of Living String with Hermite Interpolation */
/*Living String experiment 2 */
@@ -681,8 +728,9 @@
p->mempool = m;
LEAF* leaf = p->mempool->leaf;
+ p->sampleRate = leaf->sampleRate;
p->curr=0.0f;
- tExpSmooth_initToPool(&p->wlSmooth, leaf->sampleRate/freq, 0.1f, mp); // smoother for string wavelength (not freq, to avoid expensive divisions)
+ tExpSmooth_initToPool(&p->wlSmooth, p->sampleRate/freq, 0.1f, mp); // smoother for string wavelength (not freq, to avoid expensive divisions)
tLivingString2_setFreq(pl, freq);
p->freq = freq;
p->prepPos = prepPos;
@@ -742,12 +790,12 @@
void tLivingString2_setFreq(tLivingString2* const pl, float freq)
{ // NOTE: It is faster to set wavelength in samples directly
_tLivingString2* p = *pl;
- LEAF* leaf = p->mempool->leaf;
+
if (freq<20.f) freq=20.f;
else if (freq>10000.f) freq=10000.f;
freq = freq*2;
p->freq = freq;
- p->waveLengthInSamples = (leaf->sampleRate/freq) - 1;
+ p->waveLengthInSamples = (p->sampleRate/p->freq) - 1;
tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
}
@@ -754,12 +802,12 @@
void tLivingString2_setWaveLength(tLivingString2* const pl, float waveLength)
{
_tLivingString2* p = *pl;
- LEAF* leaf = p->mempool->leaf;
+
waveLength = waveLength * 0.5f;
if (waveLength<4.8f) waveLength=4.8f;
else if (waveLength>2400.f) waveLength=2400.f;
p->waveLengthInSamples = waveLength - 1;
- p->freq = leaf->sampleRate / waveLength;
+ p->freq = p->sampleRate / waveLength;
tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
}
@@ -927,7 +975,6 @@
tHermiteDelay_setDelay(&p->delLB, lowLen);
tHermiteDelay_setDelay(&p->delUF, upLen);
tHermiteDelay_setDelay(&p->delUB, upLen);
-
uint32_t pickupPosInt;
float pickupOut = 0.0f;
@@ -962,8 +1009,20 @@
return p->curr;
}
+void tLivingString2_setSampleRate(tLivingString2* const pl, float sr)
+{
+ _tLivingString2* p = *pl;
+ p->sampleRate = sr;
+ p->waveLengthInSamples = (p->sampleRate/p->freq) - 1;
+ tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
+ tTwoZero_setSampleRate(&p->bridgeFilter, p->sampleRate);
+ tTwoZero_setSampleRate(&p->nutFilter, p->sampleRate);
+ tTwoZero_setSampleRate(&p->prepFilterU, p->sampleRate);
+ tTwoZero_setSampleRate(&p->prepFilterL, p->sampleRate);
+ tHighpass_setSampleRate(&p->DCblockerU, p->sampleRate);
+ tHighpass_setSampleRate(&p->DCblockerL, p->sampleRate);
+}
-
//////////---------------------------
/* Complex Living String (has pick position and preparation position separated) */
@@ -984,8 +1043,9 @@
p->mempool = m;
LEAF* leaf = p->mempool->leaf;
+ p->sampleRate = leaf->sampleRate;
p->curr=0.0f;
- tExpSmooth_initToPool(&p->wlSmooth, leaf->sampleRate/freq, 0.01f, mp); // smoother for string wavelength (not freq, to avoid expensive divisions)
+ tExpSmooth_initToPool(&p->wlSmooth, p->sampleRate/freq, 0.01f, mp); // smoother for string wavelength (not freq, to avoid expensive divisions)
tComplexLivingString_setFreq(pl, freq);
p->freq = freq;
tExpSmooth_initToPool(&p->pickPosSmooth, pickPos, 0.01f, mp); // smoother for pick position
@@ -1050,11 +1110,10 @@
void tComplexLivingString_setFreq(tComplexLivingString* const pl, float freq)
{ // NOTE: It is faster to set wavelength in samples directly
_tComplexLivingString* p = *pl;
- LEAF* leaf = p->mempool->leaf;
if (freq<20.0f) freq=20.0f;
else if (freq>10000.0f) freq=10000.0f;
- p->waveLengthInSamples = leaf->sampleRate/freq;
+ p->waveLengthInSamples = p->sampleRate/freq;
tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
}
@@ -1205,7 +1264,20 @@
return p->curr;
}
-
+void tComplexLivingString_setSampleRate(tComplexLivingString* const pl, float sr)
+{
+ _tComplexLivingString* p = *pl;
+ float freq = p->waveLengthInSamples/p->sampleRate;
+ p->sampleRate = sr;
+ p->waveLengthInSamples = p->sampleRate/freq;
+ tExpSmooth_setDest(&p->wlSmooth, p->waveLengthInSamples);
+ tOnePole_setSampleRate(&p->bridgeFilter, p->sampleRate);
+ tOnePole_setSampleRate(&p->nutFilter, p->sampleRate);
+ tOnePole_setSampleRate(&p->prepFilterU, p->sampleRate);
+ tOnePole_setSampleRate(&p->prepFilterL, p->sampleRate);
+ tHighpass_setSampleRate(&p->DCblockerU, p->sampleRate);
+ tHighpass_setSampleRate(&p->DCblockerL, p->sampleRate);
+}
///Reed Table model
//default values from STK are 0.6 offset and -0.8 slope
--- a/leaf/Src/leaf-reverb.c
+++ b/leaf/Src/leaf-reverb.c
@@ -35,8 +35,11 @@
r->inv_441 = 1.0f/44100.0f;
+ r->sampleRate = leaf->sampleRate;
+ r->invSampleRate = leaf->invSampleRate;
+
int lengths[4] = { 341, 613, 1557, 2137 }; // Delay lengths for 44100 Hz sample rate.
- double scaler = leaf->sampleRate * r->inv_441;
+ double scaler = r->sampleRate * r->inv_441;
int delay, i;
if (scaler != 1.0f)
@@ -85,14 +88,12 @@
void tPRCReverb_setT60(tPRCReverb* const rev, float t60)
{
_tPRCReverb* r = *rev;
- LEAF* leaf = r->mempool->leaf;
if ( t60 <= 0.0f ) t60 = 0.001f;
r->t60 = t60;
- r->combCoeff = powf(10.0f, (-3.0f * tDelay_getDelay(&r->combDelay) * leaf->invSampleRate / t60 ));
-
+ r->combCoeff = powf(10.0f, (-3.0f * tDelay_getDelay(&r->combDelay) * r->invSampleRate / t60 ));
}
void tPRCReverb_setMix(tPRCReverb* const rev, float mix)
@@ -135,12 +136,40 @@
return out;
}
-void tPRCReverbSampleRateChanged (tPRCReverb* const rev)
+void tPRCReverb_setSampleRate (tPRCReverb* const rev, float sr)
{
_tPRCReverb* r = *rev;
- LEAF* leaf = r->mempool->leaf;
- r->combCoeff = powf(10.0f, (-3.0f * tDelay_getDelay(&r->combDelay) * leaf->invSampleRate / r->t60 ));
+ r->sampleRate = sr;
+ r->invSampleRate = 1.0f/r->sampleRate;
+
+ int lengths[4] = { 341, 613, 1557, 2137 }; // Delay lengths for 44100 Hz sample rate.
+ double scaler = r->sampleRate * r->inv_441;
+
+ int delay, i;
+ if (scaler != 1.0f)
+ {
+ for (i=0; i<4; i++)
+ {
+ delay = (int) scaler * lengths[i];
+
+ if ( (delay & 1) == 0) delay++;
+
+ while ( !LEAF_isPrime(delay) ) delay += 2;
+
+ lengths[i] = delay;
+ }
+ }
+
+ tDelay_free(&r->allpassDelays[0]);
+ tDelay_free(&r->allpassDelays[1]);
+ tDelay_free(&r->combDelay);
+
+ tDelay_initToPool(&r->allpassDelays[0], lengths[0], lengths[0] * 2, &r->mempool);
+ tDelay_initToPool(&r->allpassDelays[1], lengths[1], lengths[1] * 2, &r->mempool);
+ tDelay_initToPool(&r->combDelay, lengths[2], lengths[2] * 2, &r->mempool);
+
+ r->combCoeff = powf(10.0f, (-3.0f * tDelay_getDelay(&r->combDelay) * r->invSampleRate / r->t60 ));
}
/* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ NReverb ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ */
@@ -159,9 +188,11 @@
if (t60 <= 0.0f) t60 = 0.001f;
r->inv_441 = 1.0f/44100.0f;
+ r->sampleRate = leaf->sampleRate;
+ r->invSampleRate = leaf->invSampleRate;
int lengths[15] = {1433, 1601, 1867, 2053, 2251, 2399, 347, 113, 37, 59, 53, 43, 37, 29, 19}; // Delay lengths for 44100 Hz sample rate.
- double scaler = leaf->sampleRate / 25641.0f;
+ double scaler = r->sampleRate * r->inv_441;// / 25641.0f;
int delay, i;
@@ -179,7 +210,7 @@
{
tLinearDelay_initToPool(&r->combDelays[i], lengths[i], lengths[i] * 2, mp);
tLinearDelay_clear(&r->combDelays[i]);
- r->combCoeffs[i] = powf(10.0f, (-3.0f * (float)lengths[i] * leaf->invSampleRate / t60));
+ r->combCoeffs[i] = powf(10.0f, (-3.0f * (float)lengths[i] * r->invSampleRate / t60));
}
for ( i=0; i<8; i++ )
@@ -188,7 +219,6 @@
tLinearDelay_clear(&r->allpassDelays[i]);
}
-
tNReverb_setT60(rev, t60);
r->allpassCoeff = 0.7f;
r->mix = 0.3f;
@@ -214,14 +244,12 @@
void tNReverb_setT60(tNReverb* const rev, float t60)
{
_tNReverb* r = *rev;
- LEAF* leaf = r->mempool->leaf;
- if (t60 <= 0.0f) t60 = 0.001f;
+ if (t60 <= 0.0f) t60 = 0.001f;
r->t60 = t60;
- for (int i=0; i<6; i++) r->combCoeffs[i] = powf(10.0f, (-3.0f * tLinearDelay_getDelay(&r->combDelays[i]) * leaf->invSampleRate / t60 ));
-
+ for (int i=0; i<6; i++) r->combCoeffs[i] = powf(10.0f, (-3.0f * tLinearDelay_getDelay(&r->combDelays[i]) * r->invSampleRate / t60 ));
}
void tNReverb_setMix(tNReverb* const rev, float mix)
@@ -344,7 +372,6 @@
output[0] = -( r->allpassCoeff * temp2 ) + temp + drymix;
out = output[0];
-
temp = tLinearDelay_getLastOut(&r->allpassDelays[5]);
temp3 = r->allpassCoeff * temp;
temp3 += temp1;
@@ -354,12 +381,44 @@
r->lastOut = out;
}
-void tNReverbSampleRateChanged (tNReverb* const rev)
+void tNReverb_setSampleRate (tNReverb* const rev, float sr)
{
_tNReverb* r = *rev;
- LEAF* leaf = r->mempool->leaf;
- for (int i=0; i<6; i++) r->combCoeffs[i] = powf(10.0f, (-3.0f * tLinearDelay_getDelay(&r->combDelays[i]) * leaf->invSampleRate / r->t60 ));
+ r->sampleRate = sr;
+ r->invSampleRate = 1.0f/r->sampleRate;
+
+ int lengths[15] = {1433, 1601, 1867, 2053, 2251, 2399, 347, 113, 37, 59, 53, 43, 37, 29, 19}; // Delay lengths for 44100 Hz sample rate.
+ double scaler = r->sampleRate * r->inv_441;// / 25641.0f;
+
+ int delay, i;
+
+ for (i=0; i < 15; i++)
+ {
+ delay = (int) scaler * lengths[i];
+ if ( (delay & 1) == 0)
+ delay++;
+ while ( !LEAF_isPrime(delay) )
+ delay += 2;
+ lengths[i] = delay;
+ }
+
+ for ( i=0; i<6; i++ )
+ {
+ tLinearDelay_free(&r->combDelays[i]);
+ tLinearDelay_initToPool(&r->combDelays[i], lengths[i], lengths[i] * 2, &r->mempool);
+ tLinearDelay_clear(&r->combDelays[i]);
+ r->combCoeffs[i] = powf(10.0f, (-3.0f * (float)lengths[i] * r->invSampleRate / r->t60));
+ }
+
+ for ( i=0; i<8; i++ )
+ {
+ tLinearDelay_free(&r->allpassDelays[i]);
+ tLinearDelay_initToPool(&r->allpassDelays[i], lengths[i+6], lengths[i+6] * 2, &r->mempool);
+ tLinearDelay_clear(&r->allpassDelays[i]);
+ }
+
+ tNReverb_setT60(rev, r->t60);
}
// ======================================DATTORRO=========================================
@@ -369,7 +428,6 @@
float in_allpass_delays[4] = { 4.771f, 3.595f, 12.73f, 9.307f };
float in_allpass_gains[4] = { 0.75f, 0.75f, 0.625f, 0.625f };
-
void tDattorroReverb_init (tDattorroReverb* const rev, LEAF* const leaf)
{
tDattorroReverb_initToPool(rev, &leaf->mempool);
@@ -382,9 +440,11 @@
r->mempool = m;
LEAF* leaf = r->mempool->leaf;
+ r->sampleRate = leaf->sampleRate;
+
r->size_max = 2.0f;
r->size = 1.f;
- r->t = r->size * leaf->sampleRate * 0.001f;
+ r->t = r->size * r->sampleRate * 0.001f;
r->frozen = 0;
// INPUT
tTapeDelay_initToPool(&r->in_delay, 0.f, SAMP(200.f), mp);
@@ -426,16 +486,11 @@
tCycle_initToPool(&r->f2_lfo, mp);
tCycle_setFreq(&r->f2_lfo, 0.07f);
-
// PARAMETERS
tDattorroReverb_setMix(rev, 0.5f);
-
tDattorroReverb_setInputDelay(rev, 0.f);
-
tDattorroReverb_setInputFilter(rev, 10000.f);
-
tDattorroReverb_setFeedbackFilter(rev, 5000.f);
-
tDattorroReverb_setFeedbackGain(rev, 0.4f);
}
@@ -625,68 +680,67 @@
in_sample = tAllpass_tick(&r->in_allpass[i], in_sample);
}
+ // FEEDBACK 1
+ f1_sample = in_sample + r->f2_last; // + f2_last_out;
+
+ tAllpass_setDelay(&r->f1_allpass, SAMP(30.51f) + tCycle_tick(&r->f1_lfo) * SAMP(4.0f));
+
+ f1_sample = tAllpass_tick(&r->f1_allpass, f1_sample);
+
+ f1_sample = tTapeDelay_tick(&r->f1_delay_1, f1_sample);
+
+ f1_sample = tOnePole_tick(&r->f1_filter, f1_sample);
+
+ f1_sample = f1_sample + r->f1_delay_2_last * 0.5f;
+
+ f1_delay_2_sample = tTapeDelay_tick(&r->f1_delay_2, f1_sample * 0.5f);
+
+ r->f1_delay_2_last = f1_delay_2_sample;
+
+ f1_sample = r->f1_delay_2_last + f1_sample;
+
+ f1_sample = tHighpass_tick(&r->f1_hp, f1_sample);
+
+ f1_sample *= r->feedback_gain;
+
+ if (r->frozen)
+ {
+ f1_sample = 0.0f;
+ }
+
+ r->f1_last = tTapeDelay_tick(&r->f1_delay_3, f1_sample);
+
+ // FEEDBACK 2
+ f2_sample = in_sample + r->f1_last;
+
+ tAllpass_setDelay(&r->f2_allpass, SAMP(22.58f) + tCycle_tick(&r->f2_lfo) * SAMP(4.0f));
+
+ f2_sample = tAllpass_tick(&r->f2_allpass, f2_sample);
+
+ f2_sample = tTapeDelay_tick(&r->f2_delay_1, f2_sample);
+
+ f2_sample = tOnePole_tick(&r->f2_filter, f2_sample);
+
+ f2_sample = f2_sample + r->f2_delay_2_last * 0.5f;
+
+ f2_delay_2_sample = tTapeDelay_tick(&r->f2_delay_2, f2_sample * 0.5f);
+
+ r->f2_delay_2_last = f2_delay_2_sample;
+
+ f2_sample = r->f2_delay_2_last + f2_sample;
+
+ f2_sample = tHighpass_tick(&r->f2_hp, f2_sample);
+
+ f2_sample *= r->feedback_gain;
+
+ if (r->frozen)
+ {
+ f2_sample = 0.0f;
+ }
+ r->f2_last = tTapeDelay_tick(&r->f2_delay_3, f2_sample);
+
- // FEEDBACK 1
- f1_sample = in_sample + r->f2_last; // + f2_last_out;
- tAllpass_setDelay(&r->f1_allpass, SAMP(30.51f) + tCycle_tick(&r->f1_lfo) * SAMP(4.0f));
-
- f1_sample = tAllpass_tick(&r->f1_allpass, f1_sample);
-
- f1_sample = tTapeDelay_tick(&r->f1_delay_1, f1_sample);
-
- f1_sample = tOnePole_tick(&r->f1_filter, f1_sample);
-
- f1_sample = f1_sample + r->f1_delay_2_last * 0.5f;
-
- f1_delay_2_sample = tTapeDelay_tick(&r->f1_delay_2, f1_sample * 0.5f);
-
- r->f1_delay_2_last = f1_delay_2_sample;
-
- f1_sample = r->f1_delay_2_last + f1_sample;
-
- f1_sample = tHighpass_tick(&r->f1_hp, f1_sample);
-
- f1_sample *= r->feedback_gain;
-
- if (r->frozen)
- {
- f1_sample = 0.0f;
- }
-
- r->f1_last = tTapeDelay_tick(&r->f1_delay_3, f1_sample);
-
- // FEEDBACK 2
- f2_sample = in_sample + r->f1_last;
-
- tAllpass_setDelay(&r->f2_allpass, SAMP(22.58f) + tCycle_tick(&r->f2_lfo) * SAMP(4.0f));
-
- f2_sample = tAllpass_tick(&r->f2_allpass, f2_sample);
-
- f2_sample = tTapeDelay_tick(&r->f2_delay_1, f2_sample);
-
- f2_sample = tOnePole_tick(&r->f2_filter, f2_sample);
-
- f2_sample = f2_sample + r->f2_delay_2_last * 0.5f;
-
- f2_delay_2_sample = tTapeDelay_tick(&r->f2_delay_2, f2_sample * 0.5f);
-
- r->f2_delay_2_last = f2_delay_2_sample;
-
- f2_sample = r->f2_delay_2_last + f2_sample;
-
- f2_sample = tHighpass_tick(&r->f2_hp, f2_sample);
-
- f2_sample *= r->feedback_gain;
-
- if (r->frozen)
- {
- f2_sample = 0.0f;
- }
- r->f2_last = tTapeDelay_tick(&r->f2_delay_3, f2_sample);
-
-
-
// TAP OUT 1
f1_sample = tTapeDelay_tapOut(&r->f1_delay_1, SAMP(8.9f)) +
tTapeDelay_tapOut(&r->f1_delay_1, SAMP(99.8f));
@@ -730,7 +784,7 @@
r->mix = LEAF_clip(0.0f, mix, 1.0f);
}
-void tDattorroReverb_setFreeze (tDattorroReverb* const rev, uint32_t freeze)
+void tDattorroReverb_setFreeze (tDattorroReverb* const rev, int freeze)
{
_tDattorroReverb* r = *rev;
r->frozen = freeze;
@@ -772,10 +826,9 @@
void tDattorroReverb_setSize (tDattorroReverb* const rev, float size)
{
_tDattorroReverb* r = *rev;
- LEAF* leaf = r->mempool->leaf;
r->size = LEAF_clip(0.01f, size*r->size_max, r->size_max);
- r->t = r->size * leaf->sampleRate * 0.001f;
+ r->t = r->size * r->sampleRate * 0.001f;
/*
for (int i = 0; i < 4; i++)
@@ -834,4 +887,76 @@
{
_tDattorroReverb* r = *rev;
r->feedback_gain = gain;
+}
+
+void tDattorroReverb_setSampleRate (tDattorroReverb* const rev, float sr)
+{
+ _tDattorroReverb* r = *rev;
+ tMempool* mp = &r->mempool;
+
+ r->sampleRate = sr;
+ r->t = r->size * r->sampleRate * 0.001f;
+
+ // INPUT
+ tTapeDelay_free(&r->in_delay);
+
+ for (int i = 0; i < 4; i++)
+ {
+ tAllpass_free(&r->in_allpass[i]);
+ }
+
+ // FEEDBACK 1
+ tAllpass_free(&r->f1_allpass);
+
+ tTapeDelay_free(&r->f1_delay_1);
+ tTapeDelay_free(&r->f1_delay_2);
+ tTapeDelay_free(&r->f1_delay_3);
+
+ // FEEDBACK 2
+ tAllpass_free(&r->f2_allpass);
+
+ tTapeDelay_free(&r->f2_delay_1);
+ tTapeDelay_free(&r->f2_delay_2);
+ tTapeDelay_free(&r->f2_delay_3);
+
+ // INPUT
+ tTapeDelay_initToPool(&r->in_delay, 0.f, SAMP(200.f), mp);
+
+ for (int i = 0; i < 4; i++)
+ {
+ tAllpass_initToPool(&r->in_allpass[i], SAMP(in_allpass_delays[i]), SAMP(20.f), mp); // * r->size_max
+ tAllpass_setGain(&r->in_allpass[i], in_allpass_gains[i]);
+ }
+
+ // FEEDBACK 1
+ tAllpass_initToPool(&r->f1_allpass, SAMP(30.51f), SAMP(100.f), mp); // * r->size_max
+ tAllpass_setGain(&r->f1_allpass, 0.7f);
+
+ tTapeDelay_initToPool(&r->f1_delay_1, SAMP(141.69f), SAMP(200.0f) * r->size_max + 1, mp);
+ tTapeDelay_initToPool(&r->f1_delay_2, SAMP(89.24f), SAMP(100.0f) * r->size_max + 1, mp);
+ tTapeDelay_initToPool(&r->f1_delay_3, SAMP(125.f), SAMP(200.0f) * r->size_max + 1, mp);
+
+ // FEEDBACK 2
+ tAllpass_initToPool(&r->f2_allpass, SAMP(22.58f), SAMP(100.f), mp); // * r->size_max
+ tAllpass_setGain(&r->f2_allpass, 0.7f);
+
+ tTapeDelay_initToPool(&r->f2_delay_1, SAMP(149.62f), SAMP(200.f) * r->size_max + 1, mp);
+ tTapeDelay_initToPool(&r->f2_delay_2, SAMP(60.48f), SAMP(100.f) * r->size_max + 1, mp);
+ tTapeDelay_initToPool(&r->f2_delay_3, SAMP(106.28f), SAMP(200.f) * r->size_max + 1, mp);
+
+ tOnePole_setSampleRate(&r->in_filter, r->sampleRate);
+ tOnePole_setSampleRate(&r->f1_filter, r->sampleRate);
+ tHighpass_setSampleRate(&r->f1_hp, r->sampleRate);
+ tCycle_setSampleRate(&r->f1_lfo, r->sampleRate);
+ tOnePole_setSampleRate(&r->f2_filter, r->sampleRate);
+ tHighpass_setSampleRate(&r->f2_hp, r->sampleRate);
+ tCycle_setSampleRate(&r->f2_lfo, r->sampleRate);
+
+ // PARAMETERS
+ tDattorroReverb_setSize(rev, r->size*0.5f);
+ tDattorroReverb_setMix(rev, r->mix);
+ tDattorroReverb_setInputDelay(rev, r->predelay);
+ tDattorroReverb_setInputFilter(rev, r->input_filter);
+ tDattorroReverb_setFeedbackFilter(rev, r->feedback_filter);
+ tDattorroReverb_setFeedbackGain(rev, r->feedback_gain);
}
--- a/leaf/Src/leaf-sampling.c
+++ b/leaf/Src/leaf-sampling.c
@@ -34,9 +34,10 @@
_tMempool* m = *mp;
_tBuffer* s = *sb = (_tBuffer*) mpool_alloc(sizeof(_tBuffer), m);
s->mempool = m;
+ LEAF* leaf = s->mempool->leaf;
s->buff = (float*) mpool_alloc( sizeof(float) * length, m);
- s->sampleRate = s->mempool->leaf->sampleRate;
+ s->sampleRate = leaf->sampleRate;
s->channels = 1;
s->bufferLength = length;
s->recordedLength = 0;
@@ -191,13 +192,12 @@
_tBuffer* s = *b;
- p->leafInvSampleRate = leaf->invSampleRate;
- p->leafSampleRate = leaf->sampleRate;
- p->ticksPerSevenMs = 0.007f * p->leafSampleRate;
- p->rateFactor = s->sampleRate * p->leafInvSampleRate;
+ p->invSampleRate = leaf->invSampleRate;
+ p->sampleRate = leaf->sampleRate;
+ p->ticksPerSevenMs = 0.007f * p->sampleRate;
+ p->rateFactor = s->sampleRate * p->invSampleRate;
p->channels = s->channels;
-
p->samp = s;
p->active = 0;
@@ -255,9 +255,8 @@
_tBuffer* s = *b;
p->samp = s;
-
- p->rateFactor = s->sampleRate * p->leafInvSampleRate;
+ p->rateFactor = s->sampleRate * p->invSampleRate;
p->channels = s->channels;
p->start = 0;
@@ -268,8 +267,6 @@
p->idx = 0.f;
}
-
-
float tSampler_tick (tSampler* const sp)
{
_tSampler* p = *sp;
@@ -342,10 +339,7 @@
int32_t fadeRightEnd = myEnd;// + (fadeLeftEnd - start);
// if (fadeRightEnd >= length) fadeRightEnd = length - 1;
int32_t fadeRightStart = fadeRightEnd - cfxlen;
-
-
-
if (p->mode == PlayLoop)
{
@@ -532,7 +526,6 @@
return p->last;
}
-
float tSampler_tickStereo (tSampler* const sp, float* outputArray)
{
_tSampler* p = *sp;
@@ -611,9 +604,6 @@
// if (fadeRightEnd >= length) fadeRightEnd = length - 1;
int32_t fadeRightStart = fadeRightEnd - cfxlen;
-
-
-
if (p->mode == PlayLoop)
{
@@ -725,11 +715,8 @@
}
}
-
-
attemptStartEndChange(sp);
-
if (p->mode == PlayLoop)
{
if((int)p->idx < myStart)
@@ -782,9 +769,6 @@
outputArray[i] = outputArray[i] * sampleGain;
}
-
-
-
if (p->active < 0)
{
//if was fading out and reached silence
@@ -816,11 +800,8 @@
}
}
-
-
p->last = outputArray[0];
-
return p->last;
}
@@ -1089,6 +1070,18 @@
p->iinc = 1.f / p->inc;
}
+
+void tSampler_setSampleRate(tSampler* const sp, float sr)
+{
+ _tSampler* p = *sp;
+ _tBuffer* s = p->samp;
+ p->sampleRate = sr;
+ p->invSampleRate = 1.0f/p->sampleRate;
+ p->ticksPerSevenMs = 0.007f * p->sampleRate;
+ p->rateFactor = s->sampleRate * p->invSampleRate;
+ tRamp_setSampleRate(&p->gain, p->sampleRate);
+}
+
//==============================================================================
void tAutoSampler_init (tAutoSampler* const as, tBuffer* const b, LEAF* const leaf)
@@ -1212,6 +1205,11 @@
;
}
+void tAutoSampler_setSampleRate (tAutoSampler* const as, float sr)
+{
+ _tAutoSampler* a = *as;
+ tSampler_setSampleRate(&a->sampler, sr);
+}
void tMBSampler_init(tMBSampler* const sp, tBuffer* const b, LEAF* const leaf)
@@ -1267,8 +1265,6 @@
p->_p = 0.0f;
}
-
-
float tMBSampler_tick (tMBSampler* const sp)
{
--- a/leaf/Src/leaf.c
+++ b/leaf/Src/leaf.c
@@ -18,14 +18,12 @@
#endif
-void LEAF_init(LEAF* const leaf, float sr, int blocksize, char* memory, size_t memorysize, float(*random)(void))
+void LEAF_init(LEAF* const leaf, float sr, char* memory, size_t memorysize, float(*random)(void))
{
leaf->_internal_mempool.leaf = leaf;
leaf_pool_init(leaf, memory, memorysize);
leaf->sampleRate = sr;
-
- leaf->blockSize = blocksize;
leaf->invSampleRate = 1.0f/sr;
@@ -45,13 +43,11 @@
leaf->freeCount = 0;
}
-
-#define LEAFSampleRateChanged(THIS) leaf.THIS.sampleRateChanged(&leaf.THIS)
-
void LEAF_setSampleRate(LEAF* const leaf, float sampleRate)
{
leaf->sampleRate = sampleRate;
leaf->invSampleRate = 1.0f/sampleRate;
+ leaf->twoPiTimesInvSampleRate = leaf->invSampleRate * TWO_PI;
}
float LEAF_getSampleRate(LEAF* const leaf)
--- a/leaf/leaf.h
+++ b/leaf/leaf.h
@@ -142,13 +142,12 @@
//! Initialize the LEAF instance.
/*!
- @param sampleRate The audio sample rate.
- @param blockSize The audio block size.
+ @param sampleRate The default sample rate for object initialized to this LEAF instance.
@param memory A pointer to the memory that will make up the default mempool of a LEAF instance.
@param memorySize The size of the memory that will make up the default mempool of a LEAF instance.
@param random A pointer to a random number function. Should return a float >= 0 and < 1.
*/
- void LEAF_init (LEAF* const leaf, float sampleRate, int blockSize, char* memory, size_t memorySize, float(*random)(void));
+ void LEAF_init (LEAF* const leaf, float sampleRate, char* memory, size_t memorySize, float(*random)(void));
//! Set the sample rate of LEAF.
/*!