Table des matières:

Détecteur de notes de musique : 3 étapes
Détecteur de notes de musique : 3 étapes

Vidéo: Détecteur de notes de musique : 3 étapes

Vidéo: Détecteur de notes de musique : 3 étapes
Vidéo: Apprendre la musique || Solfège : les notes de musique 2024, Novembre
Anonim
Image
Image

Surprenez vos amis et votre famille avec ce projet qui détecte la note jouée par un instrument. Ce projet affichera la fréquence approximative ainsi que la note musicale jouée sur un clavier électronique, une application de piano ou tout autre instrument.

Des détails

Pour ce projet, la sortie analogique du détecteur de module sonore est envoyée à l'entrée analogique A0 de l'Arduino Uno. Le signal analogique est échantillonné et quantifié (numérisé). Le code d'autocorrélation, de pondération et d'accord est utilisé pour trouver la fréquence fondamentale en utilisant les 3 premières périodes. La fréquence fondamentale approximative est ensuite comparée aux fréquences des octaves 3, 4 et 5 pour déterminer la fréquence de note musicale la plus proche. Enfin, la note devinée pour la fréquence la plus proche est imprimée à l'écran.

Remarque: cette instructable se concentre uniquement sur la façon de construire le projet. Pour plus d'informations sur les détails et les justifications de conception, veuillez visiter ce lien: Plus d'informations

Fournitures

  • (1) Arduino Uno (ou Genuino Uno)
  • (1) Capteur de microphone DEVMO compatible avec le module de détection de son haute sensibilité
  • (1) Planche à pain sans soudure
  • (1) câble USB-A vers B
  • Fils de cavalier
  • Source musicale (piano, clavier ou application paino avec haut-parleurs)
  • (1) Ordinateur ou ordinateur portable

Étape 1: Construisez le matériel pour le détecteur de notes de musique

Configurer le détecteur de notes de musique
Configurer le détecteur de notes de musique

À l'aide d'un Arduino Uno, de fils de connexion, d'une carte d'essai sans soudure et d'un module de détection de son haute sensibilité à capteur de microphone DEVMO (ou similaire) construisez le circuit montré dans cette image

Étape 2: programmer le détecteur de notes de musique

Dans l'IDE Arduino, ajoutez le code suivant.

fichiergist1.txt

/*
Nom du fichier/du croquis: MusicalNoteDetector
N° de version: v1.0 Créé le 7 juin 2020
Auteur original: Clyde A. Lettsome, PhD, PE, MEM
Description: Ce code/croquis affiche la fréquence approximative ainsi que la note musicale jouée sur un clavier électronique ou une application de piano. Pour ce projet, la sortie analogique du
Le détecteur de module sonore est envoyé à l'entrée analogique A0 de l'Arduino Uno. Le signal analogique est échantillonné et quantifié (numérisé). Le code d'autocorrélation, de pondération et de réglage est utilisé pour
trouver la fréquence fondamentale en utilisant les 3 premières périodes. La fréquence fondamentale approximative est ensuite comparée aux fréquences des octaves 3, 4 et 5 pour déterminer la fréquence musicale la plus proche.
noter la fréquence. Enfin, la note devinée pour la fréquence la plus proche est imprimée à l'écran.
Licence: Ce programme est un logiciel libre; vous pouvez le redistribuer et/ou le modifier selon les termes de la GNU General Public License (GPL) version 3, ou toute version ultérieure
version de votre choix, telle que publiée par la Free Software Foundation.
Remarques: Copyright (c) 2020 par C. A. Lettsome Services, LLC
Pour plus d'informations, visitez
*/
#define SAMPLES 128 //Max 128 pour Arduino Uno.
#define SAMPLING_FREQUENCY 2048 //Fs = Basé sur Nyquist, doit être 2 fois la fréquence attendue la plus élevée.
#define OFFSETSAMPLES 40 //utilisé à des fins de calibrage
#define TUNER -3 // Ajuster jusqu'à ce que C3 soit 130.50
période d'échantillonnage à flotteur;
microsecondes longues non signées;
int X[ÉCHANTILLONS]; //créer un vecteur de taille SAMPLES pour contenir des valeurs réelles
float autoCorr[SAMPLES]; //créer un vecteur de taille SAMPLES pour contenir des valeurs imaginaires
float stockéNoteFreq[12] = {130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185, 196, 207.65, 220, 233.08, 246.94};
int sumOffSet = 0;
int offSet[OFFSETSAMPLES]; //créer un vecteur de décalage
int avgOffSet; //créer un vecteur de décalage
int i, k, periodEnd, periodBegin, period, ajusteur, noteLocation, octaveRange;
float maxValue, minValue;
somme longue;
seuil int = 0;
int numOfCycles = 0;
float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, total;
octet state_machine = 0;
int samplesPerPeriod = 0;
void setup()
{
Serial.begin(115200); //15200 Débit en bauds pour le moniteur série
}
boucle vide()
{
//*****************************************************************
//Section d'étalonnage
//*****************************************************************
Serial.println("Calabration. Veuillez ne jouer aucune note pendant la calibration.");
pour (i = 0; i < ÉCHANTILLONS DE DÉCALAGE; i++)
{
offSet = analogRead(0); // Lit la valeur de la broche analogique 0 (A0), la quantifie et l'enregistre en tant que terme réel.
//Série.println(offSet); // utilisez ceci pour ajuster le module de détection de son à environ la moitié ou 512 lorsqu'aucun son n'est joué.
sumOffSet = sumOffSet + offSet;
}
échantillonsParPériode = 0;
valeurmax = 0;
//*****************************************************************
//Préparez-vous à accepter l'entrée de A0
//*****************************************************************
avgOffSet = round(sumOffSet / OFFSETSAMPLES);
Serial.println("Compte à rebours.");
retard(1000); //pause pendant 1 seconde
Serial.println("3");
retard(1000); //pause pendant 1 seconde
Serial.println("2");
retard(1000); //pause pour 1
Serial.println("1");
retard(1000); //pause pendant 1 seconde
Serial.println("Joue ta note !");
retard (250); //pause pendant 1/4 de seconde pour le temps de réaction
//*****************************************************************
//Collecter des échantillons d'ÉCHANTILLONS de A0 avec la période d'échantillonnage de la période d'échantillonnage
//*****************************************************************
période d'échantillonnage = 1.0 / SAMPLING_FREQUENCY; //Période en microsecondes
pour (i = 0; i < ÉCHANTILLONS; i++)
{
microsecondes = micros(); // Renvoie le nombre de microsecondes depuis que la carte Arduino a commencé à exécuter le script actuel.
X = analogRead(0); // Lit la valeur de la broche analogique 0 (A0), la quantifie et l'enregistre en tant que terme réel.
/*temps d'attente restant entre les échantillons si nécessaire en secondes */
while (micros() < (microSeconds + (samplingPeriod * 1000000)))
{
//ne rien faire attendre
}
}
//*****************************************************************
//Fonction d'autocorrélation
//*****************************************************************
pour (i = 0; i < ÉCHANTILLONS; i++) //i=délai
{
somme = 0;
for (k = 0; k < SAMPLES - i; k++) //Faire correspondre le signal avec le signal retardé
{
somme = somme + (((X[k]) - avgOffSet) * ((X[k + i]) - avgOffSet)); //X[k] est le signal et X[k+i] est la version retardée
}
autoCorr = somme / ÉCHANTILLONS;
// Première machine d'état de détection de crête
si (state_machine==0 && i == 0)
{
seuil = autoCorr * 0,5;
state_machine = 1;
}
else if (state_machine == 1 && i>0 && thresh 0) //state_machine=1, trouver 1 période pour utiliser le premier cycle
{
maxValue = autoCorr;
}
else if (state_machine == 1&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
périodeDébut = i-1;
state_machine = 2;
nombreDeCycles = 1;
samplesPerPeriod = (periodBegin - 0);
période = échantillonsPerPériode;
ajusteur = TUNER+(50.04 * exp(-0.102 * échantillonsPerPeriod));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplesPerPeriod))-ajusteur; // f = fs/N
}
else if (state_machine == 2 && i>0 && thresh 0) //state_machine=2, trouver 2 périodes pour le 1er et le 2ème cycle
{
maxValue = autoCorr;
}
else if (state_machine == 2&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
finpériode = i-1;
state_machine = 3;
nombreDeCycles = 2;
samplesPerPeriod = (periodEnd - 0);
signalFrequency2 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-ajusteur; // f = (2*fs)/(2*N)
valeurmax = 0;
}
else if (state_machine == 3 && i>0 && thresh 0) //state_machine=3, trouver 3 périodes pour le 1er, 2e et 3e cycle
{
maxValue = autoCorr;
}
else if (state_machine == 3&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
finpériode = i-1;
state_machine = 4;
nombreDeCycles = 3;
samplesPerPeriod = (periodEnd - 0);
signalFrequency3 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-ajusteur; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
//Analyse des résultats
//*****************************************************************
if (samplesPerPeriod == 0)
{
Serial.println("Hmm….. Je ne suis pas sûr. Essayez-vous de me tromper?");
}
autre
{
//prépare la fonction de pondération
total = 0;
si (signalFréquence !=0)
{
total = 1;
}
if(signalFrequency2 !=0)
{
total = total + 2;
}
si (signalFréquence3 !=0)
{
total = total + 3;
}
//calculer la fréquence à l'aide de la fonction de pondération
signalFrequencyGuess = ((1/total) * signalFrequency) + ((2/total) * signalFrequency2) + ((3/total) * signalFrequency3); //trouver une fréquence pondérée
Serial.print("La note que vous avez jouée est approximativement ");
Serial.print(signalFrequencyGuess); //Imprime la conjecture de fréquence.
Serial.println(" Hz.");
//trouver la plage d'octave en fonction de la supposition
octaveRange=3;
while (!(signalFrequencyGuess >= storageNoteFreq[0]-7 && signalFrequencyGuess <= storageNoteFreq[11]+7))
{
pour(i = 0; i < 12; i++)
{
StockéNoteFreq = 2 * stockéNoteFreq;
}
octaveRange++;
}
//Trouve la note la plus proche
valeurmin = 10000000;
noteEmplacement = 0;
pour (i = 0; i < 12; i++)
{
if(minValue> abs(signalFrequencyGuess-storedNoteFreq))
{
minValue = abs(signalFrequencyGuess-storedNoteFreq);
noteEmplacement = i;
}
}
//Imprimer la note
Serial.print("Je pense que vous avez joué ");
if(noteEmplacement==0)
{
Serial.print("C");
}
else if(noteEmplacement==1)
{
Serial.print("C#");
}
else if(noteEmplacement==2)
{
Serial.print("D");
}
else if(noteEmplacement==3)
{
Serial.print("D#");
}
else if(noteEmplacement==4)
{
Serial.print("E");
}
else if(noteEmplacement==5)
{
Serial.print("F");
}
else if(noteEmplacement==6)
{
Serial.print("F#");
}
else if(noteEmplacement==7)
{
Serial.print("G");
}
else if(noteEmplacement==8)
{
Serial.print("G#");
}
else if(noteEmplacement==9)
{
Serial.print("A");
}
else if(noteEmplacement==10)
{
Serial.print("A#");
}
else if(noteEmplacement==11)
{
Serial.print("B");
}
Serial.println(OctaveRange);
}
//*****************************************************************
//Arrêtez ici. Appuyez sur le bouton de réinitialisation sur Arduino pour redémarrer
//*****************************************************************
tandis que (1);
}

voir rawgistfile1.txt hébergé avec ❤ par GitHub

Étape 3: Configurer le détecteur de notes de musique

Connectez l'Arduino Uno au PC avec le code écrit ou chargé dans l'IDE Arduino. Compilez et téléchargez le code sur l'Arduino. Placez le circuit à proximité de la source musicale. Remarque: Dans la vidéo d'introduction, j'utilise une application installée sur une tablette avec des haut-parleurs PC comme source de musique. Appuyez sur le bouton de réinitialisation de la carte Arduino, puis jouez une note sur la source musicale. Après quelques secondes, le détecteur de notes musicales affichera la note jouée et sa fréquence.

Conseillé: