History

keep up with the Joneses

Jeffrey Snyder committed 4 years ago

Commit 30ed1911 parent c353a6b5 files · +568 −196Browse files

Unified · Split

5 files
  1. leaf/Inc/leaf-math.h +0 −5
  2. leaf/Inc/leaf-oscillators.h +75 −12
  3. leaf/Src/leaf-filters.c +29 −5
  4. leaf/Src/leaf-math.c +33 −33
  5. leaf/Src/leaf-oscillators.c +431 −141
leaf/Inc/leaf-math.h+0−5
@@ -18,7 +18,6 @@ extern "C" { · 17 unmodified lines
1818 #include "stdint.h"
1919 #include "stdlib.h"
2020 #include "limits.h"
21−
2221 //==============================================================================
2322
2423 //==============================================================================
@@ -234,11 +233,7 @@ extern "C" { · 209 unmodified lines
234233 float median3f(float a, float b, float c);
235234
236235 void place_step_dd(float *buffer, int index, float phase, float w, float scale);
237−
238236 void place_slope_dd(float *buffer, int index, float phase, float w, float slope_delta);
239−
240− /*! @} */
241−
242237 //==============================================================================
243238
244239 #ifdef __cplusplus
leaf/Inc/leaf-oscillators.h+75−12
@@ -721,8 +721,6 @@ extern "C" { · 720 unmodified lines
721721
722722 tMempool mempool;
723723 float out;
724− float amp;
725− float last_amp;
726724 float freq;
727725 float waveform; // duty cycle, must be in [-1, 1]
728726 float lastsyncin;
@@ -732,7 +730,6 @@ extern "C" { · 3 unmodified lines
732730 float _p, _w, _b, _x, _z;
733731 int _j, _k;
734732 float _f [FILLEN + STEP_DD_PULSE_LENGTH];
735− bool _init;
736733 float invSampleRate;
737734 } _tMBPulse;
738735
@@ -748,7 +745,7 @@ extern "C" { · 9 unmodified lines
748745 float tMBPulse_sync(tMBPulse* const osc, float sync);
749746 void tMBPulse_setPhase(tMBPulse* const osc, float phase);
750747 void tMBPulse_setSyncMode(tMBPulse* const osc, int hardOrSoft);
751− void tMBPulse_setBufferOffset(tMBPulse* const osc, int offset);
748+ void tMBPulse_setBufferOffset(tMBPulse* const osc, uint32_t offset);
752749 void tMBPulse_setSampleRate (tMBPulse* const osc, float sr);
753750
754751 /*!
@@ -796,8 +793,6 @@ extern "C" { · 41 unmodified lines
796793
797794 tMempool mempool;
798795 float out;
799− float amp;
800− float last_amp;
801796 float freq;
802797 float waveform; // duty cycle, must be in [-1, 1]
803798 float lastsyncin;
@@ -807,7 +802,6 @@ extern "C" { · 3 unmodified lines
807802 float _p, _w, _b, _z;
808803 int _j, _k;
809804 float _f [FILLEN + LONGEST_DD_PULSE_LENGTH];
810− bool _init;
811805 float invSampleRate;
812806 } _tMBTriangle;
813807
@@ -823,7 +817,7 @@ extern "C" { · 9 unmodified lines
823817 float tMBTriangle_sync(tMBTriangle* const osc, float sync);
824818 void tMBTriangle_setPhase(tMBTriangle* const osc, float phase);
825819 void tMBTriangle_setSyncMode(tMBTriangle* const osc, int hardOrSoft);
826− void tMBTriangle_setBufferOffset(tMBTriangle* const osc, int offset);
820+ void tMBTriangle_setBufferOffset(tMBTriangle* const osc, uint32_t offset);
827821 void tMBTriangle_setSampleRate (tMBTriangle* const osc, float sr);
828822
829823
@@ -871,8 +865,6 @@ extern "C" { · 41 unmodified lines
871865 {
872866 tMempool mempool;
873867 float out;
874− float amp;
875− float last_amp;
876868 float freq;
877869 float lastsyncin;
878870 float sync;
@@ -881,7 +873,6 @@ extern "C" { · 2 unmodified lines
881873 float _p, _w, _z;
882874 int _j;
883875 float _f [FILLEN + STEP_DD_PULSE_LENGTH];
884− bool _init;
885876 float invSampleRate;
886877 } _tMBSaw;
887878
@@ -896,11 +887,83 @@ extern "C" { · 8 unmodified lines
896887 float tMBSaw_sync(tMBSaw* const osc, float sync);
897888 void tMBSaw_setPhase(tMBSaw* const osc, float phase);
898889 void tMBSaw_setSyncMode(tMBSaw* const osc, int hardOrSoft);
899− void tMBSaw_setBufferOffset(tMBSaw* const osc, int offset);
890+ void tMBSaw_setBufferOffset(tMBSaw* const osc, uint32_t offset);
900891 void tMBSaw_setSampleRate (tMBSaw* const osc, float sr);
901892
902893 //==============================================================================
894+ /*!
895+ @defgroup tmbsaw tMBSawPulse
896+ @ingroup oscillators
897+ @brief Saw wave mixed with Pulse wave oscillator with minBLEP anti-aliasing.
898+ @{
899+
900+ @fn void tMBSaw_init(tMBSaw* const osc, LEAF* const leaf)
901+ @brief Initialize a tMBSaw to the default mempool of a LEAF instance.
902+ @param osc A pointer to the tMBSaw to initialize.
903+
904+ @fn void tMBSaw_initToPool(tMBSaw* const osc, tMempool* const mempool)
905+ @brief Initialize a tMBSaw to a specified mempool.
906+ @param osc A pointer to the tMBSaw to initialize.
907+
908+ @fn void tMBSaw_free(tMBSaw* const osc)
909+ @brief Free a tMBSaw from its mempool.
910+ @param osc A pointer to the tMBSaw to free.
911+
912+ @fn float tMBSaw_tick(tMBSaw* const osc)
913+ @brief Tick the oscillator.
914+ @param osc A pointer to the relevant tMBSaw.
915+ @return The ticked sample.
916+
917+ @fn void tMBSaw_setFreq(tMBSaw* const osc, float f)
918+ @brief Set the frequency of the oscillator.
919+ @param osc A pointer to the relevant tMBSaw.
920+ @param freq The new frequency.
921+
922+ @fn float tMBSaw_sync(tMBSaw* const osc, float sync)
923+ @brief Sync this oscillator to another signal.
924+ @param osc A pointer to the relevant tMBSaw.
925+ @param sync A sample of the signal to sync to.
926+ @return The passed in sample.
927+
928+ @fn void tMBSaw_setSyncMode(tMBSaw* const osc, int hardOrSoft)
929+ @brief Set the sync behavior of the oscillator.
930+ @param hardOrSoft 0 for hard sync, 1 for soft sync
931+ 
932+ @} */
933+
934+ typedef struct _tMBSawPulse
935+ {
936+ tMempool mempool;
937+ float out;
938+ float freq;
939+ float lastsyncin;
940+ float sync;
941+ float syncdir;
942+ int softsync;
943+ float waveform;
944+ float _p, _w, _b, _x, _z, _k;
945+ int _j;
946+ float _f [FILLEN + STEP_DD_PULSE_LENGTH];
947+ float invSampleRate;
948+ float shape;
949+ } _tMBSawPulse;
903950
951+ typedef _tMBSawPulse* tMBSawPulse;
952+
953+ void tMBSawPulse_init(tMBSawPulse* const osc, LEAF* const leaf);
954+ void tMBSawPulse_initToPool(tMBSawPulse* const osc, tMempool* const mempool);
955+ void tMBSawPulse_free(tMBSawPulse* const osc);
956+
957+ float tMBSawPulse_tick(tMBSawPulse* const osc);
958+ void tMBSawPulse_setFreq(tMBSawPulse* const osc, float f);
959+ float tMBSawPulse_sync(tMBSawPulse* const osc, float sync);
960+ void tMBSawPulse_setPhase(tMBSawPulse* const osc, float phase);
961+ void tMBSawPulse_setShape(tMBSawPulse* const osc, float shape);
962+ void tMBSawPulse_setSyncMode(tMBSawPulse* const osc, int hardOrSoft);
963+ void tMBSawPulse_setBufferOffset(tMBSawPulse* const osc, uint32_t offset);
964+ void tMBSawPulse_setSampleRate (tMBSawPulse* const osc, float sr);
965+
966+ //==============================================================================
904967 /*!
905968 @defgroup ttable tTable
906969 @ingroup oscillators
leaf/Src/leaf-filters.c+29−5
@@ -17,7 +17,10 @@ · 16 unmodified lines
1717 #include "../Inc/leaf-filters.h"
1818 #include "../Inc/leaf-tables.h"
1919 #include "../leaf.h"
20−//#include "tim.h"
20+#endif
21+
22+#ifdef ARM_MATH_CM7
23+#include "arm_math.h"
2124 #endif
2225
2326 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OnePole Filter ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ //
@@ -1821,12 +1824,15 @@ float tanhXdX(float x) · 1797 unmodified lines
18211824 }
18221825 return ((a + 105.0f)*a + 945.0f) / output;
18231826 }
1827+
18241828 volatile int errorCheckCheck = 0;
1829+//#define SAFE_FILTER
18251830 float tDiodeFilter_tick (tDiodeFilter* const vf, float in)
18261831 {
18271832 _tDiodeFilter* f = *vf;
1828−
1833+#ifdef SAFE_FILTER
18291834 int errorCheck = 0;
1835+#endif
18301836 // the input x[n+1] is given by 'in', and x[n] by zi
18311837 // input with half delay
18321838 float ih = 0.5f * (in + f->zi);
@@ -1840,24 +1846,30 @@ float tDiodeFilter_tick (tDiodeFilter* const vf, float in) · 7 unmodified lines
18401846
18411847 // This formula gives the result for y3 thanks to MATLAB
18421848 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);
1849+#ifdef SAFE_FILTER
18431850 if (isnan(y3))
18441851 {
18451852 errorCheck = 1;
18461853 }
1854+#endif
18471855 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;
1856+#ifdef SAFE_FILTER
18481857 if (isnan(tempy3denom))
18491858 {
18501859 errorCheck = 2;
18511860 }
1861+#endif
18521862 if (tempy3denom == 0.0f)
18531863 {
18541864 tempy3denom = 0.000001f;
18551865 }
18561866 y3 = y3 / tempy3denom;
1867+#ifdef SAFE_FILTER
18571868 if (isnan(y3))
18581869 {
18591870 errorCheck = 3;
18601871 }
1872+#endif
18611873 if (t1 == 0.0f)
18621874 {
18631875 t1 = 0.000001f;
@@ -1878,19 +1890,22 @@ float tDiodeFilter_tick (tDiodeFilter* const vf, float in) · 14 unmodified lines
18781890
18791891 // update state
18801892 f->s0 += 2.0f * (t0*xx + t1*(y1-y0));
1893+#ifdef SAFE_FILTER
18811894 if (isnan(f->s0))
18821895 {
18831896 errorCheck = 4;
18841897 }
1885−
1898+
18861899 if (isinf(f->s0))
18871900 {
18881901 errorCheck = 5;
18891902 }
1903+
18901904 if (errorCheck != 0)
18911905 {
1892− errorCheckCheck = 1;
1906+ errorCheckCheck = errorCheck;
18931907 }
1908+#endif
18941909 f->s1 += 2.0f * (t2*(y2-y1) - t1*(y1-y0));
18951910 f->s2 += 2.0f * (t3*(y3-y2) - t2*(y2-y1));
18961911 f->s3 += 2.0f * (-t4*(y3) - t3*(y3-y2));
@@ -1975,7 +1990,16 @@ void tLadderFilter_free (tLadderFilter* const vf) · 78 unmodified lines
19751990
19761991 float smoothABS ( float x, const float y) // y controls 'smoothness' usually between 0.002 -> 0.04
19771992 {
1978− return (sqrtf((x * x) + y)) - sqrtf(y);
1993+ //possible speedup with sqrt CMSIS-DSP approximation? seems to resolve to just a normal call to sqrt. Maybe the vector version since there are two square roots to determine? -JS
1994+// #ifdef ARM_MATH_CM7
1995+// float output1;
1996+// float output2;
1997+// arm_sqrt_f32((x * x) + y, &output1);
1998+// arm_sqrt_f32(y, &output2);
1999+// return output1 - output2;
2000+// #else
2001+ return (sqrtf((x * x) + y)) - sqrtf(y);
2002+// #endif
19792003 }
19802004
19812005 float smoothclip (float x, const float a, const float b) // assuming symmetrical clipping
leaf/Src/leaf-math.c+33−33
@@ -847,39 +847,39 @@ float median3f(float a, float b, float c) · 846 unmodified lines
847847 /// MINBLEPS
848848 // https://github.com/MrBlueXav/Dekrispator_v2 blepvco.c
849849 void place_step_dd(float *buffer, int index, float phase, float w, float scale)
850−{
851− float r;
852− long i;
853−
854− r = MINBLEP_PHASES * phase / w;
855− i = lrintf(r - 0.5f);
856− r -= (float)i;
857− i &= MINBLEP_PHASE_MASK; /* extreme modulation can cause i to be out-of-range */
858−
859− while (i < MINBLEP_PHASES * STEP_DD_PULSE_LENGTH) {
860− buffer[index] += scale * (step_dd_table[i].value + r * step_dd_table[i].delta);
861− i += MINBLEP_PHASES;
862− index++;
850+ {
851+ float r;
852+ long i;
853+
854+ r = MINBLEP_PHASES * phase / w;
855+ i = lrintf(r - 0.5f);
856+ r -= (float)i;
857+ i &= MINBLEP_PHASE_MASK; /* extreme modulation can cause i to be out-of-range */
858+
859+ while (i < MINBLEP_PHASES * STEP_DD_PULSE_LENGTH) {
860+ buffer[index] += scale * (step_dd_table[i].value + r * step_dd_table[i].delta);
861+ i += MINBLEP_PHASES;
862+ index++;
863+ }
863864 }
864−}
865−//----------------------------------------------------------------------------------------------------------
866−
867865 void place_slope_dd(float *buffer, int index, float phase, float w, float slope_delta)
868−{
869− float r;
870− long i;
871−
872− r = MINBLEP_PHASES * phase / w;
873− i = lrintf(r - 0.5f);
874− r -= (float)i;
875− i &= MINBLEP_PHASE_MASK; /* extreme modulation can cause i to be out-of-range */
876−
877− slope_delta *= w;
878−
879− while (i < MINBLEP_PHASES * SLOPE_DD_PULSE_LENGTH) {
880− buffer[index] += slope_delta * (slope_dd_table[i] + r * (slope_dd_table[i + 1] - slope_dd_table[i]));
881− i += MINBLEP_PHASES;
882− index++;
883− }
884−}
866+ {
867+ float r;
868+ long i;
869+
870+ r = MINBLEP_PHASES * phase / w;
871+ i = lrintf(r - 0.5f);
872+ r -= (float)i;
873+ i &= MINBLEP_PHASE_MASK; /* extreme modulation can cause i to be out-of-range */
874+
875+ slope_delta *= w;
876+
877+ while (i < MINBLEP_PHASES * SLOPE_DD_PULSE_LENGTH) {
878+ buffer[index] += slope_delta * (slope_dd_table[i] + r * (slope_dd_table[i + 1] - slope_dd_table[i]));
879+ i += MINBLEP_PHASES;
880+ index++;
881+ }
882+ }
885883 #endif // LEAF_INCLUDE_MINBLEP_TABLES
884+ /*! @} */
885+
leaf/Src/leaf-oscillators.c+431−141
@@ -938,8 +938,7 @@ void tMBPulse_initToPool(tMBPulse* const osc, tMempool* const pool) · 937 unmodified lines
938938
939939 c->invSampleRate = leaf->invSampleRate;
940940
941− c->_init = true;
942− c->amp = 1.0f;
941+
943942 c->freq = 440.f;
944943 c->lastsyncin = 0.0f;
945944 c->sync = 0.0f;
@@ -948,6 +947,12 @@ void tMBPulse_initToPool(tMBPulse* const osc, tMempool* const pool) · 2 unmodified lines
948947 c->waveform = 0.0f;
949948 c->_z = 0.0f;
950949 c->_j = 0;
950+ c->_p = 0.0f; /* phase [0, 1) */
951+ c->_w = c->freq * c->invSampleRate; /* phase increment */
952+ c->_b = 0.5f * (1.0f + c->waveform); /* duty cycle (0, 1) */
953+ c->_x = 0.5f; /* temporary output variable */
954+ c->_k = 0.0f; /* output state, 0 = high (0.5f), 1 = low (-0.5f) */
955+
951956 memset (c->_f, 0, (FILLEN + STEP_DD_PULSE_LENGTH) * sizeof (float));
952957 }
953958
@@ -962,11 +967,11 @@ float tMBPulse_tick(tMBPulse* const osc) · 8 unmodified lines
962967 _tMBPulse* c = *osc;
963968
964969 int j, k;
965− float freq, sync;
966− float a, b, p, w, x, z, sw;
970+ float sync;
971+ float b, p, w, x, z, sw;
967972
968973 sync = c->sync;
969− freq = c->freq;
974+
970975 p = c->_p; /* phase [0, 1) */
971976 w = c->_w; /* phase increment */
972977 b = c->_b; /* duty cycle (0, 1) */
@@ -974,30 +979,7 @@ float tMBPulse_tick(tMBPulse* const osc) · 1 unmodified line
974979 z = c->_z; /* low pass filter state */
975980 j = c->_j; /* index into buffer _f */
976981 k = c->_k; /* output state, 0 = high (0.5f), 1 = low (-0.5f) */
977− //
978− if (c->_init) {
979− p = 0.0f;
980−
981− w = freq * c->invSampleRate;
982− b = 0.5f * (1.0f + c->waveform );
983−
984− /* for variable-width rectangular wave, we could do DC compensation with:
985− * x = 1.0f - b;
986− * but that doesn't work well with highly modulated hard sync. Instead,
987− * we keep things in the range [-0.5f, 0.5f]. */
988− x = 0.5f;
989− /* if we valued alias-free startup over low startup time, we could do:
990− * p -= w;
991− * place_step_dd(_f, j, 0.0f, w, 0.5f); */
992− k = 0;
993− c->_init = false;
994− }
995− //
996− // a = 0.2 + 0.8 * vco->_port [FILT];
997− a = 0.5f; // when a = 1, LPfilter is disabled
998−
999− w = freq * c->invSampleRate;
1000− b = 0.5f * (1.0f + c->waveform);
982+
1001983
1002984 if (sync > 0.0f && c->softsync > 0) c->syncdir = -c->syncdir;
1003985
@@ -1163,8 +1145,8 @@ float tMBPulse_tick(tMBPulse* const osc) · 159 unmodified lines
11631145 }
11641146 c->_f[j + DD_SAMPLE_DELAY] += x;
11651147
1166− z += a * (c->_f[j] - z);
1167− c->out = c->amp * z;
1148+ z += 0.5f * (c->_f[j] - z);
1149+ c->out = z;
11681150
11691151 if (++j == FILLEN)
11701152 {
@@ -1188,6 +1170,7 @@ void tMBPulse_setFreq(tMBPulse* const osc, float f) · 17 unmodified lines
11881170 {
11891171 _tMBPulse* c = *osc;
11901172 c->freq = f;
1173+ c->_w = c->freq * c->invSampleRate; /* phase increment */
11911174 }
11921175
11931176 void tMBPulse_setWidth(tMBPulse* const osc, float w)
@@ -1219,10 +1202,10 @@ void tMBPulse_setPhase(tMBPulse* const osc, float phase) · 25 unmodified lines
12191202 }
12201203
12211204 //useful if you have several oscillators so the buffer refill is not synchronized
1222−void tMBPulse_setBufferOffset(tMBPulse* const osc, int offset)
1205+void tMBPulse_setBufferOffset(tMBPulse* const osc, uint32_t offset)
12231206 {
12241207 _tMBPulse* c = *osc;
1225− offset = LEAF_clip(0,offset, FILLEN-1);
1208+ offset = offset & (FILLEN-1);
12261209 c->_j = offset;
12271210 }
12281211
@@ -1254,16 +1237,18 @@ void tMBTriangle_initToPool(tMBTriangle* const osc, tMempool* const pool) · 25 unmodified lines
12541237 LEAF* leaf = c->mempool->leaf;
12551238
12561239 c->invSampleRate = leaf->invSampleRate;
1257− c->amp = 1.0f;
12581240 c->freq = 440.f;
12591241 c->lastsyncin = 0.0f;
12601242 c->sync = 0.0f;
12611243 c->syncdir = 1.0f;
12621244 c->softsync = 0;
12631245 c->waveform = 0.0f;
1264− c->_init = true;
12651246 c->_z = 0.0f;
12661247 c->_j = 0;
1248+ c->_p = 0.0f; /* phase [0, 1) */
1249+ c->_w = c->freq * c->invSampleRate; /* phase increment */
1250+ c->_b = 0.5f * (1.0f + c->waveform); /* duty cycle (0, 1) */
1251+ c->_k = 0.0f; /* output state, 0 = high (0.5f), 1 = low (-0.5f) */
12671252 memset (c->_f, 0, (FILLEN + STEP_DD_PULSE_LENGTH) * sizeof (float));
12681253 }
12691254
@@ -1277,41 +1262,27 @@ float tMBTriangle_tick(tMBTriangle* const osc) · 7 unmodified lines
12771262 {
12781263 _tMBTriangle* c = *osc;
12791264
1280− int j, k, dir;
1281− float freq, sync;
1282− float a, b, b1, p, w, sw, x, z;
1265+ int j, k;
1266+ float sync;
1267+ float b, b1, invB, invB1, p, w, sw, z;
1268+ float x = 0.5f;
12831269
12841270 sync = c->sync;
1285− dir = c->syncdir;
1286− freq = c->freq;
1271+
1272+
12871273 p = c->_p; /* phase [0, 1) */
12881274 w = c->_w; /* phase increment */
12891275 b = c->_b; /* duty cycle (0, 1) */
1276+ invB = 1.0f / b;
12901277 z = c->_z; /* low pass filter state */
12911278 j = c->_j; /* index into buffer _f */
12921279 k = c->_k; /* output state, 0 = positive slope, 1 = negative slope */
12931280
1294− if (c->_init) {
1295− // w = (exp2ap (freq[1] + vco->_port[OCTN] + vco->_port[TUNE] + expm[1] * vco->_port[EXPG] + 8.03136)
1296− // + 1e3 * linm[1] * vco->_port[LING]) / SAMPLERATE;
1297− w = freq * c->invSampleRate;
1298− b = 0.5f * (1.0f + c->waveform);
1299−// p = 0.5f * b;
1300− p = 0.f;
1301− /* if we valued alias-free startup over low startup time, we could do:
1302− * p -= w;
1303− * place_slope_dd(_f, j, 0.0f, w, 1.0f / b); */
1304− k = 0;
1305− c->_init = false;
1306− }
13071281
1308− // a = 0.2 + 0.8 * vco->_port [FILT];
1309− a = 0.5f; // when a = 1, LPfilter is disabled
1310−
1311− w = freq * c->invSampleRate;
1282+
13121283 b = 0.5f * (1.0f + c->waveform);
13131284 b1 = 1.0f - b;
1314−
1285+ invB1 = 1.0f / b1;
13151286 if (sync > 0.0f && c->softsync > 0) c->syncdir = -c->syncdir;
13161287
13171288 sw = w * c->syncdir;
@@ -1327,18 +1298,18 @@ float tMBTriangle_tick(tMBTriangle* const osc) · 9 unmodified lines
13271298 /* place any DDs that may have occurred in subsample before reset */
13281299
13291300 if (!k) {
1330− x = -0.5f + p_at_reset / b;
1301+ x = -0.5f + p_at_reset * invB;
13311302 if (sw > 0)
13321303 {
13331304 if (p_at_reset >= b) {
1334− x = 0.5f - (p_at_reset - b) / b1;
1335− place_slope_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -1.0f / b1 - 1.0f / b);
1305+ x = 0.5f - (p_at_reset - b) * invB1;
1306+ place_slope_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -invB1 - invB);
13361307 k = 1;
13371308 }
13381309 if (p_at_reset >= 1.0f) {
13391310 p_at_reset -= 1.0f;
1340− x = -0.5f + p_at_reset / b;
1341− place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, 1.0f / b + 1.0f / b1);
1311+ x = -0.5f + p_at_reset * invB;
1312+ place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, invB + invB1);
13421313 k = 0;
13431314 }
13441315 }
@@ -1346,43 +1317,43 @@ float tMBTriangle_tick(tMBTriangle* const osc) · 1 unmodified line
13461317 {
13471318 if (p_at_reset < 0.0f) {
13481319 p_at_reset += 1.0f;
1349− x = 0.5f - (p_at_reset - b) / b1;
1350− place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, 1.0f / b + 1.0f / b1);
1320+ x = 0.5f - (p_at_reset - b) * invB1;
1321+ place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, invB + invB1);
13511322 k = 1;
13521323 }
13531324 if (k && p_at_reset < b) {
1354− x = -0.5f + p_at_reset / b;
1355− place_slope_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, -1.0f / b1 - 1.0f / b);
1325+ x = -0.5f + p_at_reset * invB;
1326+ place_slope_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, -invB1 - invB);
13561327 k = 0;
13571328 }
13581329 }
13591330 } else {
1360− x = 0.5f - (p_at_reset - b) / b1;
1331+ x = 0.5f - (p_at_reset - b) * invB1;
13611332 if (sw > 0)
13621333 {
13631334 if (p_at_reset >= 1.0f) {
13641335 p_at_reset -= 1.0f;
1365− x = -0.5f + p_at_reset / b;
1366− place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, 1.0f / b + 1.0f / b1);
1336+ x = -0.5f + p_at_reset * invB;
1337+ place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, invB + invB1);
13671338 k = 0;
13681339 }
13691340 if (!k && p_at_reset >= b) {
1370− x = 0.5f - (p_at_reset - b) / b1;
1371− place_slope_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -1.0f / b1 - 1.0f / b);
1341+ x = 0.5f - (p_at_reset - b) * invB1;
1342+ place_slope_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -invB1 - invB);
13721343 k = 1;
13731344 }
13741345 }
13751346 else if (sw < 0)
13761347 {
13771348 if (p_at_reset < b) {
1378− x = -0.5f + p_at_reset / b;
1379− place_slope_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, -1.0f / b1 - 1.0f / b);
1349+ x = -0.5f + p_at_reset * invB;
1350+ place_slope_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, -invB1 - invB);
13801351 k = 0;
13811352 }
13821353 if (p_at_reset < 0.0f) {
13831354 p_at_reset += 1.0f;
1384− x = 0.5f - (p_at_reset - b) / b1;
1385− place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, 1.0f / b + 1.0f / b1);
1355+ x = 0.5f - (p_at_reset - b) * invB1;
1356+ place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, invB + invB1);
13861357 k = 1;
13871358 }
13881359 }
@@ -1392,43 +1363,43 @@ float tMBTriangle_tick(tMBTriangle* const osc) · 3 unmodified lines
13921363 if (sw > 0)
13931364 {
13941365 if (k)
1395− place_slope_dd(c->_f, j, p, sw, 1.0f / b + 1.0f / b1);
1366+ place_slope_dd(c->_f, j, p, sw, invB + invB1);
13961367 place_step_dd(c->_f, j, p, sw, -0.5f - x);
1397− x = -0.5f + p / b;
1368+ x = -0.5f + p * invB;
13981369 k = 0;
13991370 if (p >= b) {
1400− x = 0.5f - (p - b) / b1;
1401− place_slope_dd(c->_f, j, p - b, sw, -1.0f / b1 - 1.0f / b);
1371+ x = 0.5f - (p - b) * invB1;
1372+ place_slope_dd(c->_f, j, p - b, sw, -invB1 - invB);
14021373 k = 1;
14031374 }
14041375 }
14051376 else if (sw < 0)
14061377 {
14071378 if (!k)
1408− place_slope_dd(c->_f, j, 1.0f - p, -sw, 1.0f / b + 1.0f / b1);
1379+ place_slope_dd(c->_f, j, 1.0f - p, -sw, invB + invB1);
14091380 place_step_dd(c->_f, j, 1.0f - p, -sw, -0.5f - x);
1410− x = 0.5f - (p - b) / b1;
1381+ x = 0.5f - (p - b) * invB1;
14111382 k = 1;
14121383 if (p < b) {
1413− x = -0.5f + p / b;
1414− place_slope_dd(c->_f, j, b - p, -sw, -1.0f / b1 - 1.0f / b);
1384+ x = -0.5f + p * invB;
1385+ place_slope_dd(c->_f, j, b - p, -sw, -invB1 - invB);
14151386 k = 0;
14161387 }
14171388 }
14181389 } else if (!k) { /* normal operation, slope currently up */
14191390
1420− x = -0.5f + p / b;
1391+ x = -0.5f + p * invB;
14211392 if (sw > 0)
14221393 {
14231394 if (p >= b) {
1424− x = 0.5f - (p - b) / b1;
1425− place_slope_dd(c->_f, j, p - b, sw, -1.0f / b1 - 1.0f / b);
1395+ x = 0.5f - (p - b) * invB1;;
1396+ place_slope_dd(c->_f, j, p - b, sw, -invB1 - invB);
14261397 k = 1;
14271398 }
14281399 if (p >= 1.0f) {
14291400 p -= 1.0f;
1430− x = -0.5f + p / b;
1431− place_slope_dd(c->_f, j, p, sw, 1.0f / b + 1.0f / b1);
1401+ x = -0.5f + p * invB;
1402+ place_slope_dd(c->_f, j, p, sw, invB + invB1);
14321403 k = 0;
14331404 }
14341405 }
@@ -1436,53 +1407,53 @@ float tMBTriangle_tick(tMBTriangle* const osc) · 1 unmodified line
14361407 {
14371408 if (p < 0.0f) {
14381409 p += 1.0f;
1439− x = 0.5f - (p - b) / b1;
1440− place_slope_dd(c->_f, j, 1.0f - p, -sw, 1.0f / b + 1.0f / b1);
1410+ x = 0.5f - (p - b) * invB1;
1411+ place_slope_dd(c->_f, j, 1.0f - p, -sw, invB + invB1);
14411412 k = 1;
14421413 }
14431414 if (k && p < b) {
1444− x = -0.5f + p / b;
1445− place_slope_dd(c->_f, j, b - p, -sw, -1.0f / b1 - 1.0f / b);
1415+ x = -0.5f + p * invB;
1416+ place_slope_dd(c->_f, j, b - p, -sw, -invB1 - invB);
14461417 k = 0;
14471418 }
14481419 }
14491420
14501421 } else { /* normal operation, slope currently down */
14511422
1452− x = 0.5f - (p - b) / b1;
1423+ x = 0.5f - (p - b) * invB1;
14531424 if (sw > 0)
14541425 {
14551426 if (p >= 1.0f) {
14561427 p -= 1.0f;
1457− x = -0.5f + p / b;
1458− place_slope_dd(c->_f, j, p, sw, 1.0f / b + 1.0f / b1);
1428+ x = -0.5f + p * invB;
1429+ place_slope_dd(c->_f, j, p, sw, invB + invB1);
14591430 k = 0;
14601431 }
14611432 if (!k && p >= b) {
1462− x = 0.5f - (p - b) / b1;
1463− place_slope_dd(c->_f, j, p - b, sw, -1.0f / b1 - 1.0f / b);
1433+ x = 0.5f - (p - b) * invB1;
1434+ place_slope_dd(c->_f, j, p - b, sw, -invB1 - invB);
14641435 k = 1;
14651436 }
14661437 }
14671438 else if (sw < 0)
14681439 {
14691440 if (p < b) {
1470− x = -0.5f + p / b;
1471− place_slope_dd(c->_f, j, b - p, -sw, -1.0f / b1 - 1.0f / b);
1441+ x = -0.5f + p * invB;
1442+ place_slope_dd(c->_f, j, b - p, -sw, -invB1 - invB);
14721443 k = 0;
14731444 }
14741445 if (p < 0.0f) {
14751446 p += 1.0f;
1476− x = 0.5f - (p - b) / b1;
1477− place_slope_dd(c->_f, j, 1.0f - p, -sw, 1.0f / b + 1.0f / b1);
1447+ x = 0.5f - (p - b) * invB1;
1448+ place_slope_dd(c->_f, j, 1.0f - p, -sw, invB + invB1);
14781449 k = 1;
14791450 }
14801451 }
14811452 }
14821453 c->_f[j + DD_SAMPLE_DELAY] += x;
14831454
1484− z += a * (c->_f[j] - z);
1485− c->out = c->amp * z;
1455+ z += 0.5f * (c->_f[j] - z);
1456+ c->out = z;
14861457
14871458 if (++j == FILLEN)
14881459 {
@@ -1505,6 +1476,7 @@ void tMBTriangle_setFreq(tMBTriangle* const osc, float f) · 16 unmodified lines
15051476 {
15061477 _tMBTriangle* c = *osc;
15071478 c->freq = f;
1479+ c->_w = c->freq * c->invSampleRate; /* phase increment */
15081480 }
15091481
15101482 void tMBTriangle_setWidth(tMBTriangle* const osc, float w)
@@ -1542,10 +1514,10 @@ void tMBTriangle_setSyncMode(tMBTriangle* const osc, int hardOrSoft) · 31 unmodified lines
15421514 }
15431515
15441516 //useful if you have several oscillators so the buffer refill is not synchronized
1545−void tMBTriangle_setBufferOffset(tMBTriangle* const osc, int offset)
1517+void tMBTriangle_setBufferOffset(tMBTriangle* const osc, uint32_t offset)
15461518 {
15471519 _tMBTriangle* c = *osc;
1548− offset = LEAF_clip(0,offset, FILLEN-1);
1520+ offset = offset & (FILLEN-1);
15491521 c->_j = offset;
15501522 }
15511523
@@ -1571,8 +1543,6 @@ void tMBSaw_initToPool(tMBSaw* const osc, tMempool* const pool) · 19 unmodified lines
15711543 LEAF* leaf = c->mempool->leaf;
15721544
15731545 c->invSampleRate = leaf->invSampleRate;
1574− c->_init = true;
1575− c->amp = 1.0f;
15761546 c->freq = 440.f;
15771547 c->lastsyncin = 0.0f;
15781548 c->sync = 0.0f;
@@ -1580,6 +1550,9 @@ void tMBSaw_initToPool(tMBSaw* const osc, tMempool* const pool) · 1 unmodified line
15801550 c->softsync = 0;
15811551 c->_z = 0.0f;
15821552 c->_j = 0;
1553+ c->_p = 0.0f; /* phase [0, 1) */
1554+ c->_w = c->freq * c->invSampleRate; /* phase increment */
1555+
15831556 memset (c->_f, 0, (FILLEN + STEP_DD_PULSE_LENGTH) * sizeof (float));
15841557 }
15851558
@@ -1594,45 +1567,30 @@ float tMBSaw_tick(tMBSaw* const osc) · 8 unmodified lines
15941567 _tMBSaw* c = *osc;
15951568
15961569 int j;
1597− float freq, sync;
1598− float a, p, w, sw, z;
1570+ float sync;
1571+ float p, w, sw, z;
15991572
16001573 sync = c->sync;
1601− freq = c->freq;
1574+
16021575
16031576 p = c->_p; /* phase [0, 1) */
16041577 w = c->_w; /* phase increment */
16051578 z = c->_z; /* low pass filter state */
16061579 j = c->_j; /* index into buffer _f */
1607−
1608− if (c->_init) {
1609−// p = 0.5f;
1610− p = 0.f;
1611− w = freq * c->invSampleRate;
1612−
1613− /* if we valued alias-free startup over low startup time, we could do:
1614− * p -= w;
1615− * place_slope_dd(_f, j, 0.0f, w, -1.0f); */
1616− c->_init = false;
1617− }
1618−
1619− //a = 0.2 + 0.8 * vco->_port [FILT];
1620− a = 0.5f; // when a = 1, LPfilter is disabled
1621−
1622− w = freq * c->invSampleRate;
1580+
16231581
16241582 if (sync > 0.0f && c->softsync > 0) c->syncdir = -c->syncdir;
16251583 // Should insert minblep for softsync?
1626− // if (p_at_reset >= 1.0f) {
1627− // p_at_reset -= (int)p_at_reset;
1628− // place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, 2.0f);
1629− // }
1630− // if (p_at_reset < 0.0f) {
1631− // p_at_reset += 1.0f - (int)p_at_reset;
1632− // place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, -2.0f);
1633− // }
1634− // if (sw > 0) place_slope_dd(c->_f, j, p, sw, 2.0f);
1635− // else if (sw < 0) place_slope_dd(c->_f, j, 1.0f - p, -sw, -2.0f);
1584+ // if (p_at_reset >= 1.0f) {
1585+ // p_at_reset -= (int)p_at_reset;
1586+ // place_slope_dd(c->_f, j, p_at_reset + eof_offset, sw, 2.0f);
1587+ // }
1588+ // if (p_at_reset < 0.0f) {
1589+ // p_at_reset += 1.0f - (int)p_at_reset;
1590+ // place_slope_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, -2.0f);
1591+ // }
1592+ // if (sw > 0) place_slope_dd(c->_f, j, p, sw, 2.0f);
1593+ // else if (sw < 0) place_slope_dd(c->_f, j, 1.0f - p, -sw, -2.0f);
16361594
16371595 sw = w * c->syncdir;
16381596 p += sw - (int)sw;
@@ -1670,8 +1628,8 @@ float tMBSaw_tick(tMBSaw* const osc) · 31 unmodified lines
16701628 }
16711629 c->_f[j + DD_SAMPLE_DELAY] += 0.5f - p;
16721630
1673− z += a * (c->_f[j] - z); // LP filtering
1674− c->out = c->amp * z;
1631+ z += 0.5f * (c->_f[j] - z); // LP filtering
1632+ c->out = z;
16751633
16761634 if (++j == FILLEN)
16771635 {
@@ -1692,6 +1650,8 @@ void tMBSaw_setFreq(tMBSaw* const osc, float f) · 14 unmodified lines
16921650 {
16931651 _tMBSaw* c = *osc;
16941652 c->freq = f;
1653+
1654+ c->_w = c->freq * c->invSampleRate;
16951655 }
16961656
16971657 float tMBSaw_sync(tMBSaw* const osc, float value)
@@ -1723,10 +1683,10 @@ void tMBSaw_setSyncMode(tMBSaw* const osc, int hardOrSoft) · 25 unmodified lines
17231683 }
17241684
17251685 //useful if you have several oscillators so the buffer refill is not synchronized
1726−void tMBSaw_setBufferOffset(tMBSaw* const osc, int offset)
1686+void tMBSaw_setBufferOffset(tMBSaw* const osc, uint32_t offset)
17271687 {
17281688 _tMBSaw* c = *osc;
1729− offset = LEAF_clip(0,offset, FILLEN-1);
1689+ offset = offset & (FILLEN-1);
17301690 c->_j = offset;
17311691 }
17321692
@@ -1737,6 +1697,336 @@ void tMBSaw_setSampleRate(tMBSaw* const osc, float sr) · 4 unmodified lines
17371697 }
17381698
17391699
1700+//==================================================================================================
1701+
1702+void tMBSawPulse_init(tMBSawPulse* const osc, LEAF* const leaf)
1703+{
1704+ tMBSawPulse_initToPool(osc, &leaf->mempool);
1705+}
1706+
1707+void tMBSawPulse_initToPool(tMBSawPulse* const osc, tMempool* const pool)
1708+{
1709+ _tMempool* m = *pool;
1710+ _tMBSawPulse* c = *osc = (_tMBSawPulse*) mpool_alloc(sizeof(_tMBSawPulse), m);
1711+ c->mempool = m;
1712+ LEAF* leaf = c->mempool->leaf;
1713+
1714+ c->invSampleRate = leaf->invSampleRate;
1715+ c->freq = 440.f;
1716+ c->lastsyncin = 0.0f;
1717+ c->sync = 0.0f;
1718+ c->syncdir = 1.0f;
1719+ c->softsync = 0;
1720+ c->waveform = 0.0f;
1721+ c->_z = 0.0f;
1722+ c->_j = 0;
1723+ c->_p = 0.0f; /* phase [0, 1) */
1724+ c->_w = c->freq * c->invSampleRate; /* phase increment */
1725+ c->_b = 0.5f * (1.0f + c->waveform); /* duty cycle (0, 1) */
1726+ c->_x = 0.5f; /* temporary output variable */
1727+ c->_k = 0.0f; /* output state, 0 = high (0.5f), 1 = low (-0.5f) */
1728+
1729+ memset (c->_f, 0, (FILLEN + STEP_DD_PULSE_LENGTH) * sizeof (float));
1730+}
1731+
1732+void tMBSawPulse_free(tMBSawPulse* const osc)
1733+{
1734+ _tMBSawPulse* c = *osc;
1735+ mpool_free((char*)c, c->mempool);
1736+}
1737+
1738+
1739+
1740+
1741+
1742+
1743+
1744+float tMBSawPulse_tick(tMBSawPulse* const osc)
1745+{
1746+ _tMBSawPulse* c = *osc;
1747+
1748+ int j, k;
1749+ float sync;
1750+ float b, p, w, x, z, sw;
1751+ float shape = c->shape;
1752+ float sawShape = 1.0f - c->shape;
1753+ sync = c->sync;
1754+ p = c->_p; /* phase [0, 1) */
1755+ w = c->_w; /* phase increment */
1756+ b = c->_b; /* duty cycle (0, 1) */
1757+ x = c->_x; /* temporary output variable */
1758+ z = c->_z; /* low pass filter state */
1759+ j = c->_j; /* index into buffer _f */
1760+ k = c->_k; /* output state, 0 = high (0.5f), 1 = low (-0.5f) */
1761+
1762+ if (sync > 0.0f && c->softsync > 0) c->syncdir = -c->syncdir;
1763+
1764+ sw = w * c->syncdir;
1765+ p += sw - (int)sw;
1766+
1767+ if (sync > 0.0f && c->softsync == 0)
1768+ { /* sync to master */
1769+ float eof_offset = sync * sw;
1770+ float p_at_reset = p - eof_offset;
1771+
1772+ if (sw > 0) p = eof_offset;
1773+ else if (sw < 0) p = 1.0f - eof_offset;
1774+
1775+ //pulse stuff
1776+ /* place any DDs that may have occurred in subsample before reset */
1777+ if (!k)
1778+ {
1779+ if (sw > 0)
1780+ {
1781+ if (p_at_reset >= b)
1782+ {
1783+ place_step_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -1.0f * shape);
1784+ k = 1;
1785+ x = -0.5f;
1786+ }
1787+ if (p_at_reset >= 1.0f)
1788+ {
1789+ p_at_reset -= 1.0f;
1790+ place_step_dd(c->_f, j, p_at_reset + eof_offset, sw, 1.0f);
1791+ k = 0;
1792+ x = 0.5f;
1793+ }
1794+ }
1795+ else if (sw < 0)
1796+ {
1797+ if (p_at_reset < 0.0f)
1798+ {
1799+ p_at_reset += 1.0f;
1800+ place_step_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, -1.0f);
1801+ k = 1;
1802+ x = -0.5f;
1803+ }
1804+ if (k && p_at_reset < b)
1805+ {
1806+ place_step_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, 1.0f * shape);
1807+ k = 0;
1808+ x = 0.5f;
1809+ }
1810+ }
1811+ }
1812+ else
1813+ {
1814+ if (sw > 0)
1815+ {
1816+ if (p_at_reset >= 1.0f)
1817+ {
1818+ p_at_reset -= 1.0f;
1819+ place_step_dd(c->_f, j, p_at_reset + eof_offset, sw, 1.0f);
1820+ k = 0;
1821+ x = 0.5f;
1822+ }
1823+ if (!k && p_at_reset >= b)
1824+ {
1825+ place_step_dd(c->_f, j, p_at_reset - b + eof_offset, sw, -1.0f * shape);
1826+ k = 1;
1827+ x = -0.5f;
1828+ }
1829+ }
1830+ else if (sw < 0)
1831+ {
1832+ if (p_at_reset < b)
1833+ {
1834+ place_step_dd(c->_f, j, b - p_at_reset - eof_offset, -sw, 1.0f * shape);
1835+ k = 0;
1836+ x = 0.5f;
1837+ }
1838+ if (p_at_reset < 0.0f)
1839+ {
1840+ p_at_reset += 1.0f;
1841+ place_step_dd(c->_f, j, 1.0f - p_at_reset - eof_offset, -sw, -1.0f);
1842+ k = 1;
1843+ x = -0.5f;
1844+ }
1845+ }
1846+ }
1847+
1848+
1849+ /* now place reset DD for pulse */
1850+ if (sw > 0)
1851+ {
1852+ if (k) {
1853+ place_step_dd(c->_f, j, p, sw, 1.0f * shape);
1854+ k = 0;
1855+ x = 0.5f;
1856+ }
1857+ if (p >= b) {
1858+ place_step_dd(c->_f, j, p - b, sw, -1.0f * shape);
1859+ k = 1;
1860+ x = -0.5f;
1861+ }
1862+ }
1863+ else if (sw < 0)
1864+ {
1865+ if (!k) {
1866+ place_step_dd(c->_f, j, 1.0f - p, -sw, -1.0f * shape);
1867+ k = 1;
1868+ x = -0.5f;
1869+ }
1870+ if (p < b) {
1871+ place_step_dd(c->_f, j, b - p, -sw, 1.0f * shape);
1872+ k = 0;
1873+ x = 0.5f;
1874+ }
1875+ }
1876+ /* now place reset DD for saw*/
1877+ if (sw > 0)
1878+ place_step_dd(c->_f, j, p, sw, p_at_reset * sawShape);
1879+ else if (sw < 0)
1880+ place_step_dd(c->_f, j, 1.0f - p, -sw, -p_at_reset * sawShape);
1881+
1882+ }
1883+
1884+
1885+ else if (!k)
1886+ { /* normal operation for pulse, signal currently high */
1887+
1888+ if (sw > 0)
1889+ {
1890+ if (p >= b) {
1891+ place_step_dd(c->_f, j, p - b, sw, -1.0f * shape);
1892+ k = 1;
1893+ x = -0.5f;
1894+ }
1895+ if (p >= 1.0f) {
1896+ p -= 1.0f;
1897+ place_step_dd(c->_f, j, p, sw, 1.0f);
1898+ k = 0;
1899+ x = 0.5f;
1900+ }
1901+ }
1902+ else if (sw < 0)
1903+ {
1904+ if (p < 0.0f) {
1905+ p += 1.0f;
1906+ place_step_dd(c->_f, j, 1.0f - p, -sw, -1.0f);
1907+ k = 1;
1908+ x = -0.5f;
1909+ }
1910+ if (k && p < b) {
1911+ place_step_dd(c->_f, j, b - p, -sw, 1.0f * shape);
1912+ k = 0;
1913+ x = 0.5f;
1914+ }
1915+ }
1916+
1917+ } else { /* normal operation, signal currently low */
1918+
1919+ if (sw > 0)
1920+ {
1921+ if (p >= 1.0f) {
1922+ p -= 1.0f;
1923+ place_step_dd(c->_f, j, p, sw, 1.0f);
1924+ k = 0;
1925+ x = 0.5f;
1926+ }
1927+ if (!k && p >= b) {
1928+ place_step_dd(c->_f, j, p - b, sw, -1.0f * shape);
1929+ k = 1;
1930+ x = -0.5f;
1931+ }
1932+ }
1933+ else if (sw < 0)
1934+ {
1935+ if (p < b) {
1936+ place_step_dd(c->_f, j, b - p, -sw, 1.0f * shape);
1937+ k = 0;
1938+ x = 0.5f;
1939+ }
1940+ if (p < 0.0f) {
1941+ p += 1.0f;
1942+ place_step_dd(c->_f, j, 1.0f - p, -sw, -1.0f);
1943+ k = 1;
1944+ x = -0.5f;
1945+ }
1946+ }
1947+ }
1948+
1949+ c->_f[j + DD_SAMPLE_DELAY] += ((0.5f - p) * sawShape); //saw
1950+
1951+ c->_f[j + DD_SAMPLE_DELAY] += (x * shape);//pulse
1952+
1953+ z += 0.5f * (c->_f[j] - z); // LP filtering
1954+ c->out = z;
1955+
1956+ if (++j == FILLEN)
1957+ {
1958+ j = 0;
1959+ memcpy (c->_f, c->_f + FILLEN, STEP_DD_PULSE_LENGTH * sizeof (float));
1960+ memset (c->_f + STEP_DD_PULSE_LENGTH, 0, FILLEN * sizeof (float));
1961+ }
1962+
1963+ c->_p = p;
1964+ c->_w = w;
1965+ c->_b = b;
1966+ c->_x = x;
1967+ c->_z = z;
1968+ c->_j = j;
1969+ c->_k = k;
1970+
1971+ return -c->out;
1972+}
1973+
1974+void tMBSawPulse_setFreq(tMBSawPulse* const osc, float f)
1975+{
1976+ _tMBSawPulse* c = *osc;
1977+ c->freq = f;
1978+ c->_w = c->freq * c->invSampleRate; /* phase increment */
1979+}
1980+
1981+float tMBSawPulse_sync(tMBSawPulse* const osc, float value)
1982+{
1983+ _tMBSawPulse* c = *osc;
1984+
1985+ //based on https://github.com/VCVRack/Fundamental/blob/5799ee2a9b21492b42ebcb9b65d5395ef5c1cbe2/src/VCO.cpp#L123
1986+ float last = c->lastsyncin;
1987+ float delta = value - last;
1988+ float crossing = -last / delta;
1989+ c->lastsyncin = value;
1990+ if ((0.f < crossing) && (crossing <= 1.f) && (value >= 0.f))
1991+ c->sync = (1.f - crossing) * delta;
1992+ else c->sync = 0.f;
1993+
1994+ return value;
1995+}
1996+
1997+void tMBSawPulse_setPhase(tMBSawPulse* const osc, float phase)
1998+{
1999+ _tMBSawPulse* c = *osc;
2000+ c->_p = phase;
2001+}
2002+
2003+void tMBSawPulse_setShape(tMBSawPulse* const osc, float shape)
2004+{
2005+ _tMBSawPulse* c = *osc;
2006+ c->shape = shape;
2007+}
2008+
2009+void tMBSawPulse_setSyncMode(tMBSawPulse* const osc, int hardOrSoft)
2010+{
2011+ _tMBSawPulse* c = *osc;
2012+ c->softsync = hardOrSoft > 0 ? 1 : 0;
2013+}
2014+
2015+//useful if you have several oscillators so the buffer refill is not synchronized
2016+void tMBSawPulse_setBufferOffset(tMBSawPulse* const osc, uint32_t offset)
2017+{
2018+ _tMBSawPulse* c = *osc;
2019+ offset = offset & (FILLEN-1);
2020+ c->_j = offset;
2021+}
2022+
2023+void tMBSawPulse_setSampleRate(tMBSawPulse* const osc, float sr)
2024+{
2025+ _tMBSawPulse* c = *osc;
2026+ c->invSampleRate = 1.0f/sr;
2027+}
2028+
2029+
17402030 // WaveTable
17412031 void tTable_init(tTable* const cy, float* waveTable, int size, LEAF* const leaf)
17422032 {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t