Bela
Real-time, ultra-low-latency audio and sensor processing system for BeagleBone Black
Loading...
Searching...
No Matches
calculateCentroids.h
1// returns a WORD packing two signed chars. The high bytes is the last active sensor in the last centroid,
2// while the low byte is the first active sensor of the last centroid
3WORD calculateCentroids(WORD *centroidBuffer, WORD *sizeBuffer, BYTE maxNumCentroids, BYTE minSensor, BYTE maxSensor, BYTE numSensors) {
4 signed char lastActiveSensor = -1;
5 BYTE centroidIndex = 0, sensorIndex, actualHardwareIndex;
6 BYTE wrappedAround = 0;
7 BYTE inCentroid = 0;
8 WORD peakValue = 0, troughDepth = 0;
9 BYTE counter;
10 long temp;
11
12 WORD lastSensorVal, currentSensorVal, currentWeightedSum, currentUnweightedSum;
13 BYTE currentStart, currentLength;
14
15 for(sensorIndex = 0; sensorIndex < maxNumCentroids; sensorIndex++) {
16 centroidBuffer[sensorIndex] = 0xFFFF;
17 sizeBuffer[sensorIndex] = 0;
18 }
19
20 currentSensorVal = 0;
21
22 for(sensorIndex = 0, actualHardwareIndex = minSensor; sensorIndex < numSensors; sensorIndex++)
23 {
24 lastSensorVal = currentSensorVal;
25
26 currentSensorVal = CSD_waSnsDiff[actualHardwareIndex++];
27 if(currentSensorVal > 0) {
28 lastActiveSensor = sensorIndex;
29 }
30 // if we get to the end, and there is more to go, wrap around
31 if(actualHardwareIndex == maxSensor)
32 {
33 actualHardwareIndex = minSensor;
34 // once we wrap around, if we find ourselves out of a centroid,
35 // any centroids detected after the then current point onwards
36 // would be equal or worse than the ones we already got earlier for
37 // the same sensors, so we will have to break
38 wrappedAround = 1;
39 }
40
41 if(inCentroid) {
42 // Currently in the middle of a group of sensors constituting a centroid. Use a zero sample
43 // or a spike above a certain magnitude to indicate the end of the centroid.
44
45 if(currentSensorVal == 0) {
46 if(currentUnweightedSum > wMinimumCentroidSize)
47 {
48 temp = ((long)currentWeightedSum << SLIDER_BITS) / currentUnweightedSum;
49 centroidBuffer[centroidIndex] = (currentStart << SLIDER_BITS) + (WORD)temp;
50 sizeBuffer[centroidIndex] = currentUnweightedSum;
51 centroidIndex++;
52 }
53
54 inCentroid = 0;
55 if(wrappedAround) {
56 break;
57 }
58 if(centroidIndex >= maxNumCentroids)
59 break;
60 continue;
61 }
62
63 if(currentSensorVal > peakValue) // Keep tabs on max and min values
64 peakValue = currentSensorVal;
65 if(peakValue - currentSensorVal > troughDepth)
66 troughDepth = peakValue - currentSensorVal;
67
68 // If this sensor value is a significant increase over the last one, AND the last one was decreasing, then start a new centroid.
69 // In other words, identify a trough in the values and use it to segment into two centroids.
70
71 if(sensorIndex >= 2) {
72 if(troughDepth > wAdjacentCentroidNoiseThreshold && currentSensorVal > lastSensorVal + wAdjacentCentroidNoiseThreshold) {
73 if(currentUnweightedSum > wMinimumCentroidSize)
74 {
75 temp = ((long)currentWeightedSum << SLIDER_BITS) / currentUnweightedSum;
76 centroidBuffer[centroidIndex] = (currentStart << SLIDER_BITS) + (WORD)temp;
77 sizeBuffer[centroidIndex] = currentUnweightedSum;
78 centroidIndex++;
79 }
80 inCentroid = 0;
81 if(wrappedAround){
82 break;
83 }
84 if(centroidIndex >= maxNumCentroids)
85 break;
86 inCentroid = 1;
87 currentStart = sensorIndex;
88 currentUnweightedSum = peakValue = currentSensorVal;
89 currentLength = 1;
90 currentWeightedSum = 0;
91 troughDepth = 0;
92 continue;
93 }
94 }
95
96 currentUnweightedSum += currentSensorVal;
97 currentWeightedSum += currentLength * currentSensorVal;
98 currentLength++;
99 }
100 else {
101 // Currently not in a centroid (zeros between centroids). Look for a new sample to initiate centroid.
102 if(currentSensorVal > 0) {
103 currentStart = sensorIndex;
104 currentUnweightedSum = peakValue = currentSensorVal;
105 currentLength = 1;
106 currentWeightedSum = 0;
107 troughDepth = 0;
108 inCentroid = 1;
109 }
110 }
111 if(!inCentroid && wrappedAround){
112 break;
113 }
114 }
115
116 // Finish up the calculation on the last centroid, if necessary
117 if(inCentroid && currentUnweightedSum > wMinimumCentroidSize)
118 {
119 temp = ((long)currentWeightedSum << SLIDER_BITS) / currentUnweightedSum;
120 centroidBuffer[centroidIndex] = (currentStart << SLIDER_BITS) + (WORD)temp;
121 sizeBuffer[centroidIndex] = currentUnweightedSum;
122 centroidIndex++;
123 }
124
125 return (lastActiveSensor << 8) | currentStart;
126}