Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

134 lines
2.9KB

  1. #include "Audio.h"
  2. #include "arm_math.h"
  3. #include "utility/dspinst.h"
  4. static inline int32_t multiply_32x32_rshift30(int32_t a, int32_t b) __attribute__((always_inline));
  5. static inline int32_t multiply_32x32_rshift30(int32_t a, int32_t b)
  6. {
  7. return ((int64_t)a * (int64_t)b) >> 30;
  8. }
  9. //#define TONE_DETECT_FAST
  10. void AudioAnalyzeToneDetect::update(void)
  11. {
  12. audio_block_t *block;
  13. int32_t q0, q1, q2, coef;
  14. const int16_t *p, *end;
  15. uint16_t n;
  16. block = receiveReadOnly();
  17. if (!block) return;
  18. if (!enabled) {
  19. release(block);
  20. return;
  21. }
  22. p = block->data;
  23. end = p + AUDIO_BLOCK_SAMPLES;
  24. n = count;
  25. coef = coefficient;
  26. q1 = s1;
  27. q2 = s2;
  28. do {
  29. // the Goertzel algorithm is kinda magical ;-)
  30. #ifdef TONE_DETECT_FAST
  31. q0 = (*p++) + (multiply_32x32_rshift32_rounded(coef, q1) << 2) - q2;
  32. #else
  33. q0 = (*p++) + multiply_32x32_rshift30(coef, q1) - q2;
  34. // TODO: is this only 1 cycle slower? if so, always use it
  35. #endif
  36. q2 = q1;
  37. q1 = q0;
  38. if (--n == 0) {
  39. out1 = q1;
  40. out2 = q2;
  41. q1 = 0; // TODO: does clearing these help or hinder?
  42. q2 = 0;
  43. new_output = true;
  44. n = length;
  45. }
  46. } while (p < end);
  47. count = n;
  48. s1 = q1;
  49. s2 = q2;
  50. release(block);
  51. }
  52. void AudioAnalyzeToneDetect::set_params(int32_t coef, uint16_t cycles, uint16_t len)
  53. {
  54. __disable_irq();
  55. coefficient = coef;
  56. ncycles = cycles;
  57. length = len;
  58. count = len;
  59. s1 = 0;
  60. s2 = 0;
  61. enabled = true;
  62. __enable_irq();
  63. //Serial.printf("Tone: coef=%d, ncycles=%d, length=%d\n", coefficient, ncycles, length);
  64. }
  65. float AudioAnalyzeToneDetect::read(void)
  66. {
  67. int32_t coef, q1, q2, power;
  68. uint16_t len;
  69. __disable_irq();
  70. coef = coefficient;
  71. q1 = out1;
  72. q2 = out2;
  73. len = length;
  74. __enable_irq();
  75. #ifdef TONE_DETECT_FAST
  76. power = multiply_32x32_rshift32_rounded(q2, q2);
  77. power = multiply_accumulate_32x32_rshift32_rounded(power, q1, q1);
  78. power = multiply_subtract_32x32_rshift32_rounded(power,
  79. multiply_32x32_rshift30(q1, q2), coef);
  80. power <<= 4;
  81. #else
  82. int64_t power64;
  83. power64 = (int64_t)q2 * (int64_t)q2;
  84. power64 += (int64_t)q1 * (int64_t)q1;
  85. power64 -= (((int64_t)q1 * (int64_t)q2) >> 30) * (int64_t)coef;
  86. power = power64 >> 28;
  87. #endif
  88. return sqrtf((float)power) / (float)len;
  89. }
  90. AudioAnalyzeToneDetect::operator bool()
  91. {
  92. int32_t coef, q1, q2, power, trigger;
  93. uint16_t len;
  94. __disable_irq();
  95. coef = coefficient;
  96. q1 = out1;
  97. q2 = out2;
  98. len = length;
  99. __enable_irq();
  100. #ifdef TONE_DETECT_FAST
  101. power = multiply_32x32_rshift32_rounded(q2, q2);
  102. power = multiply_accumulate_32x32_rshift32_rounded(power, q1, q1);
  103. power = multiply_subtract_32x32_rshift32_rounded(power,
  104. multiply_32x32_rshift30(q1, q2), coef);
  105. power <<= 4;
  106. #else
  107. int64_t power64;
  108. power64 = (int64_t)q2 * (int64_t)q2;
  109. power64 += (int64_t)q1 * (int64_t)q1;
  110. power64 -= (((int64_t)q1 * (int64_t)q2) >> 30) * (int64_t)coef;
  111. power = power64 >> 28;
  112. #endif
  113. trigger = (uint32_t)len * thresh;
  114. trigger = multiply_32x32_rshift32(trigger, trigger);
  115. Serial.printf("bool: power=%d, trig=%d\n", power, trigger);
  116. return (power >= trigger);
  117. }