History

fixed SVF bandpass issue, added zero crossing detector in analysis.h

spiricom committed 6 years ago

Commit af9f02f1 parent 249e21c5 files · +164 −58Browse files

Unified · Split

5 files
  1. .DS_Store +0 −0
  2. LEAF/.DS_Store +0 −0
  3. LEAF/Inc/leaf-analysis.h +24 −0
  4. LEAF/Src/leaf-analysis.c +93 −0
  5. LEAF/Src/leaf-filters.c +49 −60
.DS_Store+0−0

Binary file not shown.

LEAF/.DS_Store+0−0

Binary file not shown.

LEAF/Inc/leaf-analysis.h+24−0
@@ -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 */
LEAF/Src/leaf-analysis.c+93−0
@@ -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
94void tZeroCrossing_init (tZeroCrossing* const zc, int maxWindowSize)
95{
96 tZeroCrossing_initToPool (zc, maxWindowSize, &leaf.mempool);
97}
98void tZeroCrossing_free (tZeroCrossing* const zc)
99{
100 tZeroCrossing_freeFromPool (zc, &leaf.mempool);
101}
102void 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}
116void 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)
125float 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
164void 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//===========================================================================
LEAF/Src/leaf-filters.c+49−60
@@ -843,90 +843,79 @@ void tBiQuadSampleRateChanged(tBiQuad* const ft) · 842 unmodified lines
843// is calculated when frequency changes.843// is calculated when frequency changes.
844void tSVF_init(tSVF* const svff, SVFType type, float freq, float Q)844void 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
855void tSVF_free(tSVF* const svff)
856{
857 tSVF_freeFromPool (svff, &leaf.mempool);
858}
859
860void 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
905void tSVF_free(tSVF* const svff)
906{
907 _tSVF* svf = *svff;
908
909 leaf_free(svf);
910}
911
912void 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
932void tSVF_freeFromPool (tSVF* const svff, tMempool* const mp)921void 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
954void tSVF_setFreq(tSVF* const svff, float freq)943void 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
964void tSVF_setQ(tSVF* const svff, float Q)953void 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
975void tSVF_setFreqAndQ(tSVF* const svff, float freq, float Q)964void 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;

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