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
639 639
640 //==============================================================================640 //==============================================================================
641 641
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
642#ifdef __cplusplus760#ifdef __cplusplus
643}761}
644#endif762#endif
leaf/Inc/leaf-math.h+1−0
@@ -17,6 +17,7 @@ extern "C" { · 16 unmodified lines
17#include "math.h"17#include "math.h"
18#include "stdint.h"18#include "stdint.h"
19#include "stdlib.h"19#include "stdlib.h"
20#include "limits.h"
20 21
21 //==============================================================================22 //==============================================================================
22 23
leaf/Src/leaf-analysis.c+258−0
@@ -950,3 +950,261 @@ void tPeriodDetection_setTolerance (tPeriodDetection* pd, float tolerance · 949 unmodified lines
950 if (tolerance < 0.0f) p->tolerance = 0.0f;950 if (tolerance < 0.0f) p->tolerance = 0.0f;
951 else p->tolerance = tolerance;951 else p->tolerance = tolerance;
952}952}
953
954
955void tZeroCrossing2_init (tZeroCrossing2* const zc)
956{
957 tZeroCrossing2_initToPool(zc, &leaf.mempool);
958}
959
960void 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
971void tZeroCrossing2_free (tZeroCrossing2* const zc)
972{
973 _tZeroCrossing2* z = *zc;
974
975 mpool_free((char*)z, z->mempool);
976}
977
978void 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
987int 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
995float 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
1017int tZeroCrossing2_getWidth(tZeroCrossing2* const zc)
1018{
1019 _tZeroCrossing2* z = *zc;
1020
1021 return z->_width;
1022}
1023
1024int 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
1037static void update_state(tZeroCrossings* const zc, float s);
1038static void shift(tZeroCrossings* const zc, int n);
1039static void reset(tZeroCrossings* const zc);
1040
1041void tZeroCrossings_init (tZeroCrossings* const zc, int windowSize, float hysteresis)
1042{
1043 tZeroCrossings_initToPool(zc, windowSize, hysteresis, &leaf.mempool);
1044}
1045
1046void 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
1062void tZeroCrossings_free (tZeroCrossings* const zc)
1063{
1064 _tZeroCrossings* z = *zc;
1065
1066 mpool_free((char*)z, z->mempool);
1067}
1068
1069int tZeroCrossings_tick(tZeroCrossings* const zc, float s)
1070{
1071 _tZeroCrossings* z = *zc;
1072
1073 return z->_state;
1074}
1075
1076int tZeroCrossings_getState(tZeroCrossings* const zc)
1077{
1078 _tZeroCrossings* z = *zc;
1079
1080 return z->_state;
1081}
1082
1083int tZeroCrossings_getNumEdges(tZeroCrossings* const zc)
1084{
1085 _tZeroCrossings* z = *zc;
1086
1087 return z->_num_edges;
1088}
1089
1090int tZeroCrossings_getCapacity(tZeroCrossings* const zc)
1091{
1092 _tZeroCrossings* z = *zc;
1093
1094 return z->_window_size / 2;
1095}
1096
1097int tZeroCrossings_getFrame(tZeroCrossings* const zc)
1098{
1099 _tZeroCrossings* z = *zc;
1100
1101 return z->_frame;
1102}
1103
1104int tZeroCrossings_getWindowSize(tZeroCrossings* const zc)
1105{
1106 _tZeroCrossings* z = *zc;
1107
1108 return z->_window_size;
1109}
1110
1111int tZeroCrossings_isReady(tZeroCrossings* const zc)
1112{
1113 _tZeroCrossings* z = *zc;
1114
1115 return z->_ready;
1116}
1117
1118float tZeroCrossings_getPeak(tZeroCrossings* const zc)
1119{
1120 _tZeroCrossings* z = *zc;
1121
1122 return fmax(z->_peak, z->_peak_update);
1123}
1124
1125int tZeroCrossings_isReset(tZeroCrossings* const zc)
1126{
1127 _tZeroCrossings* z = *zc;
1128
1129 return z->_frame == 0;
1130}
1131
1132static 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
1182static 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
1203static 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