您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

131 行
3.0KB

  1. #include "Audio.h"
  2. #include "arm_math.h"
  3. #include "utility/dspinst.h"
  4. static arm_cfft_radix4_instance_q15 fft_inst;
  5. void AudioAnalyzeFFT256::init(void)
  6. {
  7. // TODO: replace this with static const version
  8. arm_cfft_radix4_init_q15(&fft_inst, 256, 0, 1);
  9. //for (int i=0; i<2048; i++) {
  10. //buffer[i] = i * 3;
  11. //}
  12. //__disable_irq();
  13. //ARM_DEMCR |= ARM_DEMCR_TRCENA;
  14. //ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
  15. //uint32_t n = ARM_DWT_CYCCNT;
  16. //arm_cfft_radix2_q15(&fft_inst, buffer);
  17. //n = ARM_DWT_CYCCNT - n;
  18. //__enable_irq();
  19. //cycles = n;
  20. //arm_cmplx_mag_q15(buffer, buffer, 512);
  21. // each audio block is 278525 cycles @ 96 MHz
  22. // 256 point fft2 takes 65408 cycles
  23. // 256 point fft4 takes 49108 cycles
  24. // 128 point cmag takes 10999 cycles
  25. // 1024 point fft2 takes 125948 cycles
  26. // 1024 point fft4 takes 125840 cycles
  27. // 512 point cmag takes 43764 cycles
  28. //state = 0;
  29. //outputflag = false;
  30. }
  31. static void copy_to_fft_buffer(void *destination, const void *source)
  32. {
  33. const int16_t *src = (const int16_t *)source;
  34. int16_t *dst = (int16_t *)destination;
  35. // TODO: optimize this
  36. for (int i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
  37. *dst++ = *src++; // real
  38. *dst++ = 0; // imaginary
  39. }
  40. }
  41. static void apply_window_to_fft_buffer(void *buffer, const void *window)
  42. {
  43. int16_t *buf = (int16_t *)buffer;
  44. const int16_t *win = (int16_t *)window;;
  45. for (int i=0; i < 256; i++) {
  46. int32_t val = *buf * *win++;
  47. //*buf = signed_saturate_rshift(val, 16, 15);
  48. *buf = val >> 15;
  49. buf += 2;
  50. }
  51. }
  52. void AudioAnalyzeFFT256::update(void)
  53. {
  54. audio_block_t *block;
  55. block = receiveReadOnly();
  56. if (!block) return;
  57. if (!prevblock) {
  58. prevblock = block;
  59. return;
  60. }
  61. copy_to_fft_buffer(buffer, prevblock->data);
  62. copy_to_fft_buffer(buffer+256, block->data);
  63. //window = AudioWindowBlackmanNuttall256;
  64. //window = NULL;
  65. if (window) apply_window_to_fft_buffer(buffer, window);
  66. arm_cfft_radix4_q15(&fft_inst, buffer);
  67. // TODO: is this averaging correct? G. Heinzel's paper says we're
  68. // supposed to average the magnitude squared, then do the square
  69. // root at the end after dividing by naverage.
  70. arm_cmplx_mag_q15(buffer, buffer, 128);
  71. if (count == 0) {
  72. for (int i=0; i < 128; i++) {
  73. output[i] = buffer[i];
  74. }
  75. } else {
  76. for (int i=0; i < 128; i++) {
  77. output[i] += buffer[i];
  78. }
  79. }
  80. if (++count == naverage) {
  81. count = 0;
  82. for (int i=0; i < 128; i++) {
  83. output[i] /= naverage;
  84. }
  85. outputflag = true;
  86. }
  87. release(prevblock);
  88. prevblock = block;
  89. #if 0
  90. block = receiveReadOnly();
  91. if (state == 0) {
  92. //Serial.print("0");
  93. if (block == NULL) return;
  94. copy_to_fft_buffer(buffer, block->data);
  95. state = 1;
  96. } else if (state == 1) {
  97. //Serial.print("1");
  98. if (block == NULL) return;
  99. copy_to_fft_buffer(buffer+256, block->data);
  100. arm_cfft_radix4_q15(&fft_inst, buffer);
  101. state = 2;
  102. } else {
  103. //Serial.print("2");
  104. arm_cmplx_mag_q15(buffer, output, 128);
  105. outputflag = true;
  106. if (block == NULL) return;
  107. copy_to_fft_buffer(buffer, block->data);
  108. state = 1;
  109. }
  110. release(block);
  111. #endif
  112. }