* @param source source address | * @param source source address | ||||
*/ | */ | ||||
static void copy_buffer(void *destination, const void *source) { | static void copy_buffer(void *destination, const void *source) { | ||||
const uint16_t *src = (const uint16_t *)source; | |||||
uint16_t *dst = (uint16_t *)destination; | |||||
for (int i=0; i < AUDIO_BLOCK_SAMPLES; i++) *dst++ = *src++; | |||||
const uint16_t *src = ( const uint16_t * )source; | |||||
uint16_t *dst = ( uint16_t * )destination; | |||||
for (int i=0; i < AUDIO_BLOCK_SAMPLES; i++) *dst++ = (*src++); | |||||
} | } | ||||
/** | /** | ||||
* Virtual function to override from Audio Library | * Virtual function to override from Audio Library | ||||
*/ | */ | ||||
if ( next_buffer ) { | if ( next_buffer ) { | ||||
if ( !first_run && process_buffer ) process( ); | if ( !first_run && process_buffer ) process( ); | ||||
for ( int i = 0; i < AUDIO_GUITARTUNER_BLOCKS; i++ ) copy_buffer( AudioBuffer+( i * 0x80 ), blocklist1[i]->data ); | for ( int i = 0; i < AUDIO_GUITARTUNER_BLOCKS; i++ ) copy_buffer( AudioBuffer+( i * 0x80 ), blocklist1[i]->data ); | ||||
for ( int i = 0; i < AUDIO_GUITARTUNER_BLOCKS; i++ ) release(blocklist1[i] ); | |||||
for ( int i = 0; i < AUDIO_GUITARTUNER_BLOCKS; i++ ) release( blocklist1[i] ); | |||||
next_buffer = false; | |||||
} else { | } else { | ||||
if ( !first_run && process_buffer ) process( ); | if ( !first_run && process_buffer ) process( ); | ||||
for ( int i = 0; i < AUDIO_GUITARTUNER_BLOCKS; i++ ) copy_buffer( AudioBuffer+( i * 0x80 ), blocklist2[i]->data ); | for ( int i = 0; i < AUDIO_GUITARTUNER_BLOCKS; i++ ) copy_buffer( AudioBuffer+( i * 0x80 ), blocklist2[i]->data ); | ||||
for ( int i = 0; i < AUDIO_GUITARTUNER_BLOCKS; i++ ) release( blocklist2[i] ); | for ( int i = 0; i < AUDIO_GUITARTUNER_BLOCKS; i++ ) release( blocklist2[i] ); | ||||
next_buffer = true; | |||||
} | } | ||||
process_buffer = true; | process_buffer = true; | ||||
first_run = false; | first_run = false; | ||||
state = 0; | state = 0; | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Start the Yin algorithm | * Start the Yin algorithm | ||||
* | * | ||||
* page 79. Might have to downsample for low fundmental frequencies because of fft buffer | * page 79. Might have to downsample for low fundmental frequencies because of fft buffer | ||||
* size limit. | * size limit. | ||||
*/ | */ | ||||
FASTRUN void AudioAnalyzeNoteFrequency::process( void ) { | |||||
void AudioAnalyzeNoteFrequency::process( void ) { | |||||
const int16_t *p; | const int16_t *p; | ||||
p = AudioBuffer; | p = AudioBuffer; | ||||
uint16_t tau = tau_global; | uint16_t tau = tau_global; | ||||
do { | do { | ||||
uint16_t x = 0; | uint16_t x = 0; | ||||
int64_t sum = 0; | |||||
uint64_t sum = 0; | |||||
do { | do { | ||||
int16_t current, lag, delta; | int16_t current, lag, delta; | ||||
lag = *( ( int16_t * )p + ( x+tau ) ); | lag = *( ( int16_t * )p + ( x+tau ) ); | ||||
current = *( ( int16_t * )p+x ); | current = *( ( int16_t * )p+x ); | ||||
delta = ( current-lag ); | delta = ( current-lag ); | ||||
sum += delta * delta; | sum += delta * delta; | ||||
#if F_CPU == 144000000 | |||||
x += 8; | |||||
#elif F_CPU == 120000000 | |||||
x += 12; | |||||
#elif F_CPU == 96000000 | |||||
x += 16; | |||||
#elif F_CPU < 96000000 | |||||
x += 32; | |||||
#endif | |||||
} while ( x <= HALF_BLOCKS ); | |||||
x += 4; | |||||
lag = *( ( int16_t * )p + ( x+tau ) ); | |||||
current = *( ( int16_t * )p+x ); | |||||
delta = ( current-lag ); | |||||
sum += delta * delta; | |||||
x += 4; | |||||
lag = *( ( int16_t * )p + ( x+tau ) ); | |||||
current = *( ( int16_t * )p+x ); | |||||
delta = ( current-lag ); | |||||
sum += delta * delta; | |||||
x += 4; | |||||
lag = *( ( int16_t * )p + ( x+tau ) ); | |||||
current = *( ( int16_t * )p+x ); | |||||
delta = ( current-lag ); | |||||
sum += delta * delta; | |||||
x += 4; | |||||
} while ( x < HALF_BLOCKS ); | |||||
running_sum += sum; | |||||
uint64_t rs = running_sum; | |||||
rs += sum; | |||||
yin_buffer[yin_idx] = sum*tau; | yin_buffer[yin_idx] = sum*tau; | ||||
rs_buffer[yin_idx] = running_sum; | |||||
rs_buffer[yin_idx] = rs; | |||||
running_sum = rs; | |||||
yin_idx = ( ++yin_idx >= 5 ) ? 0 : yin_idx; | yin_idx = ( ++yin_idx >= 5 ) ? 0 : yin_idx; | ||||
tau = estimate( yin_buffer, rs_buffer, yin_idx, tau ); | tau = estimate( yin_buffer, rs_buffer, yin_idx, tau ); | ||||
return; | return; | ||||
} | } | ||||
} while ( --cycles ); | } while ( --cycles ); | ||||
digitalWriteFast(10, LOW); | |||||
if ( tau >= HALF_BLOCKS ) { | if ( tau >= HALF_BLOCKS ) { | ||||
process_buffer = false; | process_buffer = false; | ||||
new_output = false; | new_output = false; | ||||
* | * | ||||
* @return tau | * @return tau | ||||
*/ | */ | ||||
uint16_t AudioAnalyzeNoteFrequency::estimate( int64_t *yin, int64_t *rs, uint16_t head, uint16_t tau ) { | |||||
const int64_t *y = ( int64_t * )yin; | |||||
const int64_t *r = ( int64_t * )rs; | |||||
uint16_t AudioAnalyzeNoteFrequency::estimate( uint64_t *yin, uint64_t *rs, uint16_t head, uint16_t tau ) { | |||||
const uint64_t *y = ( uint64_t * )yin; | |||||
const uint64_t *r = ( uint64_t * )rs; | |||||
uint16_t _tau, _head; | uint16_t _tau, _head; | ||||
const float thresh = yin_threshold; | const float thresh = yin_threshold; | ||||
_tau = tau; | _tau = tau; |
* @return none | * @return none | ||||
*/ | */ | ||||
AudioAnalyzeNoteFrequency( void ) : AudioStream( 1, inputQueueArray ), enabled( false ), new_output(false) { | AudioAnalyzeNoteFrequency( void ) : AudioStream( 1, inputQueueArray ), enabled( false ), new_output(false) { | ||||
} | } | ||||
/** | /** | ||||
* @return none | * @return none | ||||
*/ | */ | ||||
virtual void update( void ); | virtual void update( void ); | ||||
private: | private: | ||||
/** | /** | ||||
* check the sampled data for fundamental frequency | * check the sampled data for fundamental frequency | ||||
* | * | ||||
* @return tau | * @return tau | ||||
*/ | */ | ||||
uint16_t estimate( int64_t *yin, int64_t *rs, uint16_t head, uint16_t tau ); | |||||
uint16_t estimate( uint64_t *yin, uint64_t *rs, uint16_t head, uint16_t tau ); | |||||
/** | /** | ||||
* process audio data | * process audio data | ||||
*/ | */ | ||||
uint64_t running_sum; | uint64_t running_sum; | ||||
uint16_t tau_global; | uint16_t tau_global; | ||||
int64_t rs_buffer[5], yin_buffer[5]; | |||||
uint64_t yin_buffer[5]; | |||||
uint64_t rs_buffer[5]; | |||||
int16_t AudioBuffer[AUDIO_GUITARTUNER_BLOCKS*128] __attribute__ ( ( aligned ( 4 ) ) ); | int16_t AudioBuffer[AUDIO_GUITARTUNER_BLOCKS*128] __attribute__ ( ( aligned ( 4 ) ) ); | ||||
uint8_t yin_idx, state; | uint8_t yin_idx, state; | ||||
float periodicity, yin_threshold, cpu_usage_max, data; | float periodicity, yin_threshold, cpu_usage_max, data; |
*/ | */ | ||||
notefreq.begin(.15); | notefreq.begin(.15); | ||||
pinMode(LED_BUILTIN, OUTPUT); | pinMode(LED_BUILTIN, OUTPUT); | ||||
// Audio library isr allways gets priority | |||||
playNoteTimer.priority(144); | |||||
playNoteTimer.begin(playNote, 1000); | playNoteTimer.begin(playNote, 1000); | ||||
} | } | ||||
#include "a2_note.h" | #include "a2_note.h" | ||||
const unsigned int a2_note[53971] = { | |||||
const unsigned int a2_note[53801] = { | |||||
0x8100D2D3, 0xFFF7FFFB, 0xFFF7FFF8, 0xFFF3FFF6, 0xFFEDFFEF, 0xFFEAFFEC, 0xFFE6FFE9, 0xFFE0FFE2, 0xFFDAFFDD, 0xFFD5FFD7, 0xFFCFFFD3, | 0x8100D2D3, 0xFFF7FFFB, 0xFFF7FFF8, 0xFFF3FFF6, 0xFFEDFFEF, 0xFFEAFFEC, 0xFFE6FFE9, 0xFFE0FFE2, 0xFFDAFFDD, 0xFFD5FFD7, 0xFFCFFFD3, | ||||
0xFFC9FFCB, 0xFFC6FFC9, 0xFFC0FFC4, 0xFFBBFFBD, 0xFFB4FFB7, 0xFFB0FFB0, 0xFFABFFAE, 0xFFA3FFA7, 0xFF9CFFA0, 0xFF99FF9A, 0xFF94FF96, | 0xFFC9FFCB, 0xFFC6FFC9, 0xFFC0FFC4, 0xFFBBFFBD, 0xFFB4FFB7, 0xFFB0FFB0, 0xFFABFFAE, 0xFFA3FFA7, 0xFF9CFFA0, 0xFF99FF9A, 0xFF94FF96, | ||||
0xFF90FF93, 0xFF8CFF8D, 0xFF85FF89, 0xFF83FF82, 0xFF7DFF80, 0xFF78FF7C, 0xFF75FF77, 0xFF6EFF72, 0xFF6AFF6C, 0xFF69FF6A, 0xFF63FF67, | 0xFF90FF93, 0xFF8CFF8D, 0xFF85FF89, 0xFF83FF82, 0xFF7DFF80, 0xFF78FF7C, 0xFF75FF77, 0xFF6EFF72, 0xFF6AFF6C, 0xFF69FF6A, 0xFF63FF67, | ||||
0x069F0620, 0x07A10721, 0x08A50822, 0x09B0092A, 0x0AB70A31, 0x0BC50B3D, 0x0CD20C4C, 0x0DDF0D58, 0x0EF00E67, 0x0FFD0F77, 0x1102107F, | 0x069F0620, 0x07A10721, 0x08A50822, 0x09B0092A, 0x0AB70A31, 0x0BC50B3D, 0x0CD20C4C, 0x0DDF0D58, 0x0EF00E67, 0x0FFD0F77, 0x1102107F, | ||||
0x12011184, 0x12FA127F, 0x13E91373, 0x14CC145C, 0x15A4153A, 0x1670160C, 0x172D16D1, 0x17DD1786, 0x1879182E, 0x190118C0, 0x197A193F, | 0x12011184, 0x12FA127F, 0x13E91373, 0x14CC145C, 0x15A4153A, 0x1670160C, 0x172D16D1, 0x17DD1786, 0x1879182E, 0x190118C0, 0x197A193F, | ||||
0x19E019AF, 0x1A2C1A09, 0x1A5E1A47, 0x1A7B1A70, 0x1A851A81, 0x1A761A81, 0x1A501A66, 0x1A161A35, 0x19CF19F5, 0x197B19A8, 0x191D194D, | 0x19E019AF, 0x1A2C1A09, 0x1A5E1A47, 0x1A7B1A70, 0x1A851A81, 0x1A761A81, 0x1A501A66, 0x1A161A35, 0x19CF19F5, 0x197B19A8, 0x191D194D, | ||||
0x18B518EB, 0x184A187F, 0x17DF1813, 0x177517A9, 0x1708173D, 0x16A016D2, 0x16441671, 0x15EF1617, 0x159F15C5, 0x15521578, 0x15131532, | |||||
0x14D814F4, 0x149F14BB, 0x146B1485, 0x143B1454, 0x140A1421, 0x13DF13F3, 0x13B213C7, 0x1386139B, 0x135C1370, 0x1338134A, 0x13141326, | |||||
0x12F31304, 0x12D712E4, 0x12BF12CA, 0x12A412B1, 0x12891295, 0x1274127F, 0x125B126B, 0x123D124D, 0x1220122E, 0x11FC120E, 0x11D411E9, | |||||
0x11A611BE, 0x1173118D, 0x113A1156, 0x10F81119, 0x10B310D8, 0x1067108E, 0x1013103E, 0x0FC00FE8, 0x0F6A0F96, 0x0F0B0F3C, 0x0EAE0EDE, | |||||
0x0E510E80, 0x0DF30E24, 0x0D940DC3, 0x0D360D64, 0x0CDA0D07, 0x0C7C0CAA, 0x0C200C4D, 0x0BC80BF5, 0x0B6E0B9D, 0x0B130B41, 0x0ABE0AE7, | |||||
0x0A650A92, 0x0A0B0A38, 0x09B109DE, 0x09580984, 0x08FB092B, 0x089C08CC, 0x083D086D, 0x07DA080C, 0x077307A6, 0x070D0740, 0x06A006D7, | |||||
0x062D0667, 0x05B205EE, 0x05320573, 0x04A704EF, 0x040E045E, 0x036A03BE, 0x02B80314, 0x01F30259, 0x011B018A, 0x003200A9, 0xFF33FFB3, | |||||
0xFE1EFEAA, 0xFCF4FD8B, 0xFBB9FC59, 0xFA6FFB15, 0xF917F9C4, 0xF7B8F868, 0xF650F704, 0xF4E8F59C, 0xF385F436, 0xF228F2D7, 0xF0D3F17E, | |||||
0xEF8DF02F, 0xEE56EEEF, 0xED2EEDC0, 0xEC16ECA0, 0xEB0DEB90, 0xEA1AEA92, 0xE935E9A6, 0xE85FE8C7, 0xE798E7F8, 0xE6E0E739, 0xE638E68B, | |||||
0xE59FE5EA, 0xE510E557, 0xE48DE4CE, 0xE418E451, 0xE3ABE3E1, 0xE347E378, 0xE2E8E316, 0xE294E2BE, 0xE247E26D, 0xE1FEE222, 0xE1BEE1DE, | |||||
0xE181E19E, 0xE14CE164, 0xE11BE133, 0xE0F0E106, 0xE0CBE0DD, 0xE0ADE0BB, 0xE098E0A2, 0xE086E08F, 0xE07DE080, 0xE07EE07C, 0xE089E085, | |||||
0xE09CE092, 0xE0B8E0A8, 0xE0DCE0C8, 0xE108E0F1, 0xE141E122, 0xE180E15F, 0xE1C7E1A1, 0xE216E1EC, 0xE271E243, 0xE2D5E2A2, 0xE341E30A, | |||||
0xE3C0E37E, 0xE449E403, 0xE4E0E494, 0xE581E52E, 0xE632E5D7, 0xE6EEE68F, 0xE7B6E751, 0xE88BE820, 0xE969E8F8, 0xEA4CE9D9, 0xEB39EAC2, | |||||
0xEC2FEBB2, 0xED26ECA9, 0xEE21EDA3, 0xEF23EEA2, 0xF029EFA8, 0xF12FF0AD, 0xF23CF1B5, 0xF34CF2C4, 0xF461F3D7, 0xF577F4EC, 0xF693F605, | |||||
0xF7ACF71D, 0xF8CAF83B, 0xF9E7F957, 0xFB04FA76, 0xFC1DFB91, 0xFD33FCA8, 0xFE49FDBE, 0xFF57FED1, 0x005FFFDC, 0x016A00E5, 0x026D01EB, | |||||
0x036C02EC, 0x046A03EB, 0x056904EA, 0x066805E8, 0x076506E7, | |||||
}; | }; |
#include "Arduino.h" | #include "Arduino.h" | ||||
extern const unsigned int a2_note[53971]; | |||||
extern const unsigned int a2_note[53801]; |
#include "Arduino.h" | #include "Arduino.h" | ||||
extern const unsigned int b3_note[53990]; | |||||
extern const unsigned int b3_note[53823]; |
#include "Arduino.h" | #include "Arduino.h" | ||||
extern const unsigned int d3_note[53974]; | |||||
extern const unsigned int d3_note[53801]; |
#include "Arduino.h" | #include "Arduino.h" | ||||
extern const unsigned int e2_note[53990]; | |||||
extern const unsigned int e2_note[53636]; |
#include "Arduino.h" | #include "Arduino.h" | ||||
extern const unsigned int e4_note[53990]; | |||||
extern const unsigned int e4_note[53823]; |
#include "Arduino.h" | #include "Arduino.h" | ||||
extern const unsigned int g3_note[53965]; | |||||
extern const unsigned int g3_note[53790]; |