Generación de música con Python
Generación de música con Python
El reconocimiento de voz se refiere al proceso de reconocer y comprender el lenguaje hablado. La entrada viene en forma de datos de audio, y los reconocedores de voz procesarán estos datos para extraer información significativa de ellos. Esto tiene muchos usos prácticos, como dispositivos controlados por voz, transcripción del lenguaje hablado en palabras, sistemas de seguridad, etc.
Las señales de voz son de naturaleza muy versátil. Existen muchas variaciones del habla en el mismo idioma. Hay diferentes elementos para el habla, como el lenguaje, la emoción, el tono, el ruido, el acento, etc. Es difícil definir rígidamente un conjunto de reglas que puedan constituir discurso. Incluso con todas estas variaciones, los humanos son realmente buenos para comprender todo esto con relativa facilidad. Por lo tanto, necesitamos máquinas para entender el habla de la misma manera.
Durante las últimas décadas, los investigadores han trabajado en varios aspectos del habla, como identificar al hablante, comprender palabras, reconocer acentos, traducir el habla, etc. Entre todas estas tareas, el reconocimiento automático de voz ha sido el punto focal de atención para muchos investigadores. En este tutorial, aprenderemos cómo construir un reconocedor de voz.
[wp_ad_camp_1]
Visualizando las señales
Echemos un vistazo a cómo leer un archivo de audio y visualizar la señal. Este será un buen punto de partida, y nos dará una buena comprensión de la estructura básica de las señales de audio. Antes de comenzar, debemos entender que los archivos de audio son versiones digitalizadas de señales de audio reales. Las señales de audio reales son ondas complejas de valor continuo. Para guardar una versión digital, tomamos muestras de la señal y la convertimos en números. Por ejemplo, el habla se muestrea comúnmente a 44100 Hz. Esto significa que cada segundo de la señal se divide en 44100 partes, y los valores en estas marcas de tiempo se almacenan. En otras palabras, almacena un valor cada 1/44100 segundos. Como la frecuencia de muestreo es alta, sentimos que la señal es continua cuando la escuchamos en nuestros reproductores multimedia.
¿Cómo visualizar las señales?
En un python notebook importaremos los paquetes.
%matplotlib inline import numpy as np import matplotlib.pyplot as plt from scipy.io import wavfile
Utilizaremos el paquete wavfile para leer el archivo de audio del archivo de entrada input_read.wav . Esto lo podrá obtener en el repositorio clickando aquí.
# Leyendo el archivo wav sampling_freq, audio = wavfile.read('input_read.wav')
Y ahora imprimamos los detalles de nuestro archivo wav.
[wp_ad_camp_2]
# Imprimiendo los parámetros print ('\nShape:', audio.shape) print ('Datatype:', audio.dtype) print ('Duration:', round(audio.shape[0] / float(sampling_freq), 3), 'seconds')
La señal de audio se almacena como datos enteros con signo de 16 bits. Necesitamos normalizar estos valores:
# Normalizando los valores audio = audio / (2.**15)
Extraigamos los primeros 30 valores para poderlos graficar.
# Extraer los primeros 30 valores para graficar audio = audio[:30]
El eje X es el eje del tiempo. Construyamos este eje, considerando el hecho de que debería escalarse utilizando el factor de frecuencia de muestreo:
# Construyendo el eje del tiempo x_values = np.arange(0, len(audio), 1) / float(sampling_freq) # Conviertiendo a segundos x_values *= 1000
Y procedamos a graficar.
# Graficando la señal cortada plt.plot(x_values, audio, color='black') plt.xlabel('Tiempo (ms)') plt.ylabel('Amplitud') plt.title('Señal de Audio') plt.show()
Obtendremos algo así.
Transformada de Fourier
Las señales de audio consisten en una mezcla compleja de ondas sinusoidales de diferentes frecuencias, amplitudes y fases. Las ondas sinusoidales también se conocen como sinusoides. Hay mucha información oculta en el contenido de frecuencia de una señal de audio. De hecho, una señal de audio se caracteriza fuertemente por su contenido de frecuencia. Todo el mundo del habla y la música se basa en este hecho. Antes de continuar, necesitará algunos conocimientos sobre las transformadas de Fourier. Una actualización rápida la puede encontrar aquí. Ahora, echemos un vistazo a cómo transformar una señal de audio en el dominio de frecuencia.
[wp_ad_camp_3]
Lea el archivo input_freq.wav que lo encuentra en el repositorio y normalizamos.
La señal de audio es solo una matriz NumPy. Entonces, puede extraer la longitud usando el siguiente código:
# Leyendo el archivo input_freq sampling_freq, audio = wavfile.read('input_freq.wav') # Normalizando los valores audio = audio / (2.**15) # Extraer longitud len_audio = len(audio)
Apliquemos la transformada de Fourier. La señal de transformación de Fourier se refleja a lo largo del centro, por lo que solo necesitamos tomar la primera mitad de la señal transformada. Nuestro objetivo final es extraer la señal de potencia. Entonces, cuadramos los valores en la señal en preparación para esto:
# Aplicando la transformada de Fourier transformed_signal = np.fft.fft(audio) half_length = int(np.ceil((len_audio + 1) / 2.0)) transformed_signal = abs(transformed_signal[0:half_length]) transformed_signal /= float(len_audio) transformed_signal **= 2
Debemos ahora extraer la longitud de la señal transformada, duplicar la señal de acuerdo a la longitud y convertir a decibeles.
# Extraer la longitud de la señal transformada len_ts = len(transformed_signal) # Casos pares e impares if len_audio % 2: transformed_signal[1:len_ts] *= 2 else: transformed_signal[1:len_ts-1] *= 2 # Extrayendo la potencia en decibeles dB power = 10 * np.log10(transformed_signal)
El eje X es el eje del tiempo. Necesitamos escalar esto de acuerdo con la frecuencia de muestreo y luego convertirlo en segundos para posteriormente graficar:
# Construyendo el eje del tiempo x_values = np.arange(0, half_length, 1) * (sampling_freq / len_audio) / 1000.0 # Graficando plt.figure() plt.plot(x_values, power, color='black') plt.xlabel('Freq (in kHz)') plt.ylabel('Power (in dB)') plt.show()
Y nuestra imagen será algo mas o menos así.
[wp_ad_camp_4]
Generando señales de audio
Podemos usar NumPy para generar señales de audio. Como se mencionó anteriormente, las señales de audio son mezclas complejas de sinusoides. Por lo tanto, lo tendremos en cuenta cuando generemos nuestra propia señal de audio.
Necesitamos primero definir el archivo de salida donde se almacenará el audio generado. Lo pueden descargar aquí.
# Archivo que será guardado output_file = 'output_generated.wav'
Especifiquemos los parámetros de generación de audio. Queremos generar una señal larga de tres segundos con una frecuencia de muestreo de 44100 y una frecuencia tonal de 587 Hz. Los valores en el eje de tiempo irán de -2 * pi a 2 * pi.
Tambiéne generemos el eje del tiempo y la señal de audio. La señal de audio es una sinusoide simple con los parámetros mencionados anteriormente y agreguemos un poco de ruido.
# Especificando los parámetros del audio duration = 3 # segundos sampling_freq = 44100 # Hz tone_freq = 587 min_val = -2 * np.pi max_val = 2 * np.pi # Generar audio t = np.linspace(min_val, max_val, duration * sampling_freq) audio = np.sin(2 * np.pi * tone_freq * t) # Añadir ruido noise = 0.4 * np.random.rand(duration * sampling_freq) audio += noise
Necesitamos escalar los valores a enteros de 16 bits antes de almacenarlos:
# Escalar a 16 bits los valores enteros scaling_factor = pow(2,15) - 1 audio_normalized = audio / np.max(np.abs(audio)) audio_scaled = np.int16(audio_normalized * scaling_factor) # Escribir el archivo de salida write(output_file, sampling_freq, audio_scaled)
Luego hacemos lo que ya hemos hecho anteriormente.
# Extraer los primeros 100 valores audio = audio[:100] # Construyendo el eje del tiempo x_values = np.arange(0, len(audio), 1) / float(sampling_freq) # Convirtiendo a segundos x_values *= 1000 # Graficando la señal plt.plot(x_values, audio, color='black') plt.xlabel('Tiempo (ms)') plt.ylabel('Amplitud') plt.title('Señal de audio') plt.show()
Generación de música
Ahora que sabemos cómo generar audio, usemos este principio para sintetizar algo de música. Puedes consultar este enlace. Este enlace enumera varias notas, como A, G, D, etc., junto con sus frecuencias correspondientes. Usaremos esto para generar música simple.
[wp_ad_camp_5]
Los pasos son los siguientes:
- Importamos la librería json.
- Defina una función para sintetizar un tono, en función de los parámetros de entrada.
- Construya la muestra de audio utilizando los argumentos de entrada, como la amplitud y la frecuencia.
- Definamos la función principal. En el repositorio encontrará un archivo JSON llamado tone_freq_map.json, que contiene algunas notas junto con sus frecuencias.
- Generemos algunas notas en secuencia para darle una sensación musical. Defina una secuencia de notas junto con sus duraciones en segundos.
- Repite esta lista y llama a la función de sintetizador para cada uno de ellos.
import json # Sintetizar def synthesizer(freq, duration, amp=1.0, sampling_freq=44100): # Construir el eje del tiempo t = np.linspace(0, duration, duration * sampling_freq) # Construir la señal de audio audio = amp * np.sin(2 * np.pi * freq * t) return audio.astype(np.int16) if __name__=='__main__': # Archivo json que contiene el mapa de las notas tone_map_file = 'tone_freq_map.json' # Leyendo el mapa de frecuencias with open(tone_map_file, 'r') as f: tone_freq_map = json.loads(f.read()) # Configurando parámetros para la nota G input_tone = 'G' duration = 2 # seconds amplitude = 10000 sampling_freq = 44100 # Hz # Generando el tono synthesized_tone = synthesizer(tone_freq_map[input_tone], duration, amplitude, sampling_freq) # Escribiendo al archivo de salida write('output_tone.wav', sampling_freq, synthesized_tone)
Puede abrir el archivo output_tone_seq.wav en su reproductor multimedia y escucharlo. ¡Puedes sentir la música!
Todo el repositorio completo lo puedes encontrar en mi github.
Si te gustó este tutorial o tienes alguna pregunta por favor deja tu comentario.
-
This web site certainly has all the info I needed about this subject and
didn't know who to ask. -
Well done & written my friend.
I've only just begun writing very recently and have seen that many blogs merely rehash olld ideas
but add very little of benefit. It's terrific to seee a beneficial write-up
of some actual value too me.
It is actuqlly going on my list of things I need too emulate
being a new blogger. Reader engagement annd materiial value aree king.Some superb ideas; you have definitely got on my list of blos to watch!
Continue thee terrific work!
Welll done,
Domini -
Really great visual appeal on this website, I'd value it 10.
-
Hey I know this is off topic but I was wondering if you knew
of any widgets I could add to my blog that automatically tweet my newest twitter updates.
I've been looking for a plug-in like this for quite some time and was hoping maybe you would have some experience with
something like this. Please let me know if
you run into anything. I truly enjoy reading your blog and I look forward to your
new updates. -
Hola.
Yo estoy interesado en realizar un proyecto python enlazado a arduino.
Lo que quiero es que al escuchar un sonido dado por algún instrumento, el código me devuelva la nota que fue tocada por ese instrumento.
¿Tiene algún tutorial que trate ese tema?
¿O puede darme alguna idea?
Pienso que aplicar la transformada de fourier es necesario y este artículo me parece muy similar.
Saludos.
Deja una respuesta
Lo siento, debes estar conectado para publicar un comentario.
You actually make it seem so easy with your presentation but I find
this matter to be actually something which I think I would never understand.
It seems too complicated and extremely broad for me.
I am looking forward for your next post, I'll try to
get the hang of it!