Bela
Real-time, ultra-low-latency audio and sensor processing system for BeagleBone Black
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
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
3 WORD 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 }