| #include "analyze_fft1024.h" | #include "analyze_fft1024.h" | ||||
| #include "analyze_print.h" | #include "analyze_print.h" | ||||
| #include "analyze_tonedetect.h" | #include "analyze_tonedetect.h" | ||||
| #include "analyze_guitartuner.h" | |||||
| #include "analyze_notefreq.h" | |||||
| #include "analyze_peak.h" | #include "analyze_peak.h" | ||||
| #include "control_sgtl5000.h" | #include "control_sgtl5000.h" | ||||
| #include "control_wm8731.h" | #include "control_wm8731.h" |
| /* Audio Library Guitar and Bass Tuner | |||||
| /* Audio Library Note Frequency Detection & Guitar/Bass Tuner | |||||
| * Copyright (c) 2015, Colin Duffy | * Copyright (c) 2015, Colin Duffy | ||||
| * | * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * THE SOFTWARE. | * THE SOFTWARE. | ||||
| */ | */ | ||||
| #include "analyze_guitartuner.h" | |||||
| #include "analyze_notefreq.h" | |||||
| #include "utility/dspinst.h" | #include "utility/dspinst.h" | ||||
| #include "arm_math.h" | #include "arm_math.h" | ||||
| for (int i=0; i < AUDIO_BLOCK_SAMPLES; i++) *dst++ = *src++; | for (int i=0; i < AUDIO_BLOCK_SAMPLES; i++) *dst++ = *src++; | ||||
| } | } | ||||
| void AudioAnalyzeGuitarTuner::update( void ) { | |||||
| void AudioAnalyzeNoteFrequency::update( void ) { | |||||
| audio_block_t *block; | audio_block_t *block; | ||||
| } | } | ||||
| } | } | ||||
| FASTRUN void AudioAnalyzeGuitarTuner::process( void ) { | |||||
| FASTRUN void AudioAnalyzeNoteFrequency::process( void ) { | |||||
| //digitalWriteFast(0, HIGH); | //digitalWriteFast(0, HIGH); | ||||
| const int16_t *p; | const int16_t *p; | ||||
| * | * | ||||
| * @return tau | * @return tau | ||||
| */ | */ | ||||
| uint16_t AudioAnalyzeGuitarTuner::estimate( int64_t *yin, int64_t *rs, uint16_t head, uint16_t 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 *y = ( int64_t * )yin; | ||||
| const int64_t *r = ( int64_t * )rs; | const int64_t *r = ( int64_t * )rs; | ||||
| uint16_t _tau, _head; | uint16_t _tau, _head; | ||||
| * @param threshold Allowed uncertainty | * @param threshold Allowed uncertainty | ||||
| * @param cpu_max How much cpu usage before throttling | * @param cpu_max How much cpu usage before throttling | ||||
| */ | */ | ||||
| void AudioAnalyzeGuitarTuner::begin( float threshold ) { | |||||
| void AudioAnalyzeNoteFrequency::begin( float threshold ) { | |||||
| __disable_irq( ); | __disable_irq( ); | ||||
| process_buffer = false; | process_buffer = false; | ||||
| yin_threshold = threshold; | yin_threshold = threshold; | ||||
| * | * | ||||
| * @return true if data is ready else false | * @return true if data is ready else false | ||||
| */ | */ | ||||
| bool AudioAnalyzeGuitarTuner::available( void ) { | |||||
| bool AudioAnalyzeNoteFrequency::available( void ) { | |||||
| __disable_irq( ); | __disable_irq( ); | ||||
| bool flag = new_output; | bool flag = new_output; | ||||
| if ( flag ) new_output = false; | if ( flag ) new_output = false; | ||||
| * | * | ||||
| * @return frequency in hertz | * @return frequency in hertz | ||||
| */ | */ | ||||
| float AudioAnalyzeGuitarTuner::read( void ) { | |||||
| float AudioAnalyzeNoteFrequency::read( void ) { | |||||
| __disable_irq( ); | __disable_irq( ); | ||||
| float d = data; | float d = data; | ||||
| __enable_irq( ); | __enable_irq( ); | ||||
| * | * | ||||
| * @return periodicity | * @return periodicity | ||||
| */ | */ | ||||
| float AudioAnalyzeGuitarTuner::probability( void ) { | |||||
| float AudioAnalyzeNoteFrequency::probability( void ) { | |||||
| __disable_irq( ); | __disable_irq( ); | ||||
| float p = periodicity; | float p = periodicity; | ||||
| __enable_irq( ); | __enable_irq( ); | ||||
| * | * | ||||
| * @param thresh Allowed uncertainty | * @param thresh Allowed uncertainty | ||||
| */ | */ | ||||
| void AudioAnalyzeGuitarTuner::threshold( float p ) { | |||||
| void AudioAnalyzeNoteFrequency::threshold( float p ) { | |||||
| __disable_irq( ); | __disable_irq( ); | ||||
| yin_threshold = p; | yin_threshold = p; | ||||
| __enable_irq( ); | __enable_irq( ); |
| /* Audio Library Guitar and Bass Tuner | |||||
| /* Audio Library Note Frequency Detection & Guitar/Bass Tuner | |||||
| * Copyright (c) 2015, Colin Duffy | * Copyright (c) 2015, Colin Duffy | ||||
| * | * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * THE SOFTWARE. | * THE SOFTWARE. | ||||
| */ | */ | ||||
| #ifndef AudioAnalyzeGuitarTuner_h_ | |||||
| #define AudioAnalyzeGuitarTuner_h_ | |||||
| #ifndef AudioAnalyzeNoteFrequency_h_ | |||||
| #define AudioAnalyzeNoteFrequency_h_ | |||||
| #include "AudioStream.h" | #include "AudioStream.h" | ||||
| /*********************************************************************** | /*********************************************************************** | ||||
| ***********************************************************************/ | ***********************************************************************/ | ||||
| #define AUDIO_GUITARTUNER_BLOCKS 24 | #define AUDIO_GUITARTUNER_BLOCKS 24 | ||||
| /***********************************************************************/ | /***********************************************************************/ | ||||
| class AudioAnalyzeGuitarTuner : public AudioStream { | |||||
| class AudioAnalyzeNoteFrequency : public AudioStream { | |||||
| public: | public: | ||||
| /** | /** | ||||
| * constructor to setup Audio Library and initialize | * constructor to setup Audio Library and initialize | ||||
| * | * | ||||
| * @return none | * @return none | ||||
| */ | */ | ||||
| AudioAnalyzeGuitarTuner( void ) : AudioStream( 1, inputQueueArray ), enabled( false ), new_output(false) { | |||||
| AudioAnalyzeNoteFrequency( void ) : AudioStream( 1, inputQueueArray ), enabled( false ), new_output(false) { | |||||
| } | } | ||||
| /* Detect the frequency of music notes, by Colin Duffy | |||||
| This example repeatedly plays a guitar note (output to the DAC pin) | |||||
| and prints an analysis of the frequency to the Arduino Serial Monitor | |||||
| https://forum.pjrc.com/threads/32252-Different-Range-FFT-Algorithm/page2 | |||||
| https://github.com/duff2013/AudioTuner | |||||
| */ | |||||
| /* | /* | ||||
| C C# D Eb E F F# G G# A Bb B | C C# D Eb E F F# G G# A Bb B | ||||
| 0 16.35 17.32 18.35 19.45 20.60 21.83 23.12 24.50 25.96 27.50 29.14 30.87 | 0 16.35 17.32 18.35 19.45 20.60 21.83 23.12 24.50 25.96 27.50 29.14 30.87 | ||||
| #include "b3_note.h" | #include "b3_note.h" | ||||
| #include "e4_note.h" | #include "e4_note.h" | ||||
| //--------------------------------------------------------------------------------------- | //--------------------------------------------------------------------------------------- | ||||
| AudioAnalyzeGuitarTuner tuner; | |||||
| AudioAnalyzeNoteFrequency notefreq; | |||||
| AudioOutputAnalog dac; | AudioOutputAnalog dac; | ||||
| AudioPlayMemory wav_note; | AudioPlayMemory wav_note; | ||||
| AudioMixer4 mixer; | AudioMixer4 mixer; | ||||
| //--------------------------------------------------------------------------------------- | //--------------------------------------------------------------------------------------- | ||||
| AudioConnection patchCord0(wav_note, 0, mixer, 0); | AudioConnection patchCord0(wav_note, 0, mixer, 0); | ||||
| AudioConnection patchCord1(mixer, 0, tuner, 0); | |||||
| AudioConnection patchCord1(mixer, 0, notefreq, 0); | |||||
| AudioConnection patchCord2(mixer, 0, dac, 0); | AudioConnection patchCord2(mixer, 0, dac, 0); | ||||
| //--------------------------------------------------------------------------------------- | //--------------------------------------------------------------------------------------- | ||||
| IntervalTimer playNoteTimer; | IntervalTimer playNoteTimer; | ||||
| * Initialize the yin algorithm's absolute | * Initialize the yin algorithm's absolute | ||||
| * threshold, this is good number. | * threshold, this is good number. | ||||
| */ | */ | ||||
| tuner.begin(.15); | |||||
| notefreq.begin(.15); | |||||
| pinMode(LED_BUILTIN, OUTPUT); | pinMode(LED_BUILTIN, OUTPUT); | ||||
| playNoteTimer.begin(playNote, 1000); | playNoteTimer.begin(playNote, 1000); | ||||
| } | } | ||||
| void loop() { | void loop() { | ||||
| // read back fundamental frequency | // read back fundamental frequency | ||||
| if (tuner.available()) { | |||||
| float note = tuner.read(); | |||||
| float prob = tuner.probability(); | |||||
| if (notefreq.available()) { | |||||
| float note = notefreq.read(); | |||||
| float prob = notefreq.probability(); | |||||
| Serial.printf("Note: %3.2f | Probability: %.2f\n", note, prob); | Serial.printf("Note: %3.2f | Probability: %.2f\n", note, prob); | ||||
| } | } | ||||
| } | } |
| {"type":"AudioAnalyzeFFT256","data":{"defaults":{"name":{"value":"new"}},"shortName":"fft256","inputs":1,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png"}}, | {"type":"AudioAnalyzeFFT256","data":{"defaults":{"name":{"value":"new"}},"shortName":"fft256","inputs":1,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png"}}, | ||||
| {"type":"AudioAnalyzeFFT1024","data":{"defaults":{"name":{"value":"new"}},"shortName":"fft1024","inputs":1,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png"}}, | {"type":"AudioAnalyzeFFT1024","data":{"defaults":{"name":{"value":"new"}},"shortName":"fft1024","inputs":1,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png"}}, | ||||
| {"type":"AudioAnalyzeToneDetect","data":{"defaults":{"name":{"value":"new"}},"shortName":"tone","inputs":1,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png"}}, | {"type":"AudioAnalyzeToneDetect","data":{"defaults":{"name":{"value":"new"}},"shortName":"tone","inputs":1,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png"}}, | ||||
| {"type":"AudioAnalyzeGuitarTuner","data":{"defaults":{"name":{"value":"new"}},"shortName":"guitartuner","inputs":1,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png"}}, | |||||
| {"type":"AudioAnalyzeNoteFrequency","data":{"defaults":{"name":{"value":"new"}},"shortName":"notefreq","inputs":1,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png"}}, | |||||
| {"type":"AudioAnalyzePrint","data":{"defaults":{"name":{"value":"new"}},"shortName":"print","inputs":1,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png"}}, | {"type":"AudioAnalyzePrint","data":{"defaults":{"name":{"value":"new"}},"shortName":"print","inputs":1,"outputs":0,"category":"analyze-function","color":"#E6E0F8","icon":"arrow-in.png"}}, | ||||
| {"type":"AudioControlSGTL5000","data":{"defaults":{"name":{"value":"new"}},"shortName":"sgtl5000","inputs":0,"outputs":0,"category":"control-function","color":"#E6E0F8","icon":"arrow-in.png"}}, | {"type":"AudioControlSGTL5000","data":{"defaults":{"name":{"value":"new"}},"shortName":"sgtl5000","inputs":0,"outputs":0,"category":"control-function","color":"#E6E0F8","icon":"arrow-in.png"}}, | ||||
| {"type":"AudioControlWM8731","data":{"defaults":{"name":{"value":"new"}},"shortName":"wm8731","inputs":0,"outputs":0,"category":"control-function","color":"#E6E0F8","icon":"arrow-in.png"}}, | {"type":"AudioControlWM8731","data":{"defaults":{"name":{"value":"new"}},"shortName":"wm8731","inputs":0,"outputs":0,"category":"control-function","color":"#E6E0F8","icon":"arrow-in.png"}}, | ||||
| </div> | </div> | ||||
| </script> | </script> | ||||
| <script type="text/x-red" data-help-name="AudioAnalyzeGuitarTuner"> | |||||
| <script type="text/x-red" data-help-name="AudioAnalyzeNoteFrequency"> | |||||
| <h3>Summary</h3> | <h3>Summary</h3> | ||||
| <p>Detect with fairly good accuracy the fundamental frequencies f<sub>o</sub> from | |||||
| electric guitars and basses.</p> | |||||
| <p>Detect with fairly good accuracy the fundamental frequency f<sub>o</sub> | |||||
| of musical notes, such as electric guitar and bass.</p> | |||||
| <p>Written By Collin Duffy</p> | <p>Written By Collin Duffy</p> | ||||
| <h3>Audio Connections</h3> | <h3>Audio Connections</h3> | ||||
| <table class=doc align=center cellpadding=3> | <table class=doc align=center cellpadding=3> | ||||
| <p class=desc>Set the detection threshold, the amount of allowed uncertainty. | <p class=desc>Set the detection threshold, the amount of allowed uncertainty. | ||||
| </p> | </p> | ||||
| <h3>Examples</h3> | <h3>Examples</h3> | ||||
| <p class=exam>File > Examples > Audio > Analysis > GuitarTuneNotes | |||||
| <p class=exam>File > Examples > Audio > Analysis > NoteFrequency | |||||
| </p> | </p> | ||||
| <h3>Notes</h3> | <h3>Notes</h3> | ||||
| <p>The <a href="http://recherche.ircam.fr/equipes/pcm/cheveign/pss/2002_JASA_YIN.pdf">YIN algorithm</a> (PDF) | <p>The <a href="http://recherche.ircam.fr/equipes/pcm/cheveign/pss/2002_JASA_YIN.pdf">YIN algorithm</a> (PDF) | ||||
| <p>Within the code, AUDIO_GUITARTUNER_BLOCKS | <p>Within the code, AUDIO_GUITARTUNER_BLOCKS | ||||
| may be edited to control low frequency range. The default | may be edited to control low frequency range. The default | ||||
| (24) allows measurement down to 29.14 Hz, or B(flat)0.</p> | (24) allows measurement down to 29.14 Hz, or B(flat)0.</p> | ||||
| <p>TODO: The usable upper range of this object is not well known. | |||||
| Duff says "it should be good up to 1000Hz", but may have trouble | |||||
| at 4 kHz. Please <a href="https://forum.pjrc.com/threads/32252-Different-Range-FFT-Algorithm/page2">post feedback here</a>, ideally with audio clips for the NoteFrequency example.</p> | |||||
| <p>This object was contributed by Collin Duffy from his | <p>This object was contributed by Collin Duffy from his | ||||
| <a href="https://github.com/duff2013/AudioTuner">AudioTuner project</a>. | <a href="https://github.com/duff2013/AudioTuner">AudioTuner project</a>. | ||||
| Additional details and documentation may be found there.</p> | Additional details and documentation may be found there.</p> | ||||
| </script> | </script> | ||||
| <script type="text/x-red" data-template-name="AudioAnalyzeGuitarTuner"> | |||||
| <script type="text/x-red" data-template-name="AudioAnalyzeNoteFrequency"> | |||||
| <div class="form-row"> | <div class="form-row"> | ||||
| <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> | <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> | ||||
| <input type="text" id="node-input-name" placeholder="Name"> | <input type="text" id="node-input-name" placeholder="Name"> |