Innehållsförteckning:

Musical Note Detector: 3 steg
Musical Note Detector: 3 steg

Video: Musical Note Detector: 3 steg

Video: Musical Note Detector: 3 steg
Video: XXXtantation - Hope (Concert) | #xxxtentacion #hope #aesthetic #concert 2024, November
Anonim
Image
Image

Förundra dina vänner och familj med det här projektet som upptäcker noten som spelas av ett instrument. Detta projekt kommer att visa den ungefärliga frekvensen samt musiknoten som spelas på ett elektroniskt tangentbord, pianoapp eller något annat instrument.

Detaljer

För detta projekt skickas den analoga utsignalen från ljudmoduldetektorn till A0 analog ingång på Arduino Uno. Den analoga signalen samplas och kvantiseras (digitaliseras). Autokorrelation, viktning och inställningskod används för att hitta grundläggande frekvens med hjälp av de tre första perioderna. Den ungefärliga grundfrekvensen jämförs sedan med frekvenser i oktaverna 3, 4 och 5 för att bestämma den närmaste musikfrekvensen. Slutligen skrivs den gissade anteckningen för närmaste frekvens ut på skärmen.

Obs: Denna instruktion fokuserar bara på hur man bygger projektet. För mer information om detaljerna och designmotiveringar, besök denna länk: Mer information

Tillbehör

  • (1) Arduino Uno (eller Genuino Uno)
  • (1) DEVMO mikrofonsensor Högkänslig ljuddetekteringsmodul kompatibel
  • (1) Lödfritt brödbräda
  • (1) USB-A till B-kabel
  • Bygelkablar
  • Musikalisk källa (piano, tangentbord eller paino -app med högtalare)
  • (1) Dator eller bärbar dator

Steg 1: Konstruera hårdvaran för musiknotaldetektorn

Ställ in Musical Note Detector
Ställ in Musical Note Detector

Med hjälp av en Arduino Uno konstruerar anslutningskablar, en lödlös brödbräda och en DEVMO mikrofonsensor högkänslig ljuddetekteringsmodul (eller liknande) kretsen som visas i den här bilden

Steg 2: Programmera Musical Note Detector

Lägg till följande kod i Arduino IDE.

gistfile1.txt

/*
Fil-/skissnamn: MusicalNoteDetector
Version nr: v1.0 Skapad 7 juni 2020
Originalförfattare: Clyde A. Lettsome, PhD, PE, MEM
Beskrivning: Denna kod/skiss visar ungefärlig frekvens samt musiknoten som spelas på ett elektroniskt tangentbord eller en pianoapp. För detta projekt, den analoga utsignalen från
ljudmodul detektor skickas till A0 analog ingång på Arduino Uno. Den analoga signalen samplas och kvantiseras (digitaliseras). Autokorrelation, viktning och inställningskod används för att
hitta grundfrekvensen med de tre första perioderna. Den ungefärliga grundfrekvensen jämförs sedan med frekvenser i oktaverna 3, 4 och 5 för att bestämma den närmaste musikalen
notera frekvens. Slutligen skrivs den gissade anteckningen för närmaste frekvens ut på skärmen.
Licens: Detta program är gratis programvara; du kan omfördela den och/eller ändra den enligt villkoren i GNU General Public License (GPL) version 3, eller senare
version av ditt val, som publicerats av Free Software Foundation.
Anmärkningar: Copyright (c) 2020 av C. A. Lettsome Services, LLC
För mer information besök https://clydelettsome.com/blog 2020/06/07/my-weekend-project-musical-note-detector-using-an-arduino/
*/
#define PROV 128 /Max 128 för Arduino Uno.
#define SAMPLING_FREQUENCY 2048 // Fs = Baserat på Nyquist, måste vara 2 gånger den högsta förväntade frekvensen.
#define OFFSETSAMPLES 40 // används för kalibrering
#define TUNER -3 // Justera tills C3 är 130,50
float samplingPeriod;
osignerade långa microSeconds;
int X [PROV]; // skapa en vektor i storleksprover för att hålla verkliga värden
float autoCorr [PROV]; // skapa en vektor av storleksprover för att hålla imaginära värden
float lagradNoteFreq [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]; // skapa offsetvektor
int avgOffSet; // skapa förskjutningsvektor
int i, k, periodEnd, periodBegin, period, justerare, noteLocation, octaveRange;
float maxValue, minValue;
lång summa;
int tröskan = 0;
int numOfCycles = 0;
float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, total;
byte state_machine = 0;
int samplesPerPeriod = 0;
void setup ()
{
Serial.begin (115200); // 115200 Baudhastighet för seriemonitorn
}
void loop ()
{
//*****************************************************************
// Kalibreringssektion
//*****************************************************************
Serial.println ("Kalabrering. Spela inga noter under kalibrering.");
för (i = 0; i <OFFSETSAMPLES; i ++)
{
offSet = analogRead (0); // Läser värdet från analog pin 0 (A0), kvantifierar det och sparar det som en verklig term.
//Serial.println(offSet [ii]); // använd detta för att justera ljuddetekteringsmodulen till ungefär hälften eller 512 när inget ljud spelas.
sumOffSet = sumOffSet + offSet ;
}
samplesPerPeriod = 0;
maxValue = 0;
//*****************************************************************
// Förbered dig på att acceptera input från A0
//*****************************************************************
avgOffSet = round (sumOffSet / OFFSETSAMPLES);
Serial.println ("Räknar ner.");
fördröjning (1000); // paus i 1 sekund
Serial.println ("3");
fördröjning (1000); // paus i 1 sekund
Serial.println ("2");
fördröjning (1000); // paus för 1
Serial.println ("1");
fördröjning (1000); // paus i 1 sekund
Serial.println ("Spela din anteckning!");
fördröjning (250); // paus i 1/4 sekund för reaktionstid
//*****************************************************************
// Samla PROV från A0 med provperiod för provtagning
//*****************************************************************
samplingPeriod = 1.0 / SAMPLING_FREQUENCY; // Period i mikrosekunder
för (i = 0; i <PROV; i ++)
{
microSeconds = micros (); // Returnerar antalet mikrosekunder sedan Arduino -kortet började köra det aktuella skriptet.
X = analogRead (0); // Läser värdet från analog pin 0 (A0), kvantifierar det och sparar det som en verklig term.
/ *återstående väntetid mellan proverna om det behövs i sekunder */
medan (micros () <(microSeconds + (samplingPeriod * 1000000)))
{
// gör ingenting bara vänta
}
}
//*****************************************************************
// Autokorrelationsfunktion
//*****************************************************************
för (i = 0; i <PROV; i ++) // i = fördröjning
{
summa = 0;
för (k = 0; k <PROV - i; k ++) // Matcha signal med fördröjd signal
{
summa = summa + (((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] är signalen och X [k+i] är den fördröjda versionen
}
autoCorr = summa / PROV;
// First Peak Detect State Machine
if (state_machine == 0 && i == 0)
{
tröskan = autoCorr * 0,5;
state_machine = 1;
}
annars om (state_machine == 1 && i> 0 && thresh 0) // state_machine = 1, hitta 1 period för att använda första cykeln
{
maxValue = autoCorr ;
}
annars om (state_machine == 1 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodBegin = i-1;
state_machine = 2;
numOfCycles = 1;
samplesPerPeriod = (periodBegin - 0);
period = samplesPerPeriod;
justerare = TUNER+(50.04 * exp (-0.102 * samplesPerPeriod));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplesPerPeriod))-justerare; // f = fs/N
}
annars om (state_machine == 2 && i> 0 && thresh 0) // state_machine = 2, hitta 2 perioder för första och andra cykeln
{
maxValue = autoCorr ;
}
annars om (state_machine == 2 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
state_machine = 3;
numOfCycles = 2;
samplesPerPeriod = (periodEnd - 0);
signalFrequency2 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-justerare; // f = (2*fs)/(2*N)
maxValue = 0;
}
annars om (state_machine == 3 && i> 0 && thresh 0) // state_machine = 3, hitta 3 perioder för 1: a, 2: a och 3: e cykeln
{
maxValue = autoCorr ;
}
annars om (state_machine == 3 && i> 0 && thresh <autoCorr [i-1] && maxValue == autoCorr [i-1] && (autoCorr -autoCorr [i-1]) <= 0)
{
periodEnd = i-1;
state_machine = 4;
numOfCycles = 3;
samplesPerPeriod = (periodEnd - 0);
signalFrequency3 = ((numOfCycles*SAMPLING_FREQUENCY) / (samplesPerPeriod))-justerare; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
// Resultatanalys
//*****************************************************************
if (samplesPerPeriod == 0)
{
Serial.println ("Hmm ….. Jag är inte säker. Försöker du lura mig?");
}
annan
{
// förbereda viktningsfunktionen
totalt = 0;
if (signalFrequency! = 0)
{
totalt = 1;
}
if (signalFrequency2! = 0)
{
totalt = totalt + 2;
}
if (signalFrequency3! = 0)
{
totalt = totalt + 3;
}
// beräkna frekvensen med hjälp av viktningsfunktionen
signalFrequencyGuess = ((1/totalt) * signalFrequency) + ((2/totalt) * signalFrequency2) + ((3/totalt) * signalFrequency3); // hitta en vägd frekvens
Serial.print ("Noten du spelade är ungefär");
Serial.print (signalFrequencyGuess); // Skriv ut frekvensgissningen.
Serial.println ("Hz.");
// hitta oktavintervall baserat på gissningen
octaveRange = 3;
medan (! (signalFrequencyGuess> = storedNoteFreq [0] -7 && signalFrequencyGuess <= storageNoteFreq [11] +7))
{
för (i = 0; i <12; i ++)
{
lagradNoteFreq = 2 * lagradNoteFreq ;
}
octaveRange ++;
}
// Hitta närmaste lapp
minVärde = 10000000;
noteLocation = 0;
för (i = 0; i <12; i ++)
{
if (minValue> abs (signalFrequencyGuess-storedNoteFreq ))
{
minValue = abs (signalFrequencyGuess-storedNoteFreq );
noteLocation = i;
}
}
// Skriv ut lappen
Serial.print ("Jag tror att du spelade");
if (noteLocation == 0)
{
Serial.print ("C");
}
annars om (noteLocation == 1)
{
Serial.print ("C#");
}
annars om (noteLocation == 2)
{
Serial.print ("D");
}
annars om (noteLocation == 3)
{
Serial.print ("D#");
}
annars om (noteLocation == 4)
{
Serial.print ("E");
}
annars om (noteLocation == 5)
{
Serial.print ("F");
}
annars om (noteLocation == 6)
{
Serial.print ("F#");
}
annars om (noteLocation == 7)
{
Serial.print ("G");
}
annars om (noteLocation == 8)
{
Serial.print ("G#");
}
annars om (noteLocation == 9)
{
Serial.print ("A");
}
annars om (noteLocation == 10)
{
Serial.print ("A#");
}
annars om (noteLocation == 11)
{
Serial.print ("B");
}
Serial.println (octaveRange);
}
//*****************************************************************
//Stanna här. Tryck på återställningsknappen på Arduino för att starta om
//*****************************************************************
medan (1);
}

visa rawgistfile1.txt värd med ❤ av GitHub

Steg 3: Ställ in Musical Note Detector

Anslut Arduino Uno till datorn med koden skriven eller laddad i Arduino IDE. Kompilera och ladda upp koden till Arduino. Placera kretsen nära musikkällan. Obs! I introduktionsvideon använder jag en app installerad på surfplattan tillsammans med PC -högtalare som min musikkälla. Tryck på återställningsknappen på Arduino Board och spela sedan en anteckning om musikkällan. Efter några sekunder visar Musical Note Detector noten som spelas och dess frekvens.

Rekommenderad: