Inhaltsverzeichnis:

Musiknoten-Detektor - Gunook
Musiknoten-Detektor - Gunook

Video: Musiknoten-Detektor - Gunook

Video: Musiknoten-Detektor - Gunook
Video: SHANAN Company Introduction 2024, November
Anonim
Image
Image

Überraschen Sie Ihre Freunde und Familie mit diesem Projekt, das die von einem Instrument gespielte Note erkennt. Dieses Projekt zeigt die ungefähre Frequenz sowie die Musiknote an, die auf einer elektronischen Tastatur, einer Klavier-App oder einem anderen Instrument gespielt wird.

Einzelheiten

Für dieses Projekt wird der analoge Ausgang des Soundmodul-Detektors an den A0-Analogeingang des Arduino Uno gesendet. Das analoge Signal wird abgetastet und quantisiert (digitalisiert). Autokorrelation, Gewichtung und Abstimmungscode werden verwendet, um die Grundfrequenz unter Verwendung der ersten 3 Perioden zu finden. Die ungefähre Grundfrequenz wird dann mit Frequenzen in den Oktaven 3, 4 und 5 verglichen, um die nächste Musiktonfrequenz zu bestimmen. Schließlich wird die erratene Note für die nächste Frequenz auf dem Bildschirm gedruckt.

Hinweis: Dieses anweisbare konzentriert sich nur darauf, wie das Projekt erstellt wird. Für weitere Informationen zu den Details und Design-Begründungen besuchen Sie bitte diesen Link: Weitere Informationen

Lieferungen

  • (1) Arduino Uno (oder Genuino Uno)
  • (1) Kompatibel mit DEVMO-Mikrofonsensor mit hochempfindlichem Schallerkennungsmodul
  • (1) lötfreies Steckbrett
  • (1) USB-A-zu-B-Kabel
  • Überbrückungsdrähte
  • Musikquelle (Klavier, Keyboard oder Paino-App mit Lautsprechern)
  • (1) Computer oder Laptop

Schritt 1: Konstruieren Sie die Hardware für den Musiknotendetektor

Einrichten des Musiknotendetektors
Einrichten des Musiknotendetektors

Mit einem Arduino Uno, Verbindungsdrähten, einem lötfreien Steckbrett und einem DEVMO-Mikrofonsensor-Sounderkennungsmodul (oder ähnlichem) bauen Sie die in diesem Bild gezeigte Schaltung auf

Schritt 2: Programmieren Sie den Musiknotendetektor

Fügen Sie in der Arduino-IDE den folgenden Code hinzu.

gistfile1.txt

/*
Datei-/Skizzenname: MusicalNoteDetector
Versions-Nr.: v1.0 Erstellt am 7. Juni 2020
Originalautor: Clyde A. Lettsome, PhD, PE, MEM
Beschreibung: Dieser Code/diese Skizze zeigt die ungefähre Frequenz sowie die Musiknote an, die auf einer elektronischen Tastatur oder einer Klavier-App gespielt wird. Für dieses Projekt ist der Analogausgang des
Der Soundmodul-Detektor wird an den A0-Analogeingang des Arduino Uno gesendet. Das analoge Signal wird abgetastet und quantisiert (digitalisiert). Autokorrelation, Gewichtung und Tuning-Code wird verwendet, um
Finden Sie die Grundfrequenz mit den ersten 3 Perioden. Die ungefähre Grundfrequenz wird dann mit Frequenzen in den Oktaven 3, 4 und 5 verglichen, um das nächste musikalische
Frequenz beachten. Schließlich wird die erratene Note für die nächste Frequenz auf dem Bildschirm gedruckt.
Lizenz: Dieses Programm ist freie Software; Sie können es unter den Bedingungen der GNU General Public License (GPL) Version 3 oder einer späteren Version weitergeben und/oder ändern
Version Ihrer Wahl, wie von der Free Software Foundation veröffentlicht.
Hinweise: Copyright (c) 2020 von C. A. Lettsome Services, LLC
Weitere Informationen finden Sie unter
*/
#define SAMPLES 128 // Max 128 für Arduino Uno.
#define SAMPLING_FREQUENCY 2048 //Fs = Basierend auf Nyquist, muss das Doppelte der höchsten erwarteten Frequenz sein.
#define OFFSETSAMPLES 40 //zu Kalibrierzwecken verwendet
#define TUNER -3 //Anpassen bis C3 130,50. beträgt
Float-Sampling-Periode;
lange Mikrosekunden ohne Vorzeichen;
int X[MUSTER]; // Vektor der Größe SAMPLES erstellen, um reale Werte zu halten
float autoCorr[SAMPLES]; //Erzeuge einen Vektor der Größe SAMPLES, um imaginäre Werte zu halten
float StoredNoteFreq[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]; // Offset-Vektor erstellen
int avgOffSet; // Offset-Vektor erstellen
int i, k, periodEnd, periodBegin, period, adjuster, noteLocation, octaveRange;
float maxValue, minValue;
lange Summe;
int-Schwellwert = 0;
int numOfCycles = 0;
float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, total;
Byte state_machine = 0;
int samplePeriod = 0;
Void-Setup ()
{
Serial.begin(115200); //115200 Baudrate für den seriellen Monitor
}
Leere Schleife ()
{
//*****************************************************************
//Kalibrierungsabschnitt
//*****************************************************************
Serial.println ("Kalibrieren. Bitte spielen Sie während der Kalibrierung keine Noten.");
für (i = 0; i < OFFSETSAMPLES; i++)
{
offSet = analogRead(0); // Liest den Wert vom analogen Pin 0 (A0), quantisiere ihn und speichere ihn als realen Ausdruck.
//Seriell.println(offSet); // Verwenden Sie dies, um das Tonerkennungsmodul auf ungefähr die Hälfte oder 512 einzustellen, wenn kein Ton wiedergegeben wird.
sumOffSet = sumOffSet + offSet;
}
SamplePeriode = 0;
maxWert = 0;
//*****************************************************************
// Bereiten Sie sich darauf vor, die Eingabe von A0 zu akzeptieren
//*****************************************************************
avgOffSet = round(sumOffSet / OFFSETSAMPLES);
Serial.println ("Countdown.");
Verzögerung (1000); // 1 Sekunde pausieren
Serial.println("3");
Verzögerung (1000); // 1 Sekunde pausieren
Serial.println("2");
Verzögerung (1000); // Pause für 1
Serial.println("1");
Verzögerung (1000); // 1 Sekunde pausieren
Serial.println ("Spielen Sie Ihre Notiz ab!");
Verzögerung (250); // Pause für 1/4 Sekunde für Reaktionszeit
//*****************************************************************
// Sammle SAMPLES-Samples von A0 mit der Sample-Periode von SamplingPeriod
//*****************************************************************
SamplingPeriod = 1.0 / SAMPLING_FREQUENCY; //Zeitraum in Mikrosekunden
für (i = 0; i < PROBEN; i++)
{
microSekunden = micros(); // Gibt die Anzahl der Mikrosekunden zurück, seit das Arduino-Board mit der Ausführung des aktuellen Skripts begonnen hat.
X = analogRead(0); // Liest den Wert vom analogen Pin 0 (A0), quantisiere ihn und speichere ihn als realen Ausdruck.
/*verbleibende Wartezeit zwischen den Proben ggf. in Sekunden */
while (micros() < (microSeconds + (samplingPeriod * 1000000)))
{
// Nichts tun, nur warten
}
}
//*****************************************************************
//Autokorrelationsfunktion
//*****************************************************************
für (i = 0; i < SAMPLES; i++) //i=Verzögerung
{
Summe = 0;
for (k = 0; k < SAMPLES - i; k++) // Match-Signal mit verzögertem Signal
{
Summe = Summe + (((X[k]) – avgOffSet) * ((X[k + i]) – avgOffSet)); //X[k] ist das Signal und X[k+i] ist die verzögerte Version
}
autoCorr = Summe / SAMPLES;
// Erste Peak-Erkennungs-Zustandsmaschine
if (state_machine==0 && i == 0)
{
Schwelle = autoCorr * 0,5;
Zustandsmaschine = 1;
}
else if (state_machine == 1 && i>0 && thresh 0) //state_machine=1, finde 1 Periode für die Verwendung des ersten Zyklus
{
maxValue = autoCorr;
}
else if (state_machine == 1&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
periodBegin = i-1;
Zustandsmaschine = 2;
AnzahlZyklen = 1;
SamplesPeriod = (PeriodeBegin - 0);
Periode = SamplePeriod;
Einsteller = TUNER + (50,04 * exp(-0,102 * SamplesPerPeriod));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplesPeriod))-Einsteller; // f = fs/N
}
else if (state_machine == 2 && i>0 && thresh 0) //state_machine=2, finde 2 Perioden für den 1. und 2. Zyklus
{
maxValue = autoCorr;
}
else if (state_machine == 2&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
periodEnd = i-1;
Zustandsmaschine = 3;
AnzahlZyklen = 2;
SamplesPeriod = (PeriodeEnde - 0);
signalFrequency2 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-Einsteller; // f = (2*fs)/(2*N)
maxWert = 0;
}
else if (state_machine == 3 && i>0 && thresh 0) //state_machine=3, finde 3 Perioden für den 1., 2. und 3. Zyklus
{
maxValue = autoCorr;
}
else if (state_machine == 3&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
periodEnd = i-1;
Zustandsmaschine = 4;
AnzahlZyklen = 3;
SamplesPeriod = (PeriodeEnde - 0);
signalFrequency3 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-Einsteller; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
//Ergebnisanalyse
//*****************************************************************
if (samplesPerPeriod == 0)
{
Serial.println("Hmm….. Ich bin mir nicht sicher. Versuchst du mich auszutricksen?");
}
anders
{
// Bereiten Sie die Gewichtungsfunktion vor
gesamt = 0;
if (signalFrequenz !=0)
{
gesamt = 1;
}
if(signalFrequenz2 !=0)
{
gesamt = gesamt + 2;
}
if (signalFrequenz3 !=0)
{
gesamt = gesamt + 3;
}
// Berechnen Sie die Frequenz mit der Gewichtungsfunktion
SignalFrequencyGuess = ((1/Gesamt) * SignalFrequenz) + ((2/Gesamt) * SignalFrequenz2) + ((3/Gesamt) * SignalFrequenz3); // eine gewichtete Frequenz finden
Serial.print ("Die Note, die Sie gespielt haben, ist ungefähr");
Serial.print (signalFrequencyGuess); //Drucken Sie die Frequenzschätzung.
Serial.println("Hz.");
// Finden Sie den Oktavbereich basierend auf der Schätzung
Oktavbereich=3;
while (!(signalFrequencyGuess >= savedNoteFreq[0]-7 && signalFrequencyGuess <= savedNoteFreq[11]+7))
{
für(i = 0; i < 12; i++)
{
gespeicherteNotizFreq = 2 * gespeicherteNotizFreq;
}
octaveRange++;
}
//Finde die nächste Notiz
minWert = 10000000;
noteLocation = 0;
für (i = 0; i < 12; i++)
{
if(minValue> abs(signalFrequencyGuess-storedNoteFreq))
{
minValue = abs(signalFrequencyGuess-storedNoteFreq);
noteLocation = i;
}
}
//Drucken Sie die Notiz
Serial.print ("Ich glaube, du hast gespielt");
if(AnmerkungStandort==0)
{
Serial.print ("C");
}
sonst if(noteLocation==1)
{
Serial.print("C#");
}
sonst if(noteLocation==2)
{
Serial.print ("D");
}
sonst if(noteLocation==3)
{
Serial.print ("D #");
}
sonst if(noteLocation==4)
{
Serial.print ("E");
}
sonst if(noteLocation==5)
{
Serial.print ("F");
}
sonst if(noteLocation==6)
{
Serial.print ("F #");
}
sonst if(noteLocation==7)
{
Serial.print ("G");
}
sonst if(noteLocation==8)
{
Serial.print ("G #");
}
sonst if(noteLocation==9)
{
Serial.print ("A");
}
sonst if(noteLocation==10)
{
Serial.print ("A #");
}
sonst if(noteLocation==11)
{
Serial.print ("B");
}
Serial.println (OktaveRange);
}
//*****************************************************************
//Stoppe hier. Drücken Sie die Reset-Taste auf Arduino, um neu zu starten
//*****************************************************************
während (1);
}

rawgistfile1.txt anzeigen, gehostet mit ❤ von GitHub

Schritt 3: Einrichten des Musiknotendetektors

Verbinden Sie das Arduino Uno mit dem PC mit dem in der Arduino IDE geschriebenen oder geladenen Code. Kompilieren Sie den Code und laden Sie ihn auf den Arduino hoch. Platzieren Sie den Stromkreis in der Nähe der Musikquelle. Hinweis: Im Einführungsvideo verwende ich als Musikquelle eine auf dem Tablet installierte App in Verbindung mit PC-Lautsprechern. Drücken Sie die Reset-Taste auf dem Arduino Board und spielen Sie dann eine Note auf der Musikquelle. Nach einigen Sekunden zeigt der Musiknotendetektor die gespielte Note und ihre Frequenz an.