Video Summary and Transcription
Esta charla proporciona una visión general de un proyecto de afinador de guitarra de código abierto, que abarca temas como la detección de tono, las API web para el acceso al micrófono, la implementación con React y XGS, y la visualización de datos. Explora varios algoritmos de detección de tono, incluyendo el cruce por cero, la transformada rápida de Fourier y la autocorrelación. El proyecto utiliza la API MediaStream y la API de Audio para acceder a los medios del usuario. La implementación se realiza con React y Next.js, e incluye una biblioteca de utilidades para realizar estimación y detección de tono. La charla también discute futuras mejoras para el proyecto, como la cancelación de ruido y la detección de acordes.
1. Introducción al Proyecto de Afinador de Guitarra
Soy Omar Job, el Líder Técnico en Learn, una empresa italiana que tiene como objetivo hacer que las competencias digitales sean accesibles para todos. Hoy, tendremos una visión general de un proyecto de afinador de guitarra de código abierto. Exploraremos la detección y estimación de tono, las API web para acceder al micrófono, la implementación con React y XGS, la visualización de datos y discutiremos problemas y mejoras. Este proyecto nació por curiosidad y tiene como objetivo explorar nuevos territorios. Es de código abierto, está construido con React y extraJS, y utiliza la API de audio web.
Hola a todos. Es un placer estar aquí y no puedo esperar para compartir con ustedes este tema. Así que, comencemos con las presentaciones. Soy Omar Job y soy el Líder Técnico en Learn, que es una empresa italiana que tiene como objetivo hacer que las competencias digitales sean accesibles para todos. En mi tiempo libre, tengo muchas pasiones, una de las cuales es la música, y me encanta molestar a mis vecinos tocando la guitarra. Y por eso estamos aquí.
Así que, hoy vamos a ver muchas cosas. Tendremos una visión general del proyecto, que es un afinador de guitarra de código abierto. Veremos los conceptos básicos de la detección y estimación de tono, es decir, cómo detectar la frecuencia de una nota que se está tocando. Luego veremos las API web involucradas en el proyecto, es decir, cómo acceder al micrófono del usuario. Y veremos incluso la implementación real con React y XGS. Y luego veremos la parte de visualización de datos, es decir, cómo mostrar la información que estamos obteniendo. Y después de eso, finalmente, hablaremos sobre problemas y posibles mejoras. Me gustaría comenzar con una pregunta que es, ¿necesitamos otro afinador de guitarra? Bueno, hay muchos afinadores de guitarra en línea. Puedes encontrar muchas aplicaciones y descargarlas de forma gratuita. Entonces, eso nos lleva a otra pregunta, que es, ¿por qué? ¿Por qué volvimos a crear un afinador de guitarra? Bueno, en realidad, quería probar por mí mismo y tenía curiosidad porque quería ver qué había debajo del capó. Quería ver todas las matemáticas involucradas en la estimación y detección de tono. Y quería ver si podía construir un afinador de guitarra desde cero. Así que este es un proyecto hecho por pura curiosidad. Y una advertencia, no soy matemático. Este es el resultado de mis investigaciones y mi curiosidad. Así que este es un proyecto que tiene como objetivo explorar algo que nunca había explorado. El proyecto es de código abierto. Puedes encontrarlo en línea. Puedes revisar el código y lo compartiré contigo después de la charla para que puedas explorarlo. Está hecho con React y extraJS. Y utiliza la API de audio web. La interfaz es bastante clara. Detecta la nota que se está tocando. Y como puedes ver, el indicador se mueve
2. Conceptos básicos de detección de tono y algoritmos
Los conceptos básicos de detección de tono implican comprender que las notas se representan mediante frecuencias en hertzios. Se utiliza una frecuencia de referencia, A440, para la afinación. La señal de la guitarra, representada por una onda, a menudo es ruidosa, lo que dificulta el análisis. Existen varios algoritmos para la detección de tono, incluyendo el cruce por cero.
cuando toco una nota. Es muy preciso. Se puede mejorar, pero para esta etapa, es muy, muy bueno y funciona muy bien. Entonces, ¿cuáles son los conceptos básicos de la detección de tono? Bueno, quiero alinear a todos en el tema porque si tocas un instrumento, y he notado que muchos programadores tocan instrumentos, pero si no eres músico, este tema puede ser complicado de entender. Así que quiero alinear a todos en el tema. Comenzamos con las notas. Y les digo que las notas se representan mediante una frecuencia, que se mide en hertzios. Como pueden ver, en esta tabla, tenemos muchas notas. Cada nota se representa con un número, que es la frecuencia. En la fila superior, pueden ver los nombres de las notas que van de C a B. Y en la columna izquierda, pueden ver algunos números que van de 0 a 4. Estos números son octavas. Una octava es la misma nota repetida, pero con una frecuencia diferente y cada octava duplica la frecuencia de la nota. En otras palabras, si van a la columna A, en el A440, que está resaltado, pueden ver que si bajan por las filas en la columna, la frecuencia se duplica. Entonces, el A440 es la frecuencia de referencia para la afinación. Por lo tanto, muchos afinadores utilizan esta frecuencia para afinar todos los instrumentos, y este es el A4, el A en la octava 4. La guitarra tiene seis cuerdas, por lo que cada cuerda se toca como una nota. Como pueden ver aquí, las seis cuerdas son una nota E en la cuarta octava. La primera cuerda, por ejemplo, es un E en la segunda octava, y como pueden notar, las frecuencias son muy diferentes. Nuestro objetivo es detectar la frecuencia que se está tocando y decirle al usuario qué nota está tocando para afinar su guitarra. Entonces, la señal de la guitarra se puede representar con una gráfica. En el sonido, la señal se representa mediante una onda. Como pueden ver a la izquierda, tenemos una señal limpia que es un A4, es decir, A440 Hz. Como pueden ver, es periódica y muy clara. A la derecha, pueden ver la señal de la guitarra, que no es tan clara, pero puede ser muy ruidosa y difícil de analizar este tipo de señal. Esto nos lleva a nuestros algoritmos. Tenemos muchos algoritmos para realizar estimación y detección de tono. Estos son los tres algoritmos principales que he estudiado, y voy a mostrarles cada algoritmo paso a paso. Señalaré los pros, los contras, y cuál utilicé para realizar la detección de tono real en el proyecto. Comenzaremos con
3. Algoritmos de Detección de Tono y APIs Web
El cruce por cero es un algoritmo que cuenta el número de veces que una señal cruza la línea cero para determinar la frecuencia. La transformada rápida de Fourier convierte una señal del dominio del tiempo al dominio de la frecuencia, pero puede ser difícil de interpretar. La autocorrelación compara una señal con versiones desplazadas para obtener una representación más clara. El proyecto utiliza la API MediaStream y la API Audio para acceder a los medios del usuario.
El cruce por cero. El cruce por cero comienza con este tipo de representación, una señal clara. Estamos aplicando el cruce por cero a una señal clara. El cruce por cero es un algoritmo en el que se cuenta el número de veces que la señal cruza la línea cero. ¿Por qué se hace esto? Porque la frecuencia, es decir, los Hz, es la representación de un ciclo por segundo. Cada ciclo, una función clara, una función periódica, cruza la línea cero dos veces. Entonces, si conoces el número de cruces y lo divides por dos, obtienes el número de oscilaciones, el número de ciclos, y puedes dividir el número de oscilaciones por los segundos y obtener la frecuencia exacta en Hz. Este método es bastante sencillo en una señal clara, pero ¿funciona en una señal de guitarra? Bueno, no. La respuesta es no, porque como hemos visto antes, este tipo de señal es muy, muy complicada, es muy ruidosa, y no siempre es periódica, por lo que es difícil aplicar este tipo de método. Veamos si otro método viene a nuestro rescate. Entonces, la transformada rápida de Fourier. La transformada rápida de Fourier es un método que aplica la transformada de Fourier discreta a una señal. Convierte la señal de su dominio original, que es el tiempo, al dominio de la frecuencia. ¿Qué quiero decir con eso? Hagámoslo claro. Como puedes ver aquí, en el eje x tienes el tiempo en la señal, y en el eje y tienes la amplitud, es decir, la medida de la intensidad de la señal. A la derecha, la señal se convierte en este tipo de representación, en la que en el eje x tienes la frecuencia, y en el eje y tienes aún la amplitud, pero como puedes ver hay un pico alrededor de 440. Entonces, la señal que es A4, 440, se convierte en una representación que tiene un pico. Por lo tanto, está claro que esta frecuencia es esta. Entonces, a la derecha, en el eje x, tienes la frecuencia, y puedes detectar fácilmente la frecuencia. Pero, ¿esto funciona con una señal de guitarra? Bueno, sí, pero es muy complicado entender qué pico elegir, porque como puedes ver aquí, tienes muchos picos y no es muy claro.
Pasemos al último algoritmo que es el que he utilizado en el proyecto, que es la autocorrelación. La autocorrelación es un algoritmo que se utiliza para comparar la señal con la versión desplazada de sí misma. ¿Qué quiero decir con eso? Si miras la gráfica superior, puedes ver que la señal está desplazada y repetida a lo largo del tiempo, y en la gráfica inferior puedes ver esta función trazada. Entonces, cuando la señal es la misma, la función tiene un valor de 1. Cuando la señal es completamente diferente, tiene un valor de menos 1. Entonces, si avanzas y desplazas la señal hacia adelante, obtienes una gráfica. A partir de este tipo de señal, obtienes este tipo de gráfica, que es más fácil de entender y es muy clara. Entonces, podemos decir que este algoritmo se utiliza para limpiar la señal y trazar una gráfica que es más legible y más accesible para los cálculos. Entonces, sigamos adelante y veamos las APIs web involucradas. Las principales APIs que he utilizado son la API MediaStream y la API Audio. Echemos un vistazo a la API MediaStream. La API MediaStream es una API que te permite acceder a los medios del usuario, así que
4. Implementación con API de Audio y Estructura de Archivos
El proyecto utiliza la API de Audio, que proporciona interfaces para decodificar, procesar y analizar señales de audio. La implementación se realiza con React y Next.js. Se utiliza BrowserAudio.ts para acceder a los medios del usuario, mientras que Tuner orquesta la lógica entre los componentes. Pitch Detector es una biblioteca de utilidades para realizar estimación de frecuencia, detección de tono y autocorrelación.
al audio del usuario, al micrófono o a la cámara. Tienes muchas configuraciones que puedes utilizar y elegir, como la cancelación de ruido o el control automático de ganancia, por ejemplo, pero solo he utilizado estas tres configuraciones porque en la documentación hay muchas. Puedes echar un vistazo, pero esto es lo que necesitaba. Luego, el usuario es solicitado por esta API, cuando la llamas, con una ventana emergente. Entonces, le pide al usuario que acceda al micrófono. El usuario hace clic en sí y obtienes acceso al micrófono. Luego, tenemos la API de Audio, que es una API que expone muchas interfaces, una de las cuales es el contexto de audio, que es una interfaz que te permite decodificar y procesar la señal y realizar cálculos. Luego, después del contexto de audio, he utilizado el método createAnalyzer. Hay otro método que te permite realizar análisis de frecuencia en tiempo real y en el dominio del tiempo, por lo que tienes acceso a la señal y puedes analizar esta señal. Como puedes ver en esta imagen, tienes la señal, insertas este nodo de análisis, que es un nodo que se coloca entre la señal. Realizas algunos cálculos, algunos análisis, pero la señal no cambia. Por lo tanto, no altera la señal. Solo realiza análisis y se utiliza solo con fines de análisis, no para cambios.
La implementación real se realiza con React y Next.js. La estructura de archivos es la siguiente. He creado tres archivos principales, uno de los cuales es BrowserAudio.ts que se utiliza para acceder a los medios del usuario, por lo que todo lo que hemos visto antes. Luego, tenemos Tuner donde se orquesta toda la lógica entre los componentes. Este es el componente principal de la aplicación. Luego, tenemos Pitch Detector, que es una biblioteca de utilidades que se utiliza para realizar cálculos, estimación de frecuencia, detección de tono y autocorrelación. Veamos BrowserAudio.ts. Esta clase es muy sencilla. Tienes dos atributos que son AudioContext y Analyzer, que son los métodos de los que hablaré más adelante, por lo que son las interfaces que vamos a utilizar para acceder al micrófono del usuario. Luego, tenemos este método que llamo GetMixStream. Utilizas la API MediaDevices, WebMedia API, para acceder a los medios del usuario y ya está. El usuario recibe una solicitud y obtienes acceso a la señal. Luego, en Tuner, creas instancias de BrowserAudio.ts y luego tenemos este Buffer, que es una matriz, una matriz float32, en la que vamos a almacenar todos los data relacionados con la señal porque el AudioContext nos da la señal en este tipo de forma, por lo que se convierte en números. Después de eso, instanciamos el AudioContext y el Analyzer para acceder a estas interfaces. Luego, tenemos un método que se llama StartTuner que se utiliza para acceder al MixStream, por lo que es el método que hemos visto antes. Obtienes acceso al MixStream y realizas todos los cálculos que desees. Después de eso, establezco la fuente, que es una variable de estado con el AudioContext, por lo que tengo acceso a toda la señal y luego SetListening es solo una variable de estado utilizada con fines de visualización para mostrar solo un array o algo así. Luego, este efecto se utiliza para realizar la estimación personalizada, en la que tengo un intervalo que se ejecuta cada un milisegundo y llama a esta función, que es source.connect, en la que conecto el Analyzer, que hemos visto antes en la imagen anterior, a la señal en
5. Estimación y Detección de Tono
Luego, la señal de audio se convierte en números que representan la amplitud. Se realiza la autocorrelación para obtener una representación más legible. Luego se calcula la frecuencia y se determina la nota correspondiente en función de la frecuencia. La clase de utilidad principal realiza la estimación y detección de tono utilizando los valores autocorrelacionados.
para realizar la estimación y el análisis de tiempo de frecuencia. Luego, este intervalo continúa llamando a esta función, por lo que conectas el audio y comienzas a obtener la señal, porque GetPitch, es un método que se utiliza para realizar estimaciones de frecuencia. Esto es GetPitch. Entonces, utilizas este método que es Analyzer, GetFloatTimeDomainData que hace lo que mencioné anteriormente. Entonces, convierte todos los datos de la señal en números en este búfer, que es una matriz float32, y, como puedes notar, cada elemento de la matriz tiene un número y representa la amplitud de la señal, por lo que realiza un seguimiento de una representación gráfica. Por lo tanto, esta representación gráfica se puede ver como esta matriz. Eso me recuerda eso. Luego, después de eso, después de tener esta matriz, puedo realizar la autocorrelación, porque necesito limpiar este tipo de representación gráfica, en esta señal, y obtener algo que sea más legible. Entonces, realizo la autocorrelación y, como puedes ver, la matriz a la derecha, CorrelatedValues, es más fácil de entender, porque tiene todos los números entre 1 y -1, y si realizas un seguimiento de una representación gráfica con este tipo de números, obtienes la representación gráfica que hemos visto anteriormente con la función de autocorrelación. Por lo tanto, es más legible. Esta función realiza la autocorrelación, luego puedes calcular la frecuencia después de tener ese tipo de representación gráfica. Una vez que tienes la frecuencia, puedes determinar qué nota es, porque, como dijimos antes, cada nota está representada por una frecuencia. Entonces, si conoces la frecuencia, sabes qué nota se está tocando. Entonces, estableces la nota. La nota es esta. He creado este tipo, que tiene el nombre, una octava, por lo que el número de octavas de la nota, el sentido de, y la frecuencia. El sentido de es el número de centésimas que la nota está desafinada de la frecuencia fundamental. Por ejemplo, si la frecuencia fundamental es 440, y el usuario está tocando 435 hertzios, la nota está desafinada en 5 centésimas. Entonces, le digo al usuario que está desafinado, por lo que puedo señalar el indicador de otra manera. Luego, esta es la clase de utilidad principal que se utiliza para realizar la estimación y detección de tono. Por lo tanto, obtenemos valores autocorrelacionados y estas funciones los normalizan. La función de normalización se utiliza para obtener todos los valores entre 1 y -1, para normalizar todos los datos que tenemos, y realiza un escalado máximo absoluto, que es un algoritmo que encuentra los valores absolutos máximos y divide todos los elementos por este valor máximo. Por lo tanto, después de realizar esta función, obtienes todos los elementos entre 1 y -1. Por lo tanto, es más legible y es más fácil realizar cálculos con este tipo de datos. Luego, realizamos la autocorrelación con este método, autocorrelación con retardo, y si te fijas, hay este tipo de variable que se llama rms, que es la raíz cuadrada de la media cuadrática. ¿Qué es la raíz cuadrada de la media cuadrática? Es la medida de la magnitud del volumen de la señal. Entonces, utilizo esta variable para almacenar la magnitud de la señal y filtrar la señal si está por debajo de un umbral. Por lo tanto, quiero filtrar todos los datos que no sean fuertes porque puede ser incluso yo haciendo ruido en mi escritorio o algo así. Solo quiero las notas que sean fuertes, y la raíz cuadrada de la media cuadrática se calcula realizando la raíz cuadrada de la media cuadrática como esta fórmula. Por lo tanto, obtienes el valor que representa
6. Conversión de Señal y Detección de Frecuencia
La señal de audio se convierte en código utilizando una fórmula matemática. La frecuencia de la señal se detecta calculando el pico más alto en la función. Luego, la frecuencia se utiliza para obtener el tipo de nota. Se informa al usuario si están desafinados de la frecuencia original por un cierto número de centésimas.
la intensidad del sonido. Esta es la función principal, la función de autocorrelación. Como puedes ver, es la misma que la fórmula matemática en la que desplazas la señal y la multiplicas por eso, y luego sumas este valor multiplicado en una serie. Entonces, es esta función matemática. Solo convertí la función matemática en code. Puedes verlo en el repositorio. Y luego, una vez que tienes la señal que está clara, es decir, la función periódica, puedes detectar la frecuencia. Este método es el de obtener frecuencia. Podría haber utilizado, por ejemplo, incluso el método de cruce por cero, pero decidí utilizar otro método en el que se calcula el pico más alto en la función. En este caso, es el pico rojo, y si sabes cuánto tiempo ha transcurrido entre un pico y otro, puedes calcular fácilmente la frecuencia dividiendo la frecuencia de muestreo, que es el tiempo transcurrido entre un pico y otro, por el índice del pico más grande. Así obtienes la frecuencia. Incluso puedes intentar utilizando el cruce por cero, contando el número de veces que esta trama, esta función, cruza el cero, obtengo el número de oscilaciones y lo divido por la frecuencia fundamental. Por lo tanto, puedes obtenerlo incluso con otros algoritmos, pero utilicé este porque quería probar y utilizar otro enfoque. Luego, tienes esta utilidad que es obtener nota a partir de frecuencia. Entonces, a partir de la frecuencia, obtienes el tipo de nota que te mostré anteriormente. Obtienes el nombre de la nota, las octavas, el desafinamiento y la frecuencia. Aquí puedes ver que hay un método llamado obtener número MIDI a partir de la altura o incluso obtener el desafinamiento a partir de la altura. Escribí estos métodos, pero no inventé este método porque son estándar en la industria, ya que en MIDI music tienes estas fórmulas para convertir la frecuencia, los desafinamientos en lo que desees. Por ejemplo, obtener el número MIDI a partir de la altura es lo mismo que convertir solo la fórmula matemática que se puede encontrar en línea.
7. Mejoras y Conclusión
Estudié a fondo el tema y proporcioné la referencia de la fórmula y el código fuente en el repositorio. Después de obtener el objeto de la nota, se determina la precisión de afinación del usuario. La visualización de datos se logra utilizando la biblioteca de gráficos React Go. El proyecto tiene margen de mejora, como restablecer el indicador cuando no se detecta ninguna nota, cancelación de ruido y detección de acordes. También es una opción explorar otros algoritmos de detección de frecuencia como YIM. No dudes en consultar el proyecto, estudiar la estimación de frecuencia y conectarte conmigo en las redes sociales.
en code. Así que estudié mucho sobre este tema e inserté incluso en el repositorio, en el code, la referencia y el origen de esta fórmula. Así que puedes ir a verlos, leerlos, intentar implementarlos y encontrar tus propias soluciones. Pero esto es estándar.
Luego, después de usar este tipo de método, obtener la nota a partir de la frecuencia, se obtiene un objeto que es la nota. Tienes el nombre que es A, la octava que es 4, el desafinamiento que es 5, y la frecuencia que es 435. Y aquí, en este caso, el usuario no está afinado porque está tocando una frecuencia de 435, pero la frecuencia de referencia es 440. Así que le digo al usuario que está cinco desafinamientos por debajo de la frecuencia original. Pasemos a la parte de visualización de datos y veamos qué podemos lograr con eso. Así que quería hacerlo de manera sencilla porque el objetivo principal era la parte matemática y la parte de visualización. Así que decidí utilizar una biblioteca llamada React Go chart. Es muy fácil. Le das como propiedad la frecuencia. Por ejemplo, lo siento. Le das como propiedad el porcentaje. Entonces, el indicador se mueve con el porcentaje. Así que calculo a partir de la frecuencia el porcentaje del indicador y lo paso como propiedad, y muestra el indicador que sube y baja según la frecuencia en la que el usuario está tocando. E incluso aquí, muestro el nombre de la nota y la número de la nota y la frecuencia fácilmente sin ninguna biblioteca porque es solo data. Es una cadena y un número y lo coloco dentro de un componente. Después de eso, finalmente estamos llegando al final porque vamos a hablar sobre todas las mejoras que se pueden hacer en este proyecto. Bueno, como dije, fue un proyecto con fines de investigación, pero se pueden hacer muchas mejoras. Quiero hacer muchas mejoras mientras sigo estudiando este tema y, por ejemplo, puedes challenge a ti mismo y restablecer el indicador si no se detecta ninguna nota porque este indicador, cuando se detecta una nota, no vuelve a su posición inicial. Es muy fácil de solucionar, pero si quieres avanzar, incluso puedes mejorar la cancelación de ruido y el preprocesamiento de la señal. Puedes filtrar la señal ruidosa o, por ejemplo, intentar detectar qué acorde está tocando el usuario, no solo la nota individual sino el acorde. Es mucho más difícil de hacer, pero es muy interesante hacer la ciencia detrás de eso e incluso puedes estudiar otros algoritmos para realizar la detección de frecuencia como YIM, pero te advierto que esto es un agujero de conejo porque hay mucho detrás de todos estos algoritmos, así que la elección es tuya. Puedes ir a verlo, consultar el proyecto, tratar de entenderlo, estudiar mucho sobre la estimación de frecuencia y cálculo de frecuencia, y te digo, es muy divertido estudiar estas cosas porque nunca pensé que había algo así detrás del afinador de guitarra, pero este proyecto fue el resultado de una larga investigación y fue un proyecto divertido y te challenge a hacer lo mismo, a ver el code e intentar implementarlo. Así que gracias por tenerme aquí. Comparto el code aquí en esta diapositiva. Puedes escanear el código QR y puedes encontrarlo para acceder al repositorio que es de código abierto. Si te gusta, agrégame en mis redes sociales. Puedes encontrarme en Twitter, en LinkedIn, donde quieras. Así podemos estar en contacto, hablar sobre estimación de frecuencia, podemos hablar sobre React y otras cosas relacionadas con la informática. Ha sido un placer y te deseo un buen día.
Comments