diff --git a/include/puara/descriptors/touch.h b/include/puara/descriptors/touch.h index 853b103..01ca7d3 100644 --- a/include/puara/descriptors/touch.h +++ b/include/puara/descriptors/touch.h @@ -6,11 +6,6 @@ #include #include - -#ifndef USE_BRUSH_COUNTER - #define USE_BRUSH_COUNTER 0 -#endif - namespace puara_gestures { @@ -63,9 +58,7 @@ class Touch int touchSizeEdge{4}; // amount of stripes for top and bottom portions (arbitrary) BlobDetector blobDetector; -#if USE_BRUSH_COUNTER int brushCounter[maxNumBlobs]{}; -#endif Touch() = default; @@ -76,10 +69,17 @@ class Touch { // Update the "amount of touch" for the entire touch sensor, as well as the top, middle and bottom parts. // All normalized between 0 and 1. - touchAll = touchAverage(discrete_touch, 0, touchSize); - touchTop = touchAverage(discrete_touch, 0, touchSizeEdge); - touchMiddle = touchAverage(discrete_touch, (0 + touchSizeEdge), (touchSize - touchSizeEdge)); - touchBottom = touchAverage(discrete_touch, (touchSize - touchSizeEdge), touchSize); + touchAll = utils::average::array(discrete_touch, 0, touchSize); + touchTop = utils::average::array(discrete_touch, 0, touchSizeEdge); + touchMiddle = utils::average::array(discrete_touch, (0 + touchSizeEdge), (touchSize - touchSizeEdge)); + touchBottom = utils::average::array(discrete_touch, (touchSize - touchSizeEdge), touchSize); + + // for(int i = 0; i < touchSize; i++) + // std::cout << discrete_touch[i] << " "; + // std::cout << "\ntouchAll: " << touchAll; + // std::cout << "\ttouchTop: " << touchTop; + // std::cout << "\ttouchMiddle: " << touchMiddle; + // std::cout << "\ttouchBottom: " << touchBottom << std::endl; // 1D blob detection: used for brush const auto movement = blobDetector.detect1D(discrete_touch, touchSize); @@ -89,11 +89,9 @@ class Touch // no movement since the last update -> reset the brush counter if(movement[i] == 0) { -#if USE_BRUSH_COUNTER // wait some time before dropping the rub/brush values if(++brushCounter[i] < 10) continue; -#endif if(brushes[i].value < 0.001) { @@ -107,7 +105,7 @@ class Touch rubs[i].update(m); } } - //large movement, so update only brushes and with 0? + //large movement, so update only brushes with 0? else if(std::abs(movement[i]) > 1) { brushes[i].update(0); @@ -120,31 +118,13 @@ class Touch brushes[i].update(movement[i]); rubs[i].update(movement[i]); -#if USE_BRUSH_COUNTER - //I've left this because it was in the OG code, but TBH it's making the (wokwi) data way messier brushCounter[i] = 0; -#endif } } // Calculate total brush and rub values - totalBrush = std::accumulate( - std::begin(brushes), std::end(brushes), 0.0f, - [](float sum, const Brush& brush) { return sum + brush.value; }); - - totalRub = std::accumulate( - std::begin(rubs), std::end(rubs), 0.0f, - [](float sum, const Rub& rub) { return sum + rub.value; }); - } - -private: - float touchAverage(int* array, int start, int end) - { - float sum = 0; - for(int i = start; i < end; ++i) - sum += array[i]; - - return sum / (end - start); + totalBrush = utils::average::arrayIgnoringZeroes(brushes, maxNumBlobs); + totalRub = utils::average::arrayIgnoringZeroes(rubs, maxNumBlobs); } }; } diff --git a/include/puara/utils.h b/include/puara/utils.h index d3f819b..1f73285 100644 --- a/include/puara/utils.h +++ b/include/puara/utils.h @@ -35,11 +35,65 @@ inline unsigned long long getCurrentTimeMicroseconds() return duration.count(); } +/** + * @brief Legacy function used to calculate 1D blob detection in older + * digital musical instruments + */ +inline void bitShiftArrayL(int* origArray, int* shiftedArray, int arraySize, int shift) +{ + for(int i = 0; i < arraySize; ++i) + { + shiftedArray[i] = origArray[i]; + } + for(int k = 0; k < shift; ++k) + { + for(int i = 0; i < arraySize; ++i) + { + if(i == (arraySize - 1)) + { + shiftedArray[i] = (shiftedArray[i] << 1); + } + else + { + shiftedArray[i] = (shiftedArray[i] << 1) | (shiftedArray[i + 1] >> 7); + } + } + } +} + +namespace average +{ +/** + * @brief Computes the average of elements in an array over a specified range. + * + * @tparam T The type of the elements in the array. Must be an arithmetic type (e.g., int, float, double). + * @param array Pointer to the array of elements. + * @param start The starting index of the range (inclusive). Must be >= 0. + * @param end The ending index of the range (exclusive). Must be >= start. + * @return The average of the elements in the specified range as a float. Returns 0.0 if the range is invalid or empty. + */ +template +float array(const T* array, int start, int end) +{ + static_assert( + std::is_arithmetic::value, + "Template type T must be an arithmetic type (int, float, double, etc.)"); + assert(start >= 0 && end >= start); + + float sum{}; + for(int i = start; i < end; ++i) + sum += static_cast(array[i]); + + const auto count = end - start; + return (count > 0) ? (sum / count) : 0.0; +} + /** * @brief Function used to reduce feature arrays into single values. - * E.g., brush uses it to reduce multiBrush instances + * E.g., brush uses it to reduce multiBrush instances. Any value in + * the passed Array that is == 0 is ignored in the average calculation. */ -inline double arrayAverageZero(double* Array, int ArraySize) +inline double arrayIgnoringZeroes(double* Array, int ArraySize) { double sum = 0; int count = 0; @@ -60,29 +114,33 @@ inline double arrayAverageZero(double* Array, int ArraySize) } /** - * @brief Legacy function used to calculate 1D blob detection in older - * digital musical instruments + * @brief Function used to reduce feature arrays into single values. + * E.g., brush uses it to reduce multiBrush instances. Any value in + * the passed Array that is == 0 is ignored in the average calculation. */ -inline void bitShiftArrayL(int* origArray, int* shiftedArray, int arraySize, int shift) +template +inline double arrayIgnoringZeroes(T* Array, int ArraySize) { - for(int i = 0; i < arraySize; ++i) - { - shiftedArray[i] = origArray[i]; - } - for(int k = 0; k < shift; ++k) + static_assert(std::is_same::value, "T must have a public float value member"); + + double sum = 0.0; + int count = 0; + double output = 0.0; + + for(int i = 0; i < ArraySize; ++i) { - for(int i = 0; i < arraySize; ++i) + if(Array[i].value != 0.0f) { - if(i == (arraySize - 1)) - { - shiftedArray[i] = (shiftedArray[i] << 1); - } - else - { - shiftedArray[i] = (shiftedArray[i] << 1) | (shiftedArray[i + 1] >> 7); - } + sum += Array[i].value; + count++; } } + + if(count > 0) + output = sum / count; + + return output; +} } namespace convert