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]

Índice

    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
    

     

    Te puede interesar:  Clases en Python [Guía Completa]

    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[] / 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(, 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í.

    señal de audio

     

    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[:half_length])
    transformed_signal /= float(len_audio)
    transformed_signal **= 2
    

     

    Te puede interesar:  Clasificación de imágenes multietiquetas usando redes neuronales con python

    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(, 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]

    fourier

    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:

    Te puede interesar:  Clasificación de Imágenes usando redes neuronales con python

    # 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(, 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()
    

     

    señal generada

     

    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(, 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.

    1. 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!

    2. Efrain dice:

      This web site certainly has all the info I needed about this subject and
      didn't know who to ask.

    3. Hester dice:

      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

    4. Becky dice:

      Really great visual appeal on this website, I'd value it 10.

    5. Aidan dice:

      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.

    6. José Antonio dice:

      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.

      1. Rubén dice:

        HOla!
        Qué interesante idea, recuerdo que una vez vi algo parecido, lo estaré buscando y te lo compartiré.

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

    Subir