Innholdsfortegnelse:

Musikknote -detektor: 3 trinn
Musikknote -detektor: 3 trinn

Video: Musikknote -detektor: 3 trinn

Video: Musikknote -detektor: 3 trinn
Video: Охотимся на оленей . Загоняем их в Кораль. Жизнь лесотундры Вынгаяхи 2. 2024, November
Anonim
Image
Image

Overrask dine venner og familie med dette prosjektet som oppdager noten som spilles av et instrument. Dette prosjektet vil vise den omtrentlige frekvensen så vel som den musikalske noten som spilles på et elektronisk tastatur, piano -app eller et annet instrument.

Detaljer

For dette prosjektet sendes den analoge utgangen fra lydmoduldetektoren til den analoge A0 -inngangen på Arduino Uno. Det analoge signalet blir samplet og kvantisert (digitalisert). Autokorrelasjon, vekting og tuningskode brukes til å finne grunnleggende frekvens ved bruk av de tre første periodene. Den omtrentlige grunnfrekvensen blir deretter sammenlignet med frekvenser i oktavene 3, 4 og 5 for å bestemme den nærmeste musikknotefrekvensen. Til slutt skrives det gjettede notatet for nærmeste frekvens ut på skjermen.

Merk: Denne instruksen fokuserer bare på hvordan du bygger prosjektet. For mer informasjon om detaljene og designbegrunnelser, vennligst besøk denne lenken: Mer informasjon

Rekvisita

  • (1) Arduino Uno (eller Genuino Uno)
  • (1) DEVMO mikrofonsensor Høysensitiv lyddeteksjonsmodul kompatibel
  • (1) Loddefritt brødbrett
  • (1) USB-A til B-kabel
  • Jumper ledninger
  • Musikalsk kilde (piano, tastatur eller paino -app med høyttalere)
  • (1) Datamaskin eller bærbar datamaskin

Trinn 1: Konstruer maskinvaren for detektoren for musikknoter

Sett opp musikknotaldetektoren
Sett opp musikknotaldetektoren

Ved hjelp av en Arduino Uno konstruerer tilkoblingskabler, et loddfritt brødbrett og en DEVMO -mikrofonsensor lydsensormodul (eller lignende) for høy følsomhet (eller lignende) kretsen vist i dette bildet

Trinn 2: Programmer Musical Note Detector

Legg til følgende kode i Arduino IDE.

gistfile1.txt

/*
Fil/skisse navn: MusicalNoteDetector
Versjonsnummer: v1.0 Opprettet 7. juni 2020
Opprinnelig forfatter: Clyde A. Lettsome, PhD, PE, MEM
Beskrivelse: Denne koden/skissen viser omtrentlig frekvens så vel som musikknoten spilt på et elektronisk tastatur eller pianoapp. For dette prosjektet er den analoge utgangen fra
lydmodul detektor sendes til A0 analog inngang på Arduino Uno. Det analoge signalet blir samplet og kvantisert (digitalisert). Autokorrelasjon, vekting og tuningskode brukes til
finne grunnleggende frekvens ved hjelp av de tre første periodene. Den omtrentlige grunnfrekvensen blir deretter sammenlignet med frekvenser i oktavene 3, 4 og 5 for å bestemme den nærmeste musikalen
merk frekvens. Til slutt skrives det gjettede notatet for nærmeste frekvens ut på skjermen.
Lisens: Dette programmet er gratis programvare; du kan omfordele den og/eller endre den under vilkårene i GNU General Public License (GPL) versjon 3, eller senere
versjon av ditt valg, som utgitt av Free Software Foundation.
Merknader: Copyright (c) 2020 av C. A. Lettsome Services, LLC
For mer informasjon, besøk https://clydelettsome.com/blog 2020/06/07/my-weekend-project-musical-note-detector-using-an-arduino/
*/
#define PRØVER 128 // Maks 128 for Arduino Uno.
#define SAMPLING_FREQUENCY 2048 // Fs = Basert på Nyquist, må være 2 ganger den høyeste forventede frekvensen.
#define OFFSETSAMPLES 40 // brukt til kalibreringsformål
#define TUNER -3 // Juster til C3 er 130,50
float samplingPeriod;
usignerte lange microSeconds;
int X [PRØVER]; // Lag en vektor av størrelsesprøver for å holde reelle verdier
float autoCorr [PRØVER]; // lag en vektor i størrelse PRØVER for å holde imaginære verdier
float lagretNoteFreq [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]; // lage en offsetvektor
int avgOffSet; // lage en offsetvektor
int i, k, periodEnd, periodBegin, period, justerer, noteLocation, octaveRange;
float maxValue, minValue;
lang sum;
int treske = 0;
int numOfCycles = 0;
float signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, total;
byte state_machine = 0;
int samplesPerPeriod = 0;
ugyldig oppsett ()
{
Serial.begin (115200); // 115200 Baud rate for Serial Monitor
}
hulrom ()
{
//*****************************************************************
// Kalibreringsseksjon
//*****************************************************************
Serial.println ("Kalibrering. Vennligst ikke spill noen noter under kalibrering.");
for (i = 0; i <OFFSETSAMPLES; i ++)
{
offSet = analogRead (0); // Leser verdien fra analog pin 0 (A0), kvantiser den og lagre den som et reelt begrep.
//Serial.println(offSet ); // bruk denne til å justere lyddeteksjonsmodulen til omtrent halvparten eller 512 når ingen lyd spilles.
sumOffSet = sumOffSet + offSet ;
}
samplesPerPeriod = 0;
maxValue = 0;
//*****************************************************************
// Forbered deg på å godta innspill fra A0
//*****************************************************************
avgOffSet = round (sumOffSet / OFFSETSAMPLES);
Serial.println ("Nedtelling.");
forsinkelse (1000); // pause i 1 sekund
Serial.println ("3");
forsinkelse (1000); // pause i 1 sekund
Serial.println ("2");
forsinkelse (1000); // pause for 1
Serial.println ("1");
forsinkelse (1000); // pause i 1 sekund
Serial.println ("Spill notatet ditt!");
forsinkelse (250); // pause i 1/4 sekund for reaksjonstid
//*****************************************************************
// Samle PRØVER prøver fra A0 med prøveperiode med prøvetakingstid
//*****************************************************************
samplingPeriod = 1.0 / SAMPLING_FREQUENCY; // Periode i mikrosekunder
for (i = 0; i <SAMPLES; i ++)
{
microSeconds = micros (); // Returnerer antall mikrosekunder siden Arduino -kortet begynte å kjøre det nåværende skriptet.
X = analogRead (0); // Leser verdien fra analog pin 0 (A0), kvantiser den og lagre den som et reelt begrep.
/ *gjenværende ventetid mellom prøver om nødvendig i sekunder */
mens (micros () <(microSeconds + (samplingPeriod * 1000000)))
{
// ikke gjør noe bare vent
}
}
//*****************************************************************
// Autokorrelasjonsfunksjon
//*****************************************************************
for (i = 0; i <SAMPLES; i ++) // i = forsinkelse
{
sum = 0;
for (k = 0; k <SAMPLES - i; k ++) // Match signal med forsinket signal
{
sum = sum + (((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] er signalet og X [k+i] er den forsinkede versjonen
}
autoCorr = sum / PRØVER;
// First Peak Detect State Machine
hvis (state_machine == 0 && i == 0)
{
tersk = autoCorr * 0,5;
state_machine = 1;
}
ellers hvis (state_machine == 1 && i> 0 && thresh 0) // state_machine = 1, finn 1 periode for bruk av første syklus
{
maxValue = autoCorr ;
}
ellers hvis (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);
periode = samplesPerPeriod;
justerer = TUNER+(50.04 * eksp (-0.102 * samplesPerPeriod));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplesPerPeriod))-justerer; // f = fs/N
}
ellers hvis (state_machine == 2 && i> 0 && thresh 0) // state_machine = 2, finn 2 perioder for 1. og 2. syklus
{
maxValue = autoCorr ;
}
annet hvis (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))-justerer; // f = (2*fs)/(2*N)
maxValue = 0;
}
ellers hvis (state_machine == 3 && i> 0 && thresh 0) // state_machine = 3, finn 3 perioder for 1., 2. og 3. syklus
{
maxValue = autoCorr ;
}
ellers hvis (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))-justerer; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
// Resultatanalyse
//*****************************************************************
hvis (samplesPerPeriod == 0)
{
Serial.println ("Hmm ….. Jeg er ikke sikker. Prøver du å lure meg?");
}
ellers
{
// forberede vektingsfunksjonen
totalt = 0;
hvis (signalFrequency! = 0)
{
totalt = 1;
}
hvis (signalFrequency2! = 0)
{
totalt = totalt + 2;
}
hvis (signalFrequency3! = 0)
{
totalt = totalt + 3;
}
// beregne frekvensen ved hjelp av vektingsfunksjonen
signalFrequencyGuess = ((1/totalt) * signalFrequency) + ((2/totalt) * signalFrequency2) + ((3/totalt) * signalFrequency3); // finn en vektet frekvens
Serial.print ("Notatet du spilte er omtrent");
Serial.print (signalFrequencyGuess); // Skriv ut frekvensgjetningen.
Serial.println ("Hz.");
// finn oktavområdet basert på gjetningen
octaveRange = 3;
while (! (signalFrequencyGuess> = storedNoteFreq [0] -7 && signalFrequencyGuess <= storageNoteFreq [11] +7))
{
for (i = 0; i <12; i ++)
{
lagretNoteFreq = 2 * lagretNoteFreq ;
}
octaveRange ++;
}
// Finn det nærmeste notatet
minValue = 10000000;
noteLocation = 0;
for (i = 0; i <12; i ++)
{
if (minValue> abs (signalFrequencyGuess-storedNoteFreq ))
{
minValue = abs (signalFrequencyGuess-lagretNoteFreq );
noteLocation = i;
}
}
// Skriv ut notatet
Serial.print ("Jeg tror du spilte");
hvis (noteLocation == 0)
{
Serial.print ("C");
}
annet hvis (noteLocation == 1)
{
Serial.print ("C#");
}
annet hvis (noteLocation == 2)
{
Serial.print ("D");
}
annet hvis (noteLocation == 3)
{
Serial.print ("D#");
}
annet hvis (noteLocation == 4)
{
Serial.print ("E");
}
annet hvis (noteLocation == 5)
{
Serial.print ("F");
}
annet hvis (noteLocation == 6)
{
Serial.print ("F#");
}
annet hvis (noteLocation == 7)
{
Serial.print ("G");
}
annet hvis (noteLocation == 8)
{
Serial.print ("G#");
}
annet hvis (noteLocation == 9)
{
Serial.print ("A");
}
annet hvis (noteLocation == 10)
{
Serial.print ("A#");
}
annet hvis (noteLocation == 11)
{
Serial.print ("B");
}
Serial.println (octaveRange);
}
//*****************************************************************
//Stopp her. Trykk på reset -knappen på Arduino for å starte på nytt
//*****************************************************************
mens (1);
}

se rawgistfile1.txt hostet av ❤ av GitHub

Trinn 3: Konfigurer Musical Note Detector

Koble Arduino Uno til PC -en med koden skrevet eller lastet inn i Arduino IDE. Kompiler og last opp koden til Arduino. Plasser kretsen nær musikkilden. Merk: I introduksjonsvideoen bruker jeg en app installert på nettbrettet sammen med PC -høyttalere som min musikkilde. Trykk på tilbakestillingsknappen på Arduino Board og spill deretter et notat om musikkilden. Etter noen få sekunder viser Musical Note Detector notatet som spilles og frekvensen.

Anbefalt: