Spisu treści:

Wykrywacz nut: 3 kroki
Wykrywacz nut: 3 kroki

Wideo: Wykrywacz nut: 3 kroki

Wideo: Wykrywacz nut: 3 kroki
Wideo: ЮВЕЛИР с НУЛЯ|3-й ВЫПУСК| Как стать ювелиром 2024, Listopad
Anonim
Image
Image

Zaskocz swoich przyjaciół i rodzinę dzięki temu projektowi, który wykrywa nutę graną przez instrument. Ten projekt wyświetli przybliżoną częstotliwość, a także nutę graną na klawiaturze elektronicznej, aplikacji na fortepian lub dowolnym innym instrumencie.

Detale

W tym projekcie wyjście analogowe z detektora modułu dźwiękowego jest przesyłane do wejścia analogowego A0 Arduino Uno. Sygnał analogowy jest próbkowany i kwantyzowany (cyfryzowany). Kod autokorelacji, ważenia i strojenia jest używany do znalezienia podstawowej częstotliwości przy użyciu pierwszych 3 okresów. Przybliżona częstotliwość podstawowa jest następnie porównywana z częstotliwościami w zakresie oktaw 3, 4 i 5 w celu określenia najbliższej częstotliwości nuty muzycznej. Na koniec na ekranie wyświetlana jest odgadnięta nuta dla najbliższej częstotliwości.

Uwaga: ta instrukcja koncentruje się tylko na tym, jak zbudować projekt. Aby uzyskać więcej informacji o szczegółach i uzasadnieniu projektu, odwiedź ten link: Więcej informacji

Kieszonkowe dzieci

  • (1) Arduino Uno (lub Genuino Uno)
  • (1) Czujnik mikrofonu DEVMO Kompatybilny z modułem wykrywania dźwięku o wysokiej czułości
  • (1) Płytka chlebowa bez lutowania
  • (1) kabel USB-A do B
  • Przewody połączeniowe
  • Źródło muzyczne (fortepian, klawiatura lub aplikacja paino z głośnikami)
  • (1) Komputer lub laptop

Krok 1: Zbuduj sprzęt dla wykrywacza nut

Skonfiguruj wykrywacz nut
Skonfiguruj wykrywacz nut

Za pomocą Arduino Uno, przewodów połączeniowych, płytki stykowej bez lutowania i modułu wykrywania dźwięku o wysokiej czułości DEVMO (lub podobnego) skonstruuj obwód pokazany na tym obrazie

Krok 2: Zaprogramuj wykrywacz nut

W Arduino IDE dodaj następujący kod.

plik_gist1.txt

/*
Nazwa pliku/szkicu: MusicalNoteDetector
Wersja nr: v1.0 Utworzono 7 czerwca 2020 r.
Autor oryginalny: Clyde A. Lettsome, PhD, PE, MEM
Opis: ten kod/szkic wyświetla przybliżoną częstotliwość oraz nutę graną na klawiaturze elektronicznej lub w aplikacji na fortepian. W tym projekcie wyjście analogowe z
detektor modułu dźwiękowego jest wysyłany na wejście analogowe A0 Arduino Uno. Sygnał analogowy jest próbkowany i kwantyzowany (cyfryzowany). Kod autokorelacji, ważenia i strojenia służy do
znajdź częstotliwość podstawową używając pierwszych 3 okresów. Przybliżona częstotliwość podstawowa jest następnie porównywana z częstotliwościami w zakresie oktaw 3, 4 i 5 w celu określenia najbliższego musicalu
częstotliwość nut. Na koniec na ekranie wyświetlana jest odgadnięta nuta dla najbliższej częstotliwości.
Licencja: Ten program jest darmowym oprogramowaniem; możesz go redystrybuować i/lub modyfikować zgodnie z warunkami licencji GNU General Public License (GPL) w wersji 3 lub dowolnej późniejszej
wybraną przez Ciebie wersję opublikowaną przez Free Software Foundation.
Uwagi: Copyright (c) 2020 przez CA Lettsome Services, LLC
Więcej informacji na stronie
*/
#define SAMPLES 128 //Max 128 dla Arduino Uno.
#define SAMPLING_FREQUENCY 2048 //Fs = Na podstawie Nyquista, musi być 2 razy większa od oczekiwanej częstotliwości.
#define OFFSETSAMPLES 40 //używane do celów kalibracyjnych
#define TUNER -3 //Dostosuj, aż C3 wyniesie 130,50
okres próbkowania pływaka;
długie mikrosekundy bez znaku;
int X[PRÓBKI]; //utwórz wektor o rozmiarze SAMPLES do przechowywania rzeczywistych wartości
zmiennoprzecinkowa autoKorr[PRÓBKI]; //utwórz wektor o rozmiarze SAMPLES do przechowywania urojonych wartości
zmiennoprzecinkowa przechowywanaCzęst.noty[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 przesunięte[PRÓBKI PRZESUNIĘCIA]; //utwórz wektor przesunięcia
int avgOffset; //utwórz wektor przesunięcia
int i, k, koniec okresu, początek okresu, okres, regulator, lokalizacja notatki, zakres oktawy;
float maxValue, minValue;
długa suma;
int próg = 0;
int liczba cykli = 0;
float częstotliwość sygnału, częstotliwość sygnału2, częstotliwość sygnału3, częstotliwość sygnałuGuess, suma;
bajt stan_maszyna = 0;
int samplePerPeriod = 0;
pusta konfiguracja()
{
Serial.początek(115200); //115200 Szybkość transmisji dla monitora szeregowego
}
pusta pętla()
{
//*****************************************************************
//Sekcja Kalibracji
//*****************************************************************
Serial.println("Kalibracja. Proszę nie odtwarzać żadnych notatek podczas kalibrowania.");
dla (i = 0; i <PRÓBKI PRZESUNIĘCIA; i++)
{
offset = odczyt analogowy(0); //Odczytuje wartość z pinu analogowego 0 (A0), kwantyzuje ją i zapisuje jako rzeczywisty termin.
//Serial.println(offSet); //użyj tego, aby ustawić moduł wykrywania dźwięku na około połowę lub 512, gdy dźwięk nie jest odtwarzany.
sumOffSet = sumOffSet + offSet;
}
samplePerPeriod = 0;
maxWartość = 0;
//*****************************************************************
//Przygotuj się do przyjęcia danych wejściowych z A0
//*****************************************************************
avgOffSet = round(sumOffSet / OFFSETSAMPLES);
Serial.println("Odliczanie.");
opóźnienie (1000); //pauza na 1 sekundę
Serial.println("3");
opóźnienie (1000); //pauza na 1 sekundę
Serial.println("2");
opóźnienie (1000); //pauza na 1
Serial.println("1");
opóźnienie (1000); //pauza na 1 sekundę
Serial.println("Odtwórz swoją notatkę!");
opóźnienie(250); //pauza na 1/4 sekundy dla czasu reakcji
//*****************************************************************
//Pobierz próbki z A0 z próbnym okresem próbkowaniaOkres próbkowania
//*****************************************************************
Okres próbkowania = 1,0 / CZĘSTOTLIWOŚĆ PRÓBOWANIA; //Okres w mikrosekundach
dla (i = 0; i < PRÓBKI; i++)
{
mikrosekundy = mikros(); //Zwraca liczbę mikrosekund od rozpoczęcia bieżącego skryptu na płycie Arduino.
X = odczyt analogowy(0); //Odczytuje wartość z pinu analogowego 0 (A0), kwantyzuje ją i zapisuje jako rzeczywisty termin.
/*pozostały czas oczekiwania między próbkami, jeśli to konieczne w sekundach */
while (mikros() < (mikrosekundy + (okres próbkowania * 1000000)))
{
//nic nie rób tylko czekaj
}
}
//*****************************************************************
//Funkcja autokorelacji
//*****************************************************************
for (i = 0; i < PRÓBKI; i++) //i=opóźnienie
{
suma = 0;
for (k = 0; k < PRÓBKI - i; k++) //Dopasuj sygnał z opóźnionym sygnałem
{
suma = suma + (((X[k]) - avgOffSet) * ((X[k + i]) - avgOffSet)); //X[k] to sygnał, a X[k+i] to wersja opóźniona
}
autoCorr = suma / PRÓBKI;
// Maszyna stanu pierwszego wykrycia szczytu
if (state_machine==0 && i == 0)
{
thresh = autoCorr * 0,5;
maszyna_stanowa = 1;
}
w przeciwnym razie if (state_machine == 1 && i>0 && thresh 0) //state_machine=1, znajdź 1 okres na użycie pierwszego cyklu
{
maxValue = autoCorr;
}
else if (state_machine == 1&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
Początek okresu = i-1;
maszyna_stanowa = 2;
liczbaCykli = 1;
samplePerPeriod = (okresPoczątek - 0);
okres = samplePerPeriod;
regulator = TUNER+(50.04 * exp(-0.102 * samplePerPeriod));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplesPerPeriod))-regulator; // f = fs/N
}
else if (state_machine == 2 && i>0 && thresh 0) //state_machine=2, znajdź 2 okresy dla 1. i 2. cyklu
{
maxValue = autoCorr;
}
else if (state_machine == 2&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
koniec okresu = i-1;
maszyna_stanowa = 3;
liczbaCykli = 2;
samplePerPeriod = (periodEnd - 0);
signalFrequency2 = ((numOfCycles*SAMPLING_CREQUENCY) / (samplesPerPeriod))-regulator; // f = (2*fs)/(2*N)
maxWartość = 0;
}
else if (state_machine == 3 && i>0 && thresh 0) //state_machine=3, znajdź 3 okresy dla 1., 2. i 3. cyklu
{
maxValue = autoCorr;
}
else if (state_machine == 3&& i>0 && thresh < autoCorr[i-1] && maxValue == autoCorr[i-1] && (autoCorr-autoCorr[i-1])<=0)
{
koniec okresu = i-1;
maszyna_stanowa = 4;
liczbaCykli = 3;
samplePerPeriod = (periodEnd - 0);
signalFrequency3 = ((numOfCycles*SAMPLING_CREQUENCY) / (samplesPerPeriod))-regulator; // f = (3*fs)/(3*N)
}
}
//*****************************************************************
//Analiza wyników
//*****************************************************************
jeśli (próbki na okres == 0)
{
Serial.println("Hmm….. Nie jestem pewien. Próbujesz mnie oszukać?");
}
w przeciwnym razie
{
//przygotuj funkcję ważenia
suma = 0;
jeśli (częstotliwość sygnału !=0)
{
suma = 1;
}
if(Częstotliwość Sygnału2 !=0)
{
suma = suma + 2;
}
jeśli (Częstotliwość Sygnału3 !=0)
{
suma = suma + 3;
}
//oblicz częstotliwość za pomocą funkcji ważenia
częstotliwośćsygnałuGuess = ((1/całkowita) * częstotliwośćsygnału) + ((2/całkowita) * częstotliwośćsygnału2) + ((3/całkowita) * częstotliwośćsygnału3); //znajdź częstotliwość ważoną
Serial.print("Zagrana nuta to około ");
Serial.print(ZgadywanieCzęstotliwości Sygnału); //Wydrukuj przewidywaną częstotliwość.
Serial.println("Hz.");
//znajdź zakres oktaw na podstawie przypuszczenia
oktawaZakres=3;
while (!(signalFrequencyGuess >= zapisany NoteFreq[0]-7 && signalFrequencyGuess <= zapisanyNoteFreq[11]+7))
{
dla(i = 0; i < 12; i++)
{
zapisanyCzęstUwag = 2 * zapisanyCzęstUwag;
}
zakres oktawy++;
}
//Znajdź najbliższą notatkę
minWartość = 10000000;
uwagaLokalizacja = 0;
dla (i = 0; i < 12; i++)
{
if(minValue> abs(sygnałCzęstotliwośćGuess-przechowywanaCzęstoUwagi))
{
minValue = abs(zapisanaCzęstotliwośćSygnałówGuess-NoteFreq);
uwagaLokalizacja = ja;
}
}
//Wydrukuj notatkę
Serial.print("Myślę, że grałeś");
if(noteLokalizacja==0)
{
Serial.print("C");
}
inaczej if(noteLocation==1)
{
Serial.print("C#");
}
inaczej if(noteLocation==2)
{
Serial.print("D");
}
w przeciwnym razie, jeśli(noteLocation==3)
{
Serial.print("D#");
}
inaczej if(noteLocation==4)
{
Serial.print("E");
}
inaczej if(noteLocation==5)
{
Serial.print("F");
}
inaczej if(noteLocation==6)
{
Serial.print("F#");
}
inaczej if(noteLocation==7)
{
Serial.print("G");
}
inaczej if(noteLocation==8)
{
Serial.print("G#");
}
inaczej if(noteLocation==9)
{
Serial.print("A");
}
w przeciwnym razie, jeśli(noteLocation==10)
{
Serial.print("A#");
}
inaczej if(noteLocation==11)
{
Serial.print("B");
}
Serial.println(zakres oktawy);
}
//*****************************************************************
//Zatrzymaj się tutaj. Naciśnij przycisk resetowania na Arduino, aby ponownie uruchomić
//*****************************************************************
natomiast (1);
}

wyświetl rawgistfile1.txt hostowany z ❤ przez GitHub

Krok 3: Skonfiguruj wykrywacz nut

Podłącz Arduino Uno do komputera za pomocą kodu zapisanego lub załadowanego w Arduino IDE. Skompiluj i prześlij kod do Arduino. Umieść obwód blisko źródła muzyki. Uwaga: w filmie wprowadzającym używam aplikacji zainstalowanej na tablecie w połączeniu z głośnikami komputera jako źródła muzyki. Naciśnij przycisk resetowania na płycie Arduino, a następnie odtwórz notatkę na źródle muzyki. Po kilku sekundach Musical Note Detector wyświetli odtwarzaną nutę i jej częstotliwość.

Zalecana: