選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

AudioTuner.cpp 8.3KB

7年前
7年前
7年前
9年前
7年前
7年前
7年前
7年前
7年前
7年前
7年前
7年前
7年前
7年前
7年前
7年前
7年前
7年前
7年前
9年前
7年前
9年前
7年前
9年前
7年前
7年前
7年前
9年前
7年前
7年前
7年前
9年前
7年前
9年前
7年前
7年前
7年前
7年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /* Audio Library Note Frequency Detection & Guitar/Bass Tuner
  2. * Copyright (c) 2015, Colin Duffy
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice, development funding notice, and this permission
  12. * notice shall be included in all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. * THE SOFTWARE.
  21. */
  22. #include "utility/dspinst.h"
  23. #include "arm_math.h"
  24. #include "Arduino.h"
  25. #include "AudioTuner.h"
  26. #define NUM_SAMPLES ( AUDIO_GUITARTUNER_BLOCKS << 7 )
  27. void AudioTuner::update( void ) {
  28. audio_block_t *block;
  29. block = receiveReadOnly();
  30. if (!block) return;
  31. if ( !enabled ) {
  32. release( block );
  33. return;
  34. }
  35. /**
  36. * "factor" is the new block size calculated by
  37. * the decimated shift to incremnt the buffer
  38. * address.
  39. */
  40. const uint8_t factor = AUDIO_BLOCK_SAMPLES >> decimation_shift;
  41. // filter and decimate block by block the incoming signal and store in a buffer.
  42. arm_fir_decimate_fast_q15( &firDecimateInst, block->data, AudioBuffer + ( state * factor ), AUDIO_BLOCK_SAMPLES );
  43. /**
  44. * when half the blocks + 1 of the total
  45. * blocks have been stored in the buffer
  46. * start processing the data.
  47. */
  48. if ( state++ >= AUDIO_GUITARTUNER_BLOCKS >> 1 ) {
  49. if ( process_buffer ) process( AudioBuffer );
  50. if ( state == 0 ) process_buffer = true;
  51. }
  52. release( block );
  53. }
  54. /**
  55. * Start the Yin algorithm
  56. *
  57. * TODO: Significant speed up would be to use spectral domain to find fundamental frequency.
  58. * This paper explains: https://aubio.org/phd/thesis/brossier06thesis.pdf -> Section 3.2.4
  59. * page 79. Might have to downsample for low fundmental frequencies because of fft buffer
  60. * size limit.
  61. */
  62. void AudioTuner::process( int16_t *p ) {
  63. const uint16_t inner_cycles = ( NUM_SAMPLES >> decimation_shift ) >> 1;
  64. uint16_t outer_cycles = inner_cycles / AUDIO_GUITARTUNER_BLOCKS;
  65. uint16_t tau = tau_global;
  66. do {
  67. uint64_t sum = 0;
  68. int32_t a1, a2, b1, b2, c1, c2, d1, d2;
  69. int32_t out1, out2, out3, out4;
  70. uint16_t blkCnt;
  71. int16_t * cur = p;
  72. int16_t * lag = p + tau;
  73. // unrolling the inner loop by 8
  74. blkCnt = inner_cycles >> 3;
  75. do {
  76. // a(n), b(n), c(n), d(n) each hold two samples
  77. a1 = *__SIMD32( cur )++;
  78. a2 = *__SIMD32( cur )++;
  79. b1 = *__SIMD32( lag )++;
  80. b2 = *__SIMD32( lag )++;
  81. c1 = *__SIMD32( cur )++;
  82. c2 = *__SIMD32( cur )++;
  83. d1 = *__SIMD32( lag )++;
  84. d2 = *__SIMD32( lag )++;
  85. // subract two samples at a time
  86. out1 = __QSUB16( a1, b1 );
  87. out2 = __QSUB16( a2, b2 );
  88. out3 = __QSUB16( c1, d1 );
  89. out4 = __QSUB16( c2, d2 );
  90. // square the difference
  91. sum = multiply_accumulate_16tx16t_add_16bx16b( sum, out1, out1 );
  92. sum = multiply_accumulate_16tx16t_add_16bx16b( sum, out2, out2 );
  93. sum = multiply_accumulate_16tx16t_add_16bx16b( sum, out3, out3 );
  94. sum = multiply_accumulate_16tx16t_add_16bx16b( sum, out4, out4 );
  95. } while( --blkCnt );
  96. uint64_t rs = running_sum;
  97. rs += sum;
  98. yin_buffer[yin_idx] = sum*tau;
  99. rs_buffer[yin_idx] = rs;
  100. running_sum = rs;
  101. yin_idx = ( ++yin_idx >= 5 ) ? 0 : yin_idx;
  102. tau = estimate( yin_buffer, rs_buffer, yin_idx, tau );
  103. if ( tau == 0 ) {
  104. process_buffer = false;
  105. new_output = true;
  106. yin_idx = 1;
  107. running_sum = 0;
  108. tau_global = 1;
  109. state = 0;
  110. return;
  111. }
  112. } while ( --outer_cycles );
  113. if ( tau >= inner_cycles ) {
  114. process_buffer = true;
  115. new_output = false;
  116. yin_idx = 1;
  117. running_sum = 0;
  118. tau_global = 1;
  119. state = 0;
  120. return;
  121. }
  122. tau_global = tau;
  123. }
  124. /**
  125. * check the sampled data for fundamental frequency
  126. *
  127. * @param yin buffer to hold sum*tau value
  128. * @param rs buffer to hold running sum for sampled window
  129. * @param head buffer index
  130. * @param tau lag we are curly working on gets incremented
  131. *
  132. * @return tau
  133. */
  134. uint16_t AudioTuner::estimate( uint64_t *yin, uint64_t *rs, uint16_t head, uint16_t tau ) {
  135. const uint64_t *y = ( uint64_t * )yin;
  136. const uint64_t *r = ( uint64_t * )rs;
  137. uint16_t _tau, _head;
  138. const float thresh = yin_threshold;
  139. _tau = tau;
  140. _head = head;
  141. if ( _tau > 4 ) {
  142. uint16_t idx0, idx1, idx2;
  143. idx0 = _head;
  144. idx1 = _head + 1;
  145. idx1 = ( idx1 >= 5 ) ? 0 : idx1;
  146. idx2 = _head + 2;
  147. idx2 = ( idx2 >= 5 ) ? idx2 - 5 : idx2;
  148. // maybe fixed point would be better here? But how?
  149. float s0, s1, s2;
  150. s0 = ( ( float )*( y+idx0 ) / ( float )*( r+idx0 ) );
  151. s1 = ( ( float )*( y+idx1 ) / ( float )*( r+idx1 ) );
  152. s2 = ( ( float )*( y+idx2 ) / ( float )*( r+idx2 ) );
  153. if ( s1 < thresh && s1 < s2 ) {
  154. uint16_t period = _tau - 3;
  155. periodicity = 1 - s1;
  156. data = period + 0.5f * ( s0 - s2 ) / ( s0 - 2.0f * s1 + s2 );
  157. return 0;
  158. }
  159. }
  160. return _tau + 1;
  161. }
  162. /**
  163. * Initialise
  164. *
  165. * @param threshold Allowed uncertainty
  166. */
  167. void AudioTuner::begin( float threshold, int16_t *coeff, uint8_t taps, uint8_t factor ) {
  168. __disable_irq( );
  169. process_buffer = true;
  170. yin_threshold = threshold;
  171. periodicity = 0.0f;
  172. running_sum = 0;
  173. tau_global = 1;
  174. yin_idx = 1;
  175. enabled = true;
  176. state = 0;
  177. data = 0.0f;
  178. decimation_factor = factor;
  179. decimation_shift = log( factor ) / log( 2 );
  180. coeff_size = taps;
  181. coeff_p = coeff;
  182. arm_fir_decimate_init_q15( &firDecimateInst, coeff_size, decimation_factor, coeff_p, &coeff_state[0], AUDIO_BLOCK_SAMPLES );
  183. __enable_irq( );
  184. }
  185. /**
  186. * available
  187. *
  188. * @return true if data is ready else false
  189. */
  190. bool AudioTuner::available( void ) {
  191. __disable_irq( );
  192. bool flag = new_output;
  193. if ( flag ) new_output = false;
  194. __enable_irq( );
  195. return flag;
  196. }
  197. /**
  198. * read processes the data samples for the Yin algorithm.
  199. *
  200. * @return frequency in hertz
  201. */
  202. float AudioTuner::read( void ) {
  203. __disable_irq( );
  204. float d = data;
  205. __enable_irq( );
  206. return ( AUDIO_SAMPLE_RATE_EXACT / decimation_factor ) / d;
  207. }
  208. /**
  209. * Periodicity of the sampled signal.
  210. *
  211. * @return periodicity
  212. */
  213. float AudioTuner::probability( void ) {
  214. __disable_irq( );
  215. float p = periodicity;
  216. __enable_irq( );
  217. return p;
  218. }
  219. /**
  220. * New LP coeffients for decimation.
  221. *
  222. * @param p array pointer of coeffients.
  223. * @param n array size.
  224. */
  225. void AudioTuner::coeff( int16_t *p, int n ) {
  226. //coeff_size = n;
  227. //coeff_p = p;
  228. //arm_fir_decimate_init_q15(&firDecimateInst, coeff_size, 4, coeff_p, coeff_state, 128);
  229. }
  230. /**
  231. * Initialise parameters.
  232. *
  233. * @param thresh Allowed uncertainty
  234. */
  235. void AudioTuner::threshold( float p ) {
  236. __disable_irq( );
  237. yin_threshold = p;
  238. __enable_irq( );
  239. }
  240. /**
  241. * disable yin from processing data, use begin to start back up
  242. *
  243. * @return none
  244. */
  245. void AudioTuner::disable( void ) {
  246. __disable_irq( );
  247. enabled = false;
  248. __enable_irq( );
  249. }