Tabla de contenido:

Detector de notas musicales: 3 pasos
Detector de notas musicales: 3 pasos

Video: Detector de notas musicales: 3 pasos

Video: Detector de notas musicales: 3 pasos
Video: 5 Herramientas GRATIS p/ Detectar Notas Musicales - Alternativas al VST Key Detector de Waves Audio 2024, Noviembre
Anonim
Image
Image

Sorprenda a sus amigos y familiares con este proyecto que detecta la nota tocada por un instrumento. Este proyecto mostrará la frecuencia aproximada, así como la nota musical tocada en un teclado electrónico, aplicación de piano o cualquier otro instrumento.

Detalles

Para este proyecto, la salida analógica del detector del módulo de sonido se envía a la entrada analógica A0 del Arduino Uno. La señal analógica se muestrea y cuantifica (digitaliza). El código de autocorrelación, ponderación y sintonía se utiliza para encontrar la frecuencia fundamental utilizando los primeros 3 períodos. Luego, la frecuencia fundamental aproximada se compara con las frecuencias en el rango de octavas 3, 4 y 5 para determinar la frecuencia de nota musical más cercana. Finalmente, la nota adivinada para la frecuencia más cercana se imprime en la pantalla.

Nota: Este instructivo solo se enfoca en cómo construir el proyecto. Para obtener más información sobre los detalles y las justificaciones del diseño, visite este enlace: Más información

Suministros

  • (1) Arduino Uno (o Genuino Uno)
  • (1) Módulo de detección de sonido de alta sensibilidad con sensor de micrófono DEVMO Compatible
  • (1) Placa de pruebas sin soldadura
  • (1) Cable USB-A a B
  • Cables de puente
  • Fuente musical (piano, teclado o aplicación paino con altavoces)
  • (1) Computadora o laptop

Paso 1: construya el hardware para el detector de notas musicales

Configurar el detector de notas musicales
Configurar el detector de notas musicales

Usando un Arduino Uno, cables de conexión, una placa de prueba sin soldadura y un Módulo de detección de sonido de alta sensibilidad con sensor de micrófono DEVMO (o similar) construya el circuito que se muestra en esta imagen

Paso 2: programe el detector de notas musicales

En el IDE de Arduino, agregue el siguiente código.

gistfile1.txt

/*
Nombre de archivo / boceto: MusicalNoteDetector
Número de versión: v1.0 Creado el 7 de junio de 2020
Autor original: Clyde A. Lettsome, PhD, PE, MEM
Descripción: este código / boceto muestra la frecuencia aproximada, así como la nota musical tocada en un teclado electrónico o aplicación de piano. Para este proyecto, la salida analógica del
El detector de módulo de sonido se envía a la entrada analógica A0 del Arduino Uno. La señal analógica se muestrea y cuantifica (digitaliza). El código de autocorrelación, ponderación y ajuste se utiliza para
encuentre la frecuencia fundamental utilizando los primeros 3 períodos. Luego, la frecuencia fundamental aproximada se compara con las frecuencias en el rango de octavas 3, 4 y 5 para determinar la frecuencia musical más cercana.
nota la frecuencia. Finalmente, la nota adivinada para la frecuencia más cercana se imprime en la pantalla.
Licencia: este programa es software gratuito; puede redistribuirlo y / o modificarlo bajo los términos de la Licencia Pública General GNU (GPL) versión 3, o cualquier posterior
versión de su elección, según lo publicado por la Free Software Foundation.
Notas: Copyright (c) 2020 de C. A. Lettsome Services, LLC
Para obtener más información, visite
*/
#define SAMPLES 128 // Max 128 para Arduino Uno.
#define SAMPLING_FREQUENCY 2048 // Fs = Basado en Nyquist, debe ser 2 veces la frecuencia más alta esperada.
#define OFFSETSAMPLES 40 // utilizado con fines de calabrating
#define TUNER -3 // Ajustar hasta que C3 sea 130.50
período de muestreo flotante;
microSegundos largos sin firmar;
int X [MUESTRAS]; // crea un vector de tamaño MUESTRAS para contener valores reales
flotar autoCorr [MUESTRAS]; // crea un vector de tamaño MUESTRAS para contener valores imaginarios
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]; // crear vector de compensación
int avgOffSet; // crear vector de compensación
int i, k, periodEnd, periodBegin, period, ajustador, noteLocation, octaveRange;
float maxValue, minValue;
suma larga
int thresh = 0;
int numOfCycles = 0;
flotar signalFrequency, signalFrequency2, signalFrequency3, signalFrequencyGuess, total;
byte state_machine = 0;
int samplesPerPeriod = 0;
configuración vacía ()
{
Serial.begin (115200); // 115200 Velocidad en baudios para el monitor en serie
}
bucle vacío ()
{
//*****************************************************************
// Sección de Calabration
//*****************************************************************
Serial.println ("Calabrating. Por favor, no toque ninguna nota durante la calabration.");
para (i = 0; i <MUESTRAS DESPLAZADAS; i ++)
{
offSet = analogRead (0); // Lee el valor del pin analógico 0 (A0), lo cuantifica y lo guarda como término real.
//Serial.println(offSet); // use esto para ajustar el módulo de detección de sonido a aproximadamente la mitad o 512 cuando no se reproduce ningún sonido.
sumOffSet = sumOffSet + offSet ;
}
samplesPerPeriod = 0;
maxValue = 0;
//*****************************************************************
// Prepárese para aceptar la entrada de A0
//*****************************************************************
avgOffSet = round (sumOffSet / OFFSETSAMPLES);
Serial.println ("Cuenta regresiva");
retraso (1000); // pausa por 1 segundo
Serial.println ("3");
retraso (1000); // pausa por 1 segundo
Serial.println ("2");
retraso (1000); // pausa por 1
Serial.println ("1");
retraso (1000); // pausa por 1 segundo
Serial.println ("¡Toca tu nota!");
retraso (250); // pausa durante 1/4 de segundo para el tiempo de reacción
//*****************************************************************
// Recolectar MUESTRAS muestras de A0 con período de muestreo de período de muestreo
//*****************************************************************
SamplePeriod = 1.0 / SAMPLING_FREQUENCY; // Periodo en microsegundos
para (i = 0; i <MUESTRAS; i ++)
{
microSegundos = micros (); // Devuelve el número de microsegundos desde que la placa Arduino comenzó a ejecutar el script actual.
X = analogRead (0); // Lee el valor del pin analógico 0 (A0), lo cuantifica y lo guarda como término real.
/ * tiempo de espera restante entre muestras si es necesario en segundos * /
while (micros () <(microsegundos + (período de muestreo * 1000000)))
{
// no hagas nada solo espera
}
}
//*****************************************************************
// Función de autocorrelación
//*****************************************************************
para (i = 0; i <MUESTRAS; i ++) // i = retraso
{
suma = 0;
for (k = 0; k <SAMPLES - i; k ++) // Emparejar señal con señal retardada
{
suma = suma + (((X [k]) - avgOffSet) * ((X [k + i]) - avgOffSet)); // X [k] es la señal y X [k + i] es la versión retrasada
}
autoCorr = suma / MUESTRAS;
// Primera máquina de estado de detección de picos
si (state_machine == 0 && i == 0)
{
umbral = autoCorr * 0,5;
state_machine = 1;
}
else if (state_machine == 1 && i> 0 && thresh 0) // state_machine = 1, encuentra 1 período para usar el primer ciclo
{
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;
state_machine = 2;
numOfCycles = 1;
samplesPerPeriod = (periodBegin - 0);
period = samplesPerPeriod;
ajustador = TUNER + (50.04 * exp (-0.102 * samplesPerPeriod));
signalFrequency = ((SAMPLING_FREQUENCY) / (samplesPerPeriod)) - ajustador; // f = fs / N
}
else if (state_machine == 2 && i> 0 && thresh 0) // state_machine = 2, encuentra 2 períodos para el 1er y 2do ciclo
{
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;
state_machine = 3;
numOfCycles = 2;
samplesPerPeriod = (periodEnd - 0);
SignalFrequency2 = ((numOfCycles * SAMPLING_FREQUENCY) / (samplesPerPeriod)) - ajustador; // f = (2 * fs) / (2 * N)
maxValue = 0;
}
else if (state_machine == 3 && i> 0 && thresh 0) // state_machine = 3, encuentre 3 períodos para el 1er, 2do y 3er ciclo
{
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;
state_machine = 4;
numOfCycles = 3;
samplesPerPeriod = (periodEnd - 0);
signalFrequency3 = ((numOfCycles * SAMPLING_FREQUENCY) / (samplesPerPeriod)) - ajustador; // f = (3 * fs) / (3 * N)
}
}
//*****************************************************************
//Análisis de resultados
//*****************************************************************
si (samplesPerPeriod == 0)
{
Serial.println ("Hmm….. No estoy seguro. ¿Estás tratando de engañarme?");
}
demás
{
// preparar la función de ponderación
total = 0;
si (señalFrecuencia! = 0)
{
total = 1;
}
si (señalFrecuencia2! = 0)
{
total = total + 2;
}
si (señalFrecuencia3! = 0)
{
total = total + 3;
}
// calcula la frecuencia usando la función de ponderación
señalFrecuenciaGuess = ((1 / total) * señalFrecuencia) + ((2 / total) * señalFrecuencia2) + ((3 / total) * señalFrecuencia3); // encontrar una frecuencia ponderada
Serial.print ("La nota que tocó es aproximadamente");
Serial.print (signalFrequencyGuess); // Imprime la estimación de frecuencia.
Serial.println ("Hz.");
// encuentra el rango de octava basado en la suposición
octaveRange = 3;
while (! (signalFrequencyGuess> = storedNoteFreq [0] -7 && signalFrequencyGuess <= storedNoteFreq [11] +7))
{
para (i = 0; i <12; i ++)
{
storedNoteFreq = 2 * storedNoteFreq ;
}
octaveRange ++;
}
// Encuentra la nota más cercana
minValue = 10000000;
noteLocation = 0;
para (i = 0; i <12; i ++)
{
if (minValue> abs (signalFrequencyGuess-storedNoteFreq ))
{
minValue = abs (signalFrequencyGuess-storedNoteFreq );
noteLocation = i;
}
}
// Imprime la nota
Serial.print ("Creo que jugaste");
si (noteLocation == 0)
{
Serial.print ("C");
}
else if (noteLocation == 1)
{
Serial.print ("C #");
}
más si (noteLocation == 2)
{
Serial.print ("D");
}
más si (noteLocation == 3)
{
Serial.print ("D #");
}
más si (noteLocation == 4)
{
Serial.print ("E");
}
más si (noteLocation == 5)
{
Serial.print ("F");
}
más si (noteLocation == 6)
{
Serial.print ("F #");
}
más si (noteLocation == 7)
{
Serial.print ("G");
}
más si (noteLocation == 8)
{
Serial.print ("G #");
}
más si (noteLocation == 9)
{
Serial.print ("A");
}
más si (noteLocation == 10)
{
Serial.print ("A #");
}
más si (noteLocation == 11)
{
Serial.print ("B");
}
Serial.println (octaveRange);
}
//*****************************************************************
//Deténgase aquí. Presione el botón de reinicio en Arduino para reiniciar
//*****************************************************************
mientras (1);
}

ver rawgistfile1.txt alojado con ❤ por GitHub

Paso 3: configura el detector de notas musicales

Conecte el Arduino Uno a la PC con el código escrito o cargado en el IDE de Arduino. Compile y cargue el código en Arduino. Coloque el circuito cerca de la fuente de música. Nota: En el video de introducción, utilizo una aplicación instalada en la tableta junto con los parlantes de la PC como fuente de música. Presione el botón de reinicio en la placa Arduino y luego toque una nota en la fuente de música. Después de unos segundos, el detector de notas musicales mostrará la nota tocada y su frecuencia.

Recomendado: