History

wip on bitstream auto correlation

Matthew Wang committed 6 years ago

Commit f504bc41 parent 654405d3 files · +377 −0Browse files

Unified · Split

3 files
  1. leaf/Inc/leaf-analysis.h +118 −0
  2. leaf/Inc/leaf-math.h +1 −0
  3. leaf/Src/leaf-analysis.c +258 −0
leaf/Inc/leaf-analysis.h+118−0
@@ -639,6 +639,124 @@ extern "C" { · 638 unmodified lines
639639
640640 //==============================================================================
641641
642+ typedef struct _tZeroCrossing2
643+ {
644+ tMempool mempool;
645+
646+ float _before_crossing;
647+ float _after_crossing;
648+
649+ float _peak;
650+ int _leading_edge;// = undefined_edge; int_min
651+ int _trailing_edge;// = undefined_edge;
652+ float _width;// = 0.0f;
653+ } _tZeroCrossing2;
654+
655+ typedef _tZeroCrossing2* tZeroCrossing2;
656+
657+ void tZeroCrossing2_init (tZeroCrossing2* const);
658+ void tZeroCrossing2_initToPool (tZeroCrossing2* const, tMempool* const);
659+ void tZeroCrossing2_free (tZeroCrossing2* const);
660+
661+ int tZeroCrossing2_tick(tZeroCrossing2* const, float s);
662+ int tZeroCrossing2_getState(tZeroCrossing2* const);
663+ void tZeroCrossing2_updatePeak(tZeroCrossing2* const, float s, int pos);
664+ int tZeroCrossing2_period(tZeroCrossing2* const, tZeroCrossing2* const next);
665+ float tZeroCrossing2_fractionalPeriod(tZeroCrossing2* const, tZeroCrossing2* const next);
666+ int tZeroCrossing2_getWidth(tZeroCrossing2* const);
667+ int tZeroCrossing2_isSimilar(tZeroCrossing2* const, tZeroCrossing2* const next);
668+
669+ //==============================================================================
670+
671+#define PULSE_HEIGHT_DIFF 0.8
672+#define PULSE_WIDTH_DIFF 0.85
673+
674+ typedef struct _tZeroCrossings
675+ {
676+ tMempool mempool;
677+
678+ _tZeroCrossing2* _info;
679+
680+ int index;
681+
682+ float _prev;// = 0.0f;
683+ float _hysteresis;
684+ bool _state;// = false;
685+ int _num_edges;// = 0;
686+ int _window_size;
687+ int _frame;// = 0;
688+ bool _ready;// = false;
689+ float _peak_update;// = 0.0f;
690+ float _peak;// = 0.0f;
691+ } _tZeroCrossings;
692+
693+ typedef _tZeroCrossings* tZeroCrossings;
694+
695+ void tZeroCrossings_init (tZeroCrossings* const, int windowSize, float hysteresis);
696+ void tZeroCrossings_initToPool (tZeroCrossings* const, int windowSize, float hysteresis, tMempool* const);
697+ void tZeroCrossings_free (tZeroCrossings* const);
698+
699+ int tZeroCrossings_tick(tZeroCrossings* const, float s);
700+ int tZeroCrossings_getState(tZeroCrossings* const);
701+
702+ int tZeroCrossings_getNumEdges(tZeroCrossings* const zc);
703+ int tZeroCrossings_getCapacity(tZeroCrossings* const zc);
704+ int tZeroCrossings_getFrame(tZeroCrossings* const zc);
705+ int tZeroCrossings_getWindowSize(tZeroCrossings* const zc);
706+
707+ int tZeroCrossings_isReady(tZeroCrossings* const zc);
708+ float tZeroCrossings_getPeak(tZeroCrossings* const zc);
709+ int tZeroCrossings_isReset(tZeroCrossings* const zc);
710+
711+ tZeroCrossing2* const tZeroCrossings_getCrossing(int index);
712+
713+ //==============================================================================
714+
715+ typedef struct _tBitset
716+ {
717+ tMempool mempool;
718+
719+ unsigned int* _bits;
720+ } _tBitset;
721+
722+ typedef _tBitset* tBitset;
723+
724+ void tBitset_init (tBitset* const bitset, int numBits);
725+ void tBitset_initToPool (tBitset* const bitset, int numBits, tMempool* const mempool);
726+ void tBitset_free (tBitset* const bitset);
727+
728+ int tBitset_getSize (tBitset* const bitset);
729+// bitset& operator=(bitset const& rhs) = default;
730+// bitset& operator=(bitset&& rhs) = default;
731+//
732+// std::size_t size() const;
733+// void clear();
734+// void set(std::size_t i, bool val);
735+// void set(std::size_t i, std::size_t n, bool val);
736+// bool get(std::size_t i) const;
737+//
738+// T* data();
739+// T const* data() const;
740+
741+ //==============================================================================
742+
743+ typedef struct _tBACF
744+ {
745+ tMempool mempool;
746+
747+ int windowSize;
748+
749+
750+ } _tBACF;
751+
752+ typedef _tBACF* tBACF;
753+
754+ void tBACF_init (tBACF* const, int windowSize);
755+ void tBACF_initToPool (tBACF* const, int windowSize, tMempool* const);
756+ void tBACF_free (tBACF* const);
757+
758+
759+
642760 #ifdef __cplusplus
643761 }
644762 #endif
leaf/Inc/leaf-math.h+1−0
@@ -17,6 +17,7 @@ extern "C" { · 16 unmodified lines
1717 #include "math.h"
1818 #include "stdint.h"
1919 #include "stdlib.h"
20+#include "limits.h"
2021
2122 //==============================================================================
2223
leaf/Src/leaf-analysis.c+258−0
@@ -950,3 +950,261 @@ void tPeriodDetection_setTolerance (tPeriodDetection* pd, float tolerance · 949 unmodified lines
950950 if (tolerance < 0.0f) p->tolerance = 0.0f;
951951 else p->tolerance = tolerance;
952952 }
953+
954+
955+void tZeroCrossing2_init (tZeroCrossing2* const zc)
956+{
957+ tZeroCrossing2_initToPool(zc, &leaf.mempool);
958+}
959+
960+void tZeroCrossing2_initToPool (tZeroCrossing2* const zc, tMempool* const mp)
961+{
962+ _tMempool* m = *mp;
963+ _tZeroCrossing2* z = *zc = (_tZeroCrossing2*) mpool_alloc(sizeof(_tZeroCrossing2), m);
964+ z->mempool = m;
965+
966+ z->_leading_edge = INT_MIN;
967+ z->_trailing_edge = INT_MIN;
968+ z->_width = 0.0f;
969+}
970+
971+void tZeroCrossing2_free (tZeroCrossing2* const zc)
972+{
973+ _tZeroCrossing2* z = *zc;
974+
975+ mpool_free((char*)z, z->mempool);
976+}
977+
978+void tZeroCrossing2_updatePeak(tZeroCrossing2* const zc, float s, int pos)
979+{
980+ _tZeroCrossing2* z = *zc;
981+
982+ z->_peak = fmax(s, z->_peak);
983+ if ((z->_width == 0.0f) && (s < (z->_peak * 0.3f)))
984+ z->_width = pos - z->_leading_edge;
985+}
986+
987+int tZeroCrossing2_period(tZeroCrossing2* const zc, tZeroCrossing2* const next)
988+{
989+ _tZeroCrossing2* z = *zc;
990+ _tZeroCrossing2* n = *next;
991+
992+ return n->_leading_edge - z->_leading_edge;
993+}
994+
995+float tZeroCrossing2_fractionalPeriod(tZeroCrossing2* const zc, tZeroCrossing2* const next)
996+{
997+ _tZeroCrossing2* z = *zc;
998+ _tZeroCrossing2* n = *next;
999+
1000+ // Get the start edge
1001+ float prev1 = z->_before_crossing;
1002+ float curr1 = z->_after_crossing;
1003+ float dy1 = curr1 - prev1;
1004+ float dx1 = -prev1 / dy1;
1005+
1006+ // Get the next edge
1007+ float prev2 = n->_before_crossing;
1008+ float curr2 = n->_after_crossing;
1009+ float dy2 = curr2 - prev2;
1010+ float dx2 = -prev2 / dy2;
1011+
1012+ // Calculate the fractional period
1013+ float result = n->_leading_edge - z->_leading_edge;
1014+ return result + (dx2 - dx1);
1015+}
1016+
1017+int tZeroCrossing2_getWidth(tZeroCrossing2* const zc)
1018+{
1019+ _tZeroCrossing2* z = *zc;
1020+
1021+ return z->_width;
1022+}
1023+
1024+int tZeroCrossing2_isSimilar(tZeroCrossing2* const zc, tZeroCrossing2* const next)
1025+{
1026+ _tZeroCrossing2* z = *zc;
1027+ _tZeroCrossing2* n = *next;
1028+
1029+ int similarPeak = fabs(z->_peak - n->_peak) <= ((1.0f - PULSE_HEIGHT_DIFF) * fmax(fabs(z->_peak), fabs(n->_peak)));
1030+
1031+ int similarWidth = fabs(z->_width - n->_width) <= ((1.0f - PULSE_WIDTH_DIFF) * fmax(fabs(z->_width), fabs(n->_width)));
1032+
1033+ return similarPeak && similarWidth;
1034+}
1035+
1036+
1037+static void update_state(tZeroCrossings* const zc, float s);
1038+static void shift(tZeroCrossings* const zc, int n);
1039+static void reset(tZeroCrossings* const zc);
1040+
1041+void tZeroCrossings_init (tZeroCrossings* const zc, int windowSize, float hysteresis)
1042+{
1043+ tZeroCrossings_initToPool(zc, windowSize, hysteresis, &leaf.mempool);
1044+}
1045+
1046+void tZeroCrossings_initToPool (tZeroCrossings* const zc, int windowSize, float hysteresis, tMempool* const mp)
1047+{
1048+ _tMempool* m = *mp;
1049+ _tZeroCrossings* z = *zc = (_tZeroCrossings*) mpool_alloc(sizeof(_tZeroCrossings), m);
1050+ z->mempool = m;
1051+
1052+ z->_hysteresis = hysteresis;
1053+ int bits = CHAR_BIT * sizeof(unsigned int);
1054+ z->_window_size = fmax(2, (windowSize + bits - 1) / bits) * bits;
1055+
1056+ // The current ring buffer and indexing implementation for this is less efficient than the original source
1057+ // May be worth porting over the ring buffer class from https://github.com/cycfi/q/tree/develop
1058+ z->_info = (_tZeroCrossing2*) mpool_alloc(sizeof(_tZeroCrossing2) * (z->_window_size / 2), m);
1059+ z->index = -1;
1060+}
1061+
1062+void tZeroCrossings_free (tZeroCrossings* const zc)
1063+{
1064+ _tZeroCrossings* z = *zc;
1065+
1066+ mpool_free((char*)z, z->mempool);
1067+}
1068+
1069+int tZeroCrossings_tick(tZeroCrossings* const zc, float s)
1070+{
1071+ _tZeroCrossings* z = *zc;
1072+
1073+ return z->_state;
1074+}
1075+
1076+int tZeroCrossings_getState(tZeroCrossings* const zc)
1077+{
1078+ _tZeroCrossings* z = *zc;
1079+
1080+ return z->_state;
1081+}
1082+
1083+int tZeroCrossings_getNumEdges(tZeroCrossings* const zc)
1084+{
1085+ _tZeroCrossings* z = *zc;
1086+
1087+ return z->_num_edges;
1088+}
1089+
1090+int tZeroCrossings_getCapacity(tZeroCrossings* const zc)
1091+{
1092+ _tZeroCrossings* z = *zc;
1093+
1094+ return z->_window_size / 2;
1095+}
1096+
1097+int tZeroCrossings_getFrame(tZeroCrossings* const zc)
1098+{
1099+ _tZeroCrossings* z = *zc;
1100+
1101+ return z->_frame;
1102+}
1103+
1104+int tZeroCrossings_getWindowSize(tZeroCrossings* const zc)
1105+{
1106+ _tZeroCrossings* z = *zc;
1107+
1108+ return z->_window_size;
1109+}
1110+
1111+int tZeroCrossings_isReady(tZeroCrossings* const zc)
1112+{
1113+ _tZeroCrossings* z = *zc;
1114+
1115+ return z->_ready;
1116+}
1117+
1118+float tZeroCrossings_getPeak(tZeroCrossings* const zc)
1119+{
1120+ _tZeroCrossings* z = *zc;
1121+
1122+ return fmax(z->_peak, z->_peak_update);
1123+}
1124+
1125+int tZeroCrossings_isReset(tZeroCrossings* const zc)
1126+{
1127+ _tZeroCrossings* z = *zc;
1128+
1129+ return z->_frame == 0;
1130+}
1131+
1132+static void update_state(tZeroCrossings* const zc, float s)
1133+{
1134+ _tZeroCrossings* z = *zc;
1135+
1136+ int capacity = z->_window_size / 2;
1137+ if (z->_ready)
1138+ {
1139+ shift(zc, capacity);
1140+ z->_ready = 0;
1141+ z->_peak = z->_peak_update;
1142+ z->_peak_update = 0.0f;
1143+ }
1144+
1145+ if (z->_num_edges >= capacity)
1146+ reset(zc);
1147+
1148+ if (s > 0.0f)
1149+ {
1150+ if (!z->_state)
1151+ {
1152+ ++z->index;
1153+ _tZeroCrossing2 crossing = z->_info[z->index];
1154+ crossing._before_crossing = z->_prev;
1155+ crossing._after_crossing = s;
1156+ crossing._peak = s;
1157+ crossing._leading_edge = (int) z->_frame;
1158+ ++z->_num_edges;
1159+ z->_state = 1;
1160+ }
1161+ else
1162+ {
1163+ tZeroCrossing2 ptr = &z->_info[z->index];
1164+ tZeroCrossing2_updatePeak(&ptr, s, z->_frame);
1165+ }
1166+ if (s > z->_peak_update)
1167+ {
1168+ z->_peak_update = s;
1169+ }
1170+ }
1171+ else if (z->_state && (s < z->_hysteresis))
1172+ {
1173+ z->_state = 0;
1174+ z->_info[z->index]._trailing_edge = z->_frame;
1175+ if (z->_peak == 0.0f)
1176+ z->_peak = z->_peak_update;
1177+ }
1178+
1179+ z->_prev = s;
1180+}
1181+
1182+static void shift(tZeroCrossings* const zc, int n)
1183+{
1184+ _tZeroCrossings* z = *zc;
1185+
1186+ _tZeroCrossing2 crossing = z->_info[z->index];
1187+
1188+ crossing._leading_edge -= n;
1189+ if (!z->_state)
1190+ crossing._trailing_edge -= n;
1191+ int i = 1;
1192+ for (; i != z->_num_edges; ++i)
1193+ {
1194+ int idx = (z->index + i) % (z->_window_size / 2);
1195+ z->_info[idx]._leading_edge -= n;
1196+ int edge = (z->_info[idx]._trailing_edge -= n);
1197+ if (edge < 0.0f)
1198+ break;
1199+ }
1200+ z->_num_edges = i;
1201+}
1202+
1203+static void reset(tZeroCrossings* const zc)
1204+{
1205+ _tZeroCrossings* z = *zc;
1206+
1207+ z->_num_edges = 0;
1208+ z->_state = 0;
1209+ z->_frame = 0;
1210+}

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