Tabla de contenido:

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

Video: Detector de notas musicales Arduino: 3 pasos

Video: Detector de notas musicales Arduino: 3 pasos
Video: 11.- TUTORIAL ARDUINO - Notas musicales y melodias 2024, Noviembre
Anonim
Image
Image

La detección de notas musicales a partir de la señal de audio es difícil de hacer, especialmente en Arduino debido a la memoria limitada y la potencia de procesamiento. Generalmente, la nota no es una onda sinusoidal pura que dificulta la detección. Si tomamos la transformación de frecuencia de varios instrumentos musicales, puede contener múltiples armónicos basados en la nota que se está tocando. Cada instrumento tiene su propia combinación característica de varios armónicos. En este código, traté de hacer un programa que pueda cubrir tantos instrumentos como sea posible. Puede consultar el video adjunto en el que intenté probar los diversos tipos de instrumentos, se verifican varios tipos de tonos generados por el teclado e incluso el sonido de la voz. La precisión de la detección varía de un instrumento a otro. Para algunos instrumentos (es decir, piano) en un rango limitado (200-500Hz) es preciso, mientras que algunos instrumentos tienen baja precisión (es decir, armónica).

Este código hace uso de un código FFT desarrollado previamente llamado EasyFFT.

La demostración del código se muestra en el video anterior con varios tipos de sonido de instrumentos, así como vocales.

Suministros

- Arduino Nano / Uno o superior

- Módulo de micrófono para Arduino

Paso 1: algoritmo para la detección de notas

Como se mencionó en el paso anterior, la detección es difícil debido a la presencia de múltiples frecuencias en las muestras de audio.

El programa funciona en el siguiente flujo:

1. Adquisición de datos:

- esta sección toma 128 muestras de datos de audio, la separación entre dos muestras (frecuencia de muestreo) depende de la frecuencia de interés. En este caso, estamos usando el espaciado entre dos muestras para aplicar la función de ventana de Hann, así como el cálculo de amplitud / RMS. Este código también realiza una puesta a cero aproximada restando 500 del valor de lectura analógica. Este valor se puede cambiar si es necesario. Para un caso típico, estos valores funcionan bien. Además, es necesario agregar algo de retraso para tener una frecuencia de muestreo de alrededor de 1200 Hz. en el caso de una frecuencia de muestreo de 1200Hz, se puede detectar una frecuencia máxima de 600 HZ.

para (int i = 0; i <128; i ++) {a = analogRead (Mic_pin) -500; // desplazamiento a cero aproximado sum1 = sum1 + a; // al valor medio sum2 = sum2 + a * a; // al valor RMS a = a * (sin (i * 3.14 / 128) * sin (i * 3.14 / 128)); // Ventana de Hann en = 4 * a; // escalado para conversión de flotante a int delayMicroseconds (195); // basado en el rango de frecuencia de operación}

2. FFT:

Una vez que los datos están listos, FFT se realiza usando EasyFFT. Esta función EasyFFT se modifica para fijar FFT para 128 muestras. El código también se modifica para reducir el consumo de memoria. La función EasyFFT original diseñada para tener hasta 1028 muestras (con la placa compatible), mientras que solo necesitamos 128 muestras. este código reduce el consumo de memoria en aproximadamente un 20% en comparación con la función EasyFFT original.

Una vez que se realiza la FFT, el código devuelve los 5 picos de frecuencia más dominantes para un análisis más detallado. Esta frecuencia se dispone en orden descendente de amplitud.

3. Para cada pico, el código detecta posibles notas asociadas a él. este código solo escanea hasta 1200 Hz. No es necesario tener una nota igual a la frecuencia con amplitud máxima.

Todas las frecuencias se asignan entre 0 y 255, aquí se detecta la primera octava, por ejemplo, 65,4 Hz a 130,8 representa una octava, 130,8 Hz a 261,6 Hz representa otra. Para cada octava, las frecuencias se mapean de 0 a 255. aquí se mapean comenzando desde C a C '.

if (f_peaks > 1040) {f_peaks = 0;} if (f_peaks > = 65.4 && f_peaks = 130.8 && f_peaks = 261.6 && f_peaks = 523.25 && f_peaks = 1046 && f_peaks <= 2093) {f_peaks = 255 * ((f_peaks / 1046) -1);}

Los valores de la matriz NoteV se utilizan para asignar la nota a las frecuencias detectadas.

byte NoteV [13] = {8, 23, 40, 57, 76, 96, 116, 138, 162, 187, 213, 241, 255};

4. Después de calcular la nota para cada frecuencia, puede darse el caso de que existan múltiples frecuencias que sugieran la misma nota. Para tener un código de salida preciso también se consideran las repeticiones. El código suma todos los valores de frecuencia en función del orden de amplitud y las repeticiones y eleva la nota con la amplitud máxima.

Paso 2: aplicación

Usar el código es sencillo, sin embargo, también hay múltiples limitaciones que deben tenerse en cuenta al hacerlo. El código se puede copiar ya que se utiliza para la detección de notas. Los siguientes puntos deben tenerse en cuenta al usarlo.

1. Asignación de pines:

Según la asignación de pines adjunta, debe modificarse. Para mi experimento, lo mantuve en el pin 7 analógico, configuración vacía () {Serial.begin (250000); Mic_pin = A7; }

2. Sensibilidad del micrófono:

La sensibilidad del micrófono debe modificarse para que la forma de onda se pueda generar con buena amplitud. Principalmente, el módulo de micrófono viene con un ajuste de sensibilidad. Se debe seleccionar la sensibilidad adecuada de manera que la señal no sea demasiado pequeña y tampoco se corte debido a una mayor amplitud.

3. Umbral de amplitud:

Este código se activa solo si la amplitud de la señal es lo suficientemente alta. esta configuración debe ser establecida manualmente por el usuario. este valor depende de la sensibilidad del micrófono y de la aplicación.

si (suma2-suma1> 5) {

..

en el código anterior, suma2 da valor RMS mientras que suma 1 da valor medio. por lo que la diferencia entre estos dos valores da la amplitud de la señal de sonido. en mi caso, funciona correctamente con un valor de amplitud de alrededor de 5.

4. De forma predeterminada, este código imprimirá la nota detectada. sin embargo, si planea usar la nota para algún otro propósito, debe usar el número asignado directamente. por ejemplo C = 0; C # = 1, D = 2, D # = 3 y en adelante.

5. Si el instrumento tiene una frecuencia más alta, el código puede dar una salida falsa. la frecuencia máxima está limitada por la frecuencia de muestreo. por lo que puede jugar por debajo de los valores de retardo para obtener una salida óptima. en el retardo de código inferior de 195 microsegundos. que puede modificarse para obtener un resultado óptimo. Esto afectará el tiempo de ejecución general.

{a = analogRead (Mic_pin) -500; // cambio de cero aproximado

suma1 = suma1 + a; // al valor medio sum2 = sum2 + a * a; // al valor RMS a = a * (sin (i * 3.14 / 128) * sin (i * 3.14 / 128)); // Ventana de Hann en = 4 * a; // escalado para conversión de flotante a int delayMicroseconds (195); // basado en el rango de frecuencia de operación}

6. este código solo funcionará hasta una frecuencia de 2000Hz. eliminando el retardo entre muestreo, se pueden obtener alrededor de 3-4 kHz de frecuencias de muestreo.

Precauciones:

  • Como se mencionó en el tutorial de EasyFFT, FFT consume una gran cantidad de memoria de Arduino. Entonces, si tiene un programa que necesita almacenar algunos valores, se recomienda usar una placa con mayor memoria.
  • Este código puede funcionar bien para un instrumento / vocalista y malo para otro. La detección precisa en tiempo real no es posible debido a limitaciones computacionales.

Paso 3: veraniego

La detección de notas es un trabajo computacionalmente intensivo, obtener resultados en tiempo real es muy difícil, especialmente en Arduino. Este código puede dar alrededor de 6,6 muestras / segundos (por un retraso de 195 microsegundos añadido). este código funciona bien con el piano y algunos otros instrumentos.

Espero que este código y tutorial te sea de ayuda en tu proyecto relacionado con la música. en caso de cualquier duda o sugerencia, no dude en comentar o enviar un mensaje.

En el próximo tutorial, modificaré este código para la detección de acordes musicales. así que estad atentos.

Recomendado: