#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"> |