Unified · Split
Binary file not shown.
Binary file not shown.
| @@ -51,6 +51,30 @@ extern "C" { · 50 unmodified lines | |||
| 51 | int tEnvelopeFollower_decayCoeff (tEnvelopeFollower* const, float decayCoeff); | 51 | int tEnvelopeFollower_decayCoeff (tEnvelopeFollower* const, float decayCoeff); |
| 52 | int tEnvelopeFollower_attackThresh (tEnvelopeFollower* const, float attackThresh); | 52 | int tEnvelopeFollower_attackThresh (tEnvelopeFollower* const, float attackThresh); |
| 53 | 53 | ||
| 54 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | ||
| 55 | |||
| 56 | /* Zero Crossing Detector */ | ||
| 57 | typedef struct _tZeroCrossing { | ||
| 58 | int count; | ||
| 59 | int maxWindowSize; | ||
| 60 | int currentWindowSize; | ||
| 61 | float invCurrentWindowSize; | ||
| 62 | float* inBuffer; | ||
| 63 | uint16_t* countBuffer; | ||
| 64 | int prevPosition; | ||
| 65 | int position; | ||
| 66 | } _tZeroCrossing; | ||
| 67 | |||
| 68 | typedef _tZeroCrossing* tZeroCrossing; | ||
| 69 | |||
| 70 | void tZeroCrossing_init (tZeroCrossing* const, int maxWindowSize); | ||
| 71 | void tZeroCrossing_free (tZeroCrossing* const); | ||
| 72 | void tZeroCrossing_initToPool (tZeroCrossing* const, int maxWindowSize, tMempool* const); | ||
| 73 | void tZeroCrossing_freeFromPool (tZeroCrossing* const, tMempool* const); | ||
| 74 | |||
| 75 | float tZeroCrossing_tick (tZeroCrossing* const, float input); | ||
| 76 | void tZeroCrossing_setWindow (tZeroCrossing* const, float windowSize); | ||
| 77 | |||
| 54 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | 78 | // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ |
| 55 | 79 | ||
| 56 | /* PowerEnvelopeFollower */ | 80 | /* PowerEnvelopeFollower */ |
| @@ -86,6 +86,99 @@ int tEnvelopeFollower_attackThresh(tEnvelopeFollower* const ef, float attack · 85 unmodified lines | |||
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | 88 | ||
| 89 | |||
| 90 | |||
| 91 | |||
| 92 | // zero crossing detector | ||
| 93 | |||
| 94 | void tZeroCrossing_init (tZeroCrossing* const zc, int maxWindowSize) | ||
| 95 | { | ||
| 96 | tZeroCrossing_initToPool (zc, maxWindowSize, &leaf.mempool); | ||
| 97 | } | ||
| 98 | void tZeroCrossing_free (tZeroCrossing* const zc) | ||
| 99 | { | ||
| 100 | tZeroCrossing_freeFromPool (zc, &leaf.mempool); | ||
| 101 | } | ||
| 102 | void tZeroCrossing_initToPool (tZeroCrossing* const zc, int maxWindowSize, tMempool* const mp) | ||
| 103 | { | ||
| 104 | _tMempool* m = *mp; | ||
| 105 | _tZeroCrossing* z = *zc = (_tZeroCrossing*) mpool_alloc(sizeof(_tZeroCrossing), m); | ||
| 106 | |||
| 107 | z->count = 0; | ||
| 108 | z->maxWindowSize = maxWindowSize; | ||
| 109 | z->currentWindowSize = maxWindowSize; | ||
| 110 | z->invCurrentWindowSize = 1.0f / maxWindowSize; | ||
| 111 | z->position = 0; | ||
| 112 | z->prevPosition = maxWindowSize; | ||
| 113 | z->inBuffer = (float*) mpool_calloc(sizeof(float) * maxWindowSize, m); | ||
| 114 | z->countBuffer = (uint16_t*) mpool_calloc(sizeof(uint16_t) * maxWindowSize, m); | ||
| 115 | } | ||
| 116 | void tZeroCrossing_freeFromPool (tZeroCrossing* const zc, tMempool* const mp) | ||
| 117 | { | ||
| 118 | _tMempool* m = *mp; | ||
| 119 | _tZeroCrossing* z = *zc; | ||
| 120 | |||
| 121 | mpool_free(z, m); | ||
| 122 | } | ||
| 123 | |||
| 124 | //returns proportion of zero crossings within window size (0.0 would be none in window, 1.0 would be all zero crossings) | ||
| 125 | float tZeroCrossing_tick (tZeroCrossing* const zc, float input) | ||
| 126 | { | ||
| 127 | _tZeroCrossing* z = *zc; | ||
| 128 | |||
| 129 | z->inBuffer[z->position] = input; | ||
| 130 | int futurePosition = ((z->position + 1) % z->currentWindowSize); | ||
| 131 | float output = 0.0f; | ||
| 132 | |||
| 133 | //add new value to count | ||
| 134 | if ((z->inBuffer[z->position] * z->inBuffer[z->prevPosition]) < 0.0f) | ||
| 135 | { | ||
| 136 | //zero crossing happened, add it to the count array | ||
| 137 | z->countBuffer[z->position] = 1; | ||
| 138 | z->count++; | ||
| 139 | } | ||
| 140 | else | ||
| 141 | { | ||
| 142 | z->countBuffer[z->position] = 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | //remove oldest value from count | ||
| 146 | if (z->countBuffer[futurePosition] > 0) | ||
| 147 | { | ||
| 148 | z->count--; | ||
| 149 | if (z->count < 0) | ||
| 150 | { | ||
| 151 | z->count = 0; | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | z->prevPosition = z->position; | ||
| 156 | z->position = futurePosition; | ||
| 157 | |||
| 158 | output = z->count * z->invCurrentWindowSize; | ||
| 159 | |||
| 160 | return output; | ||
| 161 | } | ||
| 162 | |||
| 163 | |||
| 164 | void tZeroCrossing_setWindow (tZeroCrossing* const zc, float windowSize) | ||
| 165 | { | ||
| 166 | _tZeroCrossing* z = *zc; | ||
| 167 | if (windowSize <= z->maxWindowSize) | ||
| 168 | { | ||
| 169 | z->currentWindowSize = windowSize; | ||
| 170 | } | ||
| 171 | else | ||
| 172 | { | ||
| 173 | z->currentWindowSize = z->maxWindowSize; | ||
| 174 | } | ||
| 175 | z->invCurrentWindowSize = 1.0f / z->currentWindowSize; | ||
| 176 | } | ||
| 177 | |||
| 178 | |||
| 179 | |||
| 180 | |||
| 181 | |||
| 89 | //=========================================================================== | 182 | //=========================================================================== |
| 90 | /* Power Follower */ | 183 | /* Power Follower */ |
| 91 | //=========================================================================== | 184 | //=========================================================================== |
| @@ -843,90 +843,79 @@ void tBiQuadSampleRateChanged(tBiQuad* const ft) · 842 unmodified lines | |||
| 843 | // is calculated when frequency changes. | 843 | // is calculated when frequency changes. |
| 844 | void tSVF_init(tSVF* const svff, SVFType type, float freq, float Q) | 844 | void tSVF_init(tSVF* const svff, SVFType type, float freq, float Q) |
| 845 | { | 845 | { |
| 846 | _tSVF* svf = *svff = (_tSVF*) leaf_alloc(sizeof(_tSVF)); | 846 | tSVF_initToPool (svff, type, freq, Q, &leaf.mempool); |
| 847 | 847 | ||
| 848 | // or maybe this? | ||
| 849 | /* | ||
| 850 | * hp=1 bp=A/Q (where A is 10^(G/40) and G is gain in decibels) and lp = 1 | ||
| 851 | */ | ||
| 852 | |||
| 853 | } | ||
| 854 | |||
| 855 | void tSVF_free(tSVF* const svff) | ||
| 856 | { | ||
| 857 | tSVF_freeFromPool (svff, &leaf.mempool); | ||
| 858 | } | ||
| 859 | |||
| 860 | void tSVF_initToPool (tSVF* const svff, SVFType type, float freq, float Q, tMempool* const mp) | ||
| 861 | { | ||
| 862 | _tMempool* m = *mp; | ||
| 863 | _tSVF* svf = *svff = (_tSVF*) mpool_alloc(sizeof(_tSVF), m); | ||
| 864 | |||
| 848 | svf->type = type; | 865 | svf->type = type; |
| 849 | 866 | ||
| 850 | svf->ic1eq = 0; | 867 | svf->ic1eq = 0; |
| 851 | svf->ic2eq = 0; | 868 | svf->ic2eq = 0; |
| 852 | 869 | svf->Q = Q; | |
| 870 | svf->cutoff = freq; | ||
| 853 | svf->g = tanf(PI * freq * leaf.invSampleRate); | 871 | svf->g = tanf(PI * freq * leaf.invSampleRate); |
| 854 | svf->k = 1.0f/Q; | 872 | svf->k = 1.0f/Q; |
| 855 | svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k)); | 873 | svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k)); |
| 856 | svf->a2 = svf->g*svf->a1; | 874 | svf->a2 = svf->g*svf->a1; |
| 857 | svf->a3 = svf->g*svf->a2; | 875 | svf->a3 = svf->g*svf->a2; |
| 876 | svf->cH = 0.0f; | ||
| 877 | svf->cB = 0.0f; | ||
| 878 | svf->cL = 1.0f; | ||
| 858 | 879 | ||
| 859 | if (type == SVFTypeLowpass) | 880 | if (type == SVFTypeLowpass) |
| 860 | { | 881 | { |
| 861 | svf->cH = 0.0f; | 882 | svf->cH = 0.0f; |
| 862 | svf->cB = 0.0f; | 883 | svf->cB = 0.0f; |
| 863 | svf->kAmount = 0.0f; | 884 | svf->cBK = 0.0f; |
| 864 | svf->cL = 1.0f; | 885 | svf->cL = 1.0f; |
| 865 | } | 886 | } |
| 866 | else if (type == SVFTypeBandpass) | 887 | else if (type == SVFTypeBandpass) |
| 867 | { | 888 | { |
| 868 | svf->cH = 0.0f; | 889 | svf->cH = 0.0f; |
| 869 | svf->cB = 1.0f; | 890 | svf->cB = 1.0f; |
| 870 | svf->kAmount = 0.0f; | 891 | svf->cBK = 0.0f; |
| 871 | svf->cL = 0.0f; | 892 | svf->cL = 0.0f; |
| 872 | } | 893 | } |
| 873 | 894 | ||
| 874 | else if (type == SVFTypeHighpass) | 895 | else if (type == SVFTypeHighpass) |
| 875 | { | 896 | { |
| 876 | svf->cH = 1.0f; | 897 | svf->cH = 1.0f; |
| 877 | svf->cB = svf->k * -1.0f; | 898 | svf->cB = 0.0f; |
| 878 | svf->kAmount = 1.0f; | 899 | svf->cBK = -1.0f; |
| 879 | svf->cL = -1.0f; | 900 | svf->cL = -1.0f; |
| 880 | } | 901 | } |
| 881 | 902 | ||
| 882 | else if (type == SVFTypeNotch) | 903 | else if (type == SVFTypeNotch) |
| 883 | { | 904 | { |
| 884 | svf->cH = 1.0f; | 905 | svf->cH = 1.0f; |
| 885 | svf->cB = svf->k * -1.0f; | 906 | svf->cB = 0.0f; |
| 886 | svf->kAmount = 1.0f; | 907 | svf->cBK = -1.0f; |
| 887 | svf->cL = 0.0f; | 908 | svf->cL = 0.0f; |
| 888 | } | 909 | } |
| 889 | 910 | ||
| 890 | 911 | ||
| 891 | else if (type == SVFTypePeak) | 912 | else if (type == SVFTypePeak) |
| 892 | { | 913 | { |
| 893 | svf->cH = 1.0f; | 914 | svf->cH = 1.0f; |
| 894 | svf->cB = svf->k * -1.0f; | 915 | svf->cB = 0.0f; |
| 895 | svf->kAmount = 1.0f; | 916 | svf->cBK = -1.0f; |
| 896 | svf->cL = -2.0f; | 917 | svf->cL = -2.0f; |
| 897 | } | 918 | } |
| 898 | // or maybe this? | ||
| 899 | /* | ||
| 900 | * hp=1 bp=A/Q (where A is 10^(G/40) and G is gain in decibels) and lp = 1 | ||
| 901 | */ | ||
| 902 | |||
| 903 | } | ||
| 904 | |||
| 905 | void tSVF_free(tSVF* const svff) | ||
| 906 | { | ||
| 907 | _tSVF* svf = *svff; | ||
| 908 | |||
| 909 | leaf_free(svf); | ||
| 910 | } | ||
| 911 | |||
| 912 | void tSVF_initToPool (tSVF* const svff, SVFType type, float freq, float Q, tMempool* const mp) | ||
| 913 | { | ||
| 914 | _tMempool* m = *mp; | ||
| 915 | _tSVF* svf = *svff = (_tSVF*) mpool_alloc(sizeof(_tSVF), m); | ||
| 916 | |||
| 917 | svf->type = type; | ||
| 918 | |||
| 919 | svf->ic1eq = 0; | ||
| 920 | svf->ic2eq = 0; | ||
| 921 | |||
| 922 | svf->g = tanf(PI * freq * leaf.invSampleRate); | ||
| 923 | svf->k = 1.0f/Q; | ||
| 924 | svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k)); | ||
| 925 | svf->a2 = svf->g*svf->a1; | ||
| 926 | svf->a3 = svf->g*svf->a2; | ||
| 927 | svf->cH = 0.0f; | ||
| 928 | svf->cB = 0.0f; | ||
| 929 | svf->cL = 1.0f; | ||
| 930 | } | 919 | } |
| 931 | 920 | ||
| 932 | void tSVF_freeFromPool (tSVF* const svff, tMempool* const mp) | 921 | void tSVF_freeFromPool (tSVF* const svff, tMempool* const mp) |
| @@ -948,13 +937,13 @@ float tSVF_tick(tSVF* const svff, float v0) · 15 unmodified lines | |||
| 948 | svf->ic1eq = (2.0f * v1) - svf->ic1eq; | 937 | svf->ic1eq = (2.0f * v1) - svf->ic1eq; |
| 949 | svf->ic2eq = (2.0f * v2) - svf->ic2eq; | 938 | svf->ic2eq = (2.0f * v2) - svf->ic2eq; |
| 950 | 939 | ||
| 951 | return (v0 * svf->cH) + (svf->kAmount * svf->k * v1 * svf->cB) + (v2 * svf->cL); | 940 | return (v0 * svf->cH) + (v1 * svf->cB) + (svf->k * v1 * svf->cBK) + (v2 * svf->cL); |
| 952 | } | 941 | } |
| 953 | 942 | ||
| 954 | void tSVF_setFreq(tSVF* const svff, float freq) | 943 | void tSVF_setFreq(tSVF* const svff, float freq) |
| 955 | { | 944 | { |
| 956 | _tSVF* svf = *svff; | 945 | _tSVF* svf = *svff; |
| 957 | 946 | svf->cutoff = freq; | |
| 958 | svf->g = tanf(PI * freq * leaf.invSampleRate); | 947 | svf->g = tanf(PI * freq * leaf.invSampleRate); |
| 959 | svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k)); | 948 | svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k)); |
| 960 | svf->a2 = svf->g * svf->a1; | 949 | svf->a2 = svf->g * svf->a1; |
| @@ -964,7 +953,7 @@ void tSVF_setFreq(tSVF* const svff, float freq) · 3 unmodified lines | |||
| 964 | void tSVF_setQ(tSVF* const svff, float Q) | 953 | void tSVF_setQ(tSVF* const svff, float Q) |
| 965 | { | 954 | { |
| 966 | _tSVF* svf = *svff; | 955 | _tSVF* svf = *svff; |
| 967 | 956 | svf->Q = Q; | |
| 968 | svf->k = 1.0f/Q; | 957 | svf->k = 1.0f/Q; |
| 969 | 958 | ||
| 970 | svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k)); | 959 | svf->a1 = 1.0f/(1.0f + svf->g * (svf->g + svf->k)); |
| @@ -972,7 +961,7 @@ void tSVF_setQ(tSVF* const svff, float Q) · 1 unmodified line | |||
| 972 | svf->a3 = svf->g * svf->a2; | 961 | svf->a3 = svf->g * svf->a2; |
| 973 | } | 962 | } |
| 974 | 963 | ||
| 975 | void tSVF_setFreqAndQ(tSVF* const svff, float freq, float Q) | 964 | void tSVF_setFreqAndQ(tSVF* const svff, float freq, float Q) |
| 976 | { | 965 | { |
| 977 | _tSVF* svf = *svff; | 966 | _tSVF* svf = *svff; |
| 978 | svf->k = 1.0f/Q; | 967 | svf->k = 1.0f/Q; |