You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

283 satır
7.7KB

  1. /* Audio Library Guitar and 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 "AudioTuner.h"
  23. #include "utility/dspinst.h"
  24. #if SAMPLE_RATE == SAMPLE_RATE_44100
  25. #define SAMPLE_RATE_EXACT AUDIO_SAMPLE_RATE_EXACT / 1
  26. #elif SAMPLE_RATE == SAMPLE_RATE_22050
  27. #define SAMPLE_RATE_EXACT AUDIO_SAMPLE_RATE_EXACT / 2
  28. #elif SAMPLE_RATE == SAMPLE_RATE_11025
  29. #define SAMPLE_RATE_EXACT AUDIO_SAMPLE_RATE_EXACT / 4
  30. #endif
  31. #define HALF_BUFFER NUM_SAMPLES / 2
  32. #define LOOP1(a) a
  33. #define LOOP2(a) a LOOP1(a)
  34. #define LOOP3(a) a LOOP2(a)
  35. #define LOOP8(a) a LOOP3(a) a LOOP3(a)
  36. #define UNROLL(n,a) LOOP##n(a)
  37. /**
  38. * Audio update function.
  39. */
  40. void AudioTuner::update( void ) {
  41. audio_block_t *block;
  42. const int16_t *p, *end;
  43. block = receiveReadOnly( );
  44. if ( !block ) return;
  45. if ( !enabled ) {
  46. release( block );
  47. return;
  48. }
  49. p = block->data;
  50. end = p + AUDIO_BLOCK_SAMPLES;
  51. /*
  52. * Set the number of cycles to processed per receiving block.
  53. *
  54. */
  55. uint16_t cycles;
  56. const uint16_t usage_max = cpu_usage_max;
  57. if ( AudioProcessorUsage( ) > usage_max ) {
  58. #if NUM_SAMPLES >= 8192
  59. cycles = tau_global + 2;
  60. #elif NUM_SAMPLES == 4096
  61. cycles = tau_global + 4;
  62. #elif NUM_SAMPLES == 2048
  63. cycles = tau_global + 8;
  64. #elif NUM_SAMPLES <= 1024
  65. cycles = tau_global + 16;
  66. #endif
  67. }
  68. else {
  69. #if NUM_SAMPLES >= 8192
  70. cycles = tau_global + 8;
  71. #elif NUM_SAMPLES == 4096
  72. cycles = tau_global + 16;
  73. #elif NUM_SAMPLES == 2048
  74. cycles = tau_global + 32;
  75. #elif NUM_SAMPLES <= 1024
  76. cycles = tau_global + 64;
  77. #endif
  78. }
  79. uint16_t count = count_global;
  80. /*
  81. * Double buffering, one fill while the other is processed
  82. * 2x the throughput.
  83. */
  84. uint16_t *dst;
  85. if ( next_buffer ) dst = ( uint16_t * )buffer;
  86. else dst = ( uint16_t * )buffer + NUM_SAMPLES;
  87. // gather data
  88. do {
  89. *( dst+count++ ) = *( uint16_t * )p;
  90. p += SAMPLE_RATE;
  91. } while ( p < end );
  92. release( block );
  93. /*
  94. * If buffer full switch to start filling next
  95. * buffer and process the just filled buffer.
  96. */
  97. if ( count >= NUM_SAMPLES ) {
  98. //digitalWriteFast(2, !digitalReadFast(2));
  99. next_buffer = !next_buffer;
  100. process_buffer = true;
  101. count_global = 0;
  102. tau_global = 1;
  103. yin_idx = 1;
  104. running_sum = 0;
  105. count = 0;
  106. }
  107. count_global = count;// update global count
  108. if ( process_buffer ) {
  109. //digitalWriteFast(0, HIGH);
  110. uint16_t tau;
  111. uint16_t next;
  112. next = next_buffer;
  113. tau = tau_global;
  114. do {
  115. int64_t sum = 0;
  116. const int16_t *end, *buf;
  117. if ( next ) buf = buffer + NUM_SAMPLES;
  118. else buf = buffer;
  119. end = buf + HALF_BUFFER;
  120. do {
  121. int16_t current, lag, delta;
  122. UNROLL( 8,
  123. lag = *( buf + tau );
  124. current = *buf++;
  125. delta = current - lag;
  126. //sum = multiply_accumulate_32x32_rshift32_rounded(sum, delta, delta);
  127. sum += delta*delta;
  128. );
  129. } while ( buf < end );
  130. running_sum += sum;
  131. yin_buffer[yin_idx] = sum*tau;
  132. rs_buffer[yin_idx] = running_sum;
  133. yin_idx = ( ++yin_idx >= 5 ) ? 0 : yin_idx;
  134. tau = estimate( yin_buffer, rs_buffer, yin_idx, tau );
  135. if ( tau == 0 ) {
  136. process_buffer = false;
  137. new_output = true;
  138. //digitalWriteFast(0, LOW);
  139. return;
  140. }
  141. else if ( tau >= HALF_BUFFER ) {
  142. process_buffer = false;
  143. new_output = false;
  144. //digitalWriteFast(0, LOW);
  145. return;
  146. }
  147. } while ( tau <= cycles );
  148. tau_global = tau;
  149. //digitalWriteFast(0, LOW);
  150. }
  151. }
  152. /**
  153. * check the sampled data for fundmental frequency
  154. *
  155. * @param yin buffer to hold sum*tau value
  156. * @param rs buffer to hold running sum for sampled window
  157. * @param head buffer index
  158. * @param tau lag we are currently working on this gets incremented
  159. *
  160. * @return tau
  161. */
  162. uint16_t AudioTuner::estimate( int64_t *yin, int64_t *rs, uint16_t head, uint16_t tau ) {
  163. const int64_t *p = ( int64_t * )yin;
  164. const int64_t *r = ( int64_t * )rs;
  165. uint16_t _tau, _head;
  166. _tau = tau;
  167. _head = head;
  168. if ( _tau > 4 ) {
  169. uint16_t idx0, idx1, idx2;
  170. idx0 = _head;
  171. idx1 = _head + 1;
  172. idx1 = ( idx1 >= 5 ) ? 0 : idx1;
  173. idx2 = head + 2;
  174. idx2 = ( idx2 >= 5 ) ? 0 : idx2;
  175. float s0, s1, s2;
  176. s0 = ( ( float )*( p+idx0 ) / r[idx0] );
  177. s1 = ( ( float )*( p+idx1 ) / r[idx1] );
  178. s2 = ( ( float )*( p+idx2 ) / r[idx2] );
  179. if ( s1 < yin_threshold && s1 < s2 ) {
  180. uint16_t period = _tau - 3;
  181. periodicity = 1 - s1;
  182. data = period + 0.5f * ( s0 - s2 ) / ( s0 - 2.0f * s1 + s2 );
  183. return 0;
  184. }
  185. if ( s1 > 2.4 ) return _tau + 2;
  186. else return _tau + 1;
  187. }
  188. return _tau + 1;
  189. }
  190. /**
  191. * Initialise
  192. *
  193. * @param threshold Allowed uncertainty
  194. * @param cpu_max How much cpu usage before throttling
  195. */
  196. void AudioTuner::initialize( float threshold, uint8_t cpu_max ) {
  197. __disable_irq( );
  198. cpu_usage_max = cpu_max;
  199. yin_threshold = threshold;
  200. process_buffer = false;
  201. periodicity = 0.0f;
  202. next_buffer = 1;
  203. running_sum = 0;
  204. count_global = 0;
  205. yin_idx = 1;
  206. data = 0;
  207. enabled = true;
  208. __enable_irq( );
  209. }
  210. /**
  211. * available
  212. *
  213. * @return true if data is ready else false
  214. */
  215. bool AudioTuner::available( void ) {
  216. __disable_irq( );
  217. bool flag = new_output;
  218. if ( flag ) new_output = false;
  219. __enable_irq( );
  220. return flag;
  221. }
  222. /**
  223. * read processes the data samples for the Yin algorithm.
  224. *
  225. * @return frequency in hertz
  226. */
  227. float AudioTuner::read( void ) {
  228. __disable_irq( );
  229. float d = data;
  230. __enable_irq( );
  231. d = SAMPLE_RATE_EXACT / d;
  232. return d;
  233. }
  234. /**
  235. * Periodicity of the sampled signal from Yin algorithm from read function.
  236. *
  237. * @return periodicity
  238. */
  239. float AudioTuner::probability( void ) {
  240. __disable_irq( );
  241. float p = periodicity;
  242. __enable_irq( );
  243. return p;
  244. }
  245. /**
  246. * Initialise parameters.
  247. *
  248. * @param thresh Allowed uncertainty
  249. */
  250. void AudioTuner::threshold( float p ) {
  251. __disable_irq( );
  252. yin_threshold = p;
  253. __enable_irq( );
  254. }