Síntesis de audio Python
- Síntesis de audio Python
-
Utilice
IPython.display
para la síntesis aditiva en Python - Cree varias formas de onda básicas con síntesis aditiva en Python
-
Use
pyaudio
para generar síntesis de audio en Python
Hoy aprenderemos sobre la síntesis de audio y cómo podemos generar sonido usando Python.
Síntesis de audio Python
La síntesis de sonido o síntesis de audio genera sonido electrónicamente (usando hardware o software) que imita la voz humana o instrumentos musicales.
La síntesis es principalmente para música, donde un dispositivo/instrumento electrónico conocido como sintetizador se usa para grabar e interpretar música.
Ahora, el punto es ¿podemos usar Python para generar este tipo de sonidos simples, por ejemplo, onda sinusoidal? ¿Tenemos algún módulo para eso, o cómo podemos crear uno propio?
Aprendamos las diferentes formas a continuación.
Utilice IPython.display
para la síntesis aditiva en Python
-
Primero, importamos los módulos y bibliotecas necesarios. Importamos
IPython
para mostrar el reproductor de sonido,numpy
para trabajar con matrices,matplotlib
para trazar gráficos (lo haremos mientras generamos formas de onda básicas) ymath
para usar funciones matemáticas.import IPython.display as ipd import numpy import math import matplotlib.pyplot as plt
-
Establezca la frecuencia de muestreo. Aquí, establecemos el
sample_rate
con22050
.sample_rate = 22050
-
Haz la forma de onda sinusoidal.
def makesine(frequency, duration): t = numpy.linspace(0, duration, math.ceil(sample_rate * duration)) x = numpy.sin(2 * numpy.pi * frequency * t) return x
En este paso, definimos una función
makesine()
, que tomafrecuencia
yduración
como parámetros. Utilizamos los métodosduration
ennumpy.linspace()
yfrequency
ennumpy.sin()
para reutilizar formas de onda sinusoidales puras.Tenga en cuenta que
numpy.linspace()
crea secuencias numéricas, o podemos decir que devuelve números/muestras espaciados uniformemente w.r.t. intervalo (comienzo, parada). Es similar anumpy.arange()
pero toma un número de muestra (num
) como parámetro en lugar depaso
.Puedes encontrar más sobre eso aquí.
Por otro lado,
numpy.sin()
calcula el seno trigonométrico para todas lasx
especificadas (una matriz de elementos). -
Ejecute
makesine()
.output = numpy.array(()) y = makesine(261.63, 0.5) # C for 0.5 seconds output = numpy.concatenate((output, y)) y = makesine(293.66, 0.5) # D for 0.5 seconds output = numpy.concatenate((output, y)) y = makesine(329.63, 0.5) # E for 0.5 seconds output = numpy.concatenate((output, y)) ipd.Audio(output, rate=sample_rate)
A continuación, ejecutamos
makesine()
varias veces para formar una nueva forma de onda con unafrecuencia
y unaduración
especificadas. Después de eso, usamosnumpy.concatenate()
para colocarlos todos juntos.Puede encontrar el código fuente de trabajo completo a continuación con la salida respectiva.
-
Aquí está el código fuente completo.
import IPython.display as ipd import matplotlib.pyplot as plt import numpy import math sample_rate = 22050 def makesine(frequency, duration): t = numpy.linspace(0, duration, math.ceil(sample_rate * duration)) x = numpy.sin(2 * numpy.pi * frequency * t) return x output = numpy.array(()) y = makesine(261.63, 0.5) # C for 0.5 seconds output = numpy.concatenate((output, y)) y = makesine(293.66, 0.5) # D for 0.5 seconds output = numpy.concatenate((output, y)) y = makesine(329.63, 0.5) # E for 0.5 seconds output = numpy.concatenate((output, y)) ipd.Audio(output, rate=sample_rate)
PRODUCCIÓN:
Cree varias formas de onda básicas con síntesis aditiva en Python
Hemos terminado con la forma de onda sinusoidal básica. Experimentemos con varias formas de onda básicas con frecuencias en múltiplos enteros usando frecuencia * i
; aquí, i
es el contador de 1
y se incrementa en 1
cada vez.
Necesitamos suavizar estas ondas sinusoidales en amplitudes predefinidas (amplist
), que luego se apilan en la “salida”. Para que eso suceda, debemos crear una función llamada addsyn()
de la siguiente manera:
def addsyn(frequency, duration, amplist):
i = 1
t = numpy.linspace(0, duration, math.ceil(sample_rate * duration))
output = numpy.zeros(t.size)
for amp in amplist:
x = numpy.multiply(makesine(frequency * i, duration), amp)
output = output + x
i += 1
if numpy.max(output) > abs(numpy.min(output)):
output = output / numpy.max(output)
else:
output = output / -numpy.min(output)
return output
Dentro de addsyn()
, inicializamos una nueva salida
. Dentro del ciclo for
, hacemos la forma de onda sinusoidal con una amplitud máxima (amp
); aquí, frecuencia
es un múltiplo entero.
Luego, lo sumamos a la salida y lo guardamos en la variable salida
. A continuación, nos aseguramos de que la amplitud máxima no supere 1
y devolvemos la salida
.
Ahora, podemos ejecutar el siguiente fragmento de código para hacer solo una onda sinusoidal armónica y hacer un gráfico para ella que muestre solo 0.005
segundos para ver esta forma de onda.
t = numpy.linspace(0, 1, sample_rate)
sinewave = addsyn(440, 1, [1])
plt.plot(t, sinewave)
plt.xlim(0, 0.005)
ipd.Audio(sinewave, rate=sample_rate)
El código fuente completo sería el siguiente.
Código de ejemplo:
import IPython.display as ipd
import matplotlib.pyplot as plt
import numpy
import math
sample_rate = 22050
def addsyn(frequency, duration, amplist):
i = 1
t = numpy.linspace(0, duration, math.ceil(sample_rate * duration))
output = numpy.zeros(t.size)
for amp in amplist:
x = numpy.multiply(makesine(frequency * i, duration), amp)
output = output + x
i += 1
if numpy.max(output) > abs(numpy.min(output)):
output = output / numpy.max(output)
else:
output = output / -numpy.min(output)
return output
t = numpy.linspace(0, 1, sample_rate)
sinewave = addsyn(440, 1, [1])
plt.plot(t, sinewave)
plt.xlim(0, 0.005)
ipd.Audio(sinewave, rate=sample_rate)
PRODUCCIÓN:
síntesis de audio de Python - forma de onda sinusoidal básica armónica.wav
Ahora, podemos jugar con diferentes valores de la función addsyn()
para obtener diferentes resultados. Vea otro ejemplo para crear una onda cuadrada a continuación.
Código de ejemplo:
import IPython.display as ipd
import matplotlib.pyplot as plt
import numpy
import math
sample_rate = 22050
def addsyn(frequency, duration, amplist):
i = 1
t = numpy.linspace(0, duration, math.ceil(sample_rate * duration))
output = numpy.zeros(t.size)
for amp in amplist:
x = numpy.multiply(makesine(frequency * i, duration), amp)
output = output + x
i += 1
if numpy.max(output) > abs(numpy.min(output)):
output = output / numpy.max(output)
else:
output = output / -numpy.min(output)
return output
t = numpy.linspace(0, 1, sample_rate)
square_wave = addsyn(440, 1, [1, 0, 0.349, 0, 0.214, 0, 0.156, 0, 0.121, 0])
plt.plot(t, square_wave)
plt.xlim(0, 0.005)
ipd.Audio(square_wave, rate=sample_rate)
PRODUCCIÓN:
síntesis de audio de Python: forma de onda sinusoidal básica cuadrada.wav
Use pyaudio
para generar síntesis de audio en Python
Aquí, usaremos pyaudio
, un módulo de Python que graba audio con Python.
-
Primero, importamos las bibliotecas necesarias:
math
para realizar funciones matemáticas ypyaudio
para generar ondas.import math # import needed modules import pyaudio # sudo apt-get install python-pyaudio
-
Inicializa
pyaudio
.PyAudio = pyaudio.PyAudio
-
Inicializar variables.
bit_rate = 16000 frequency = 500 length = 1 bit_rate = max(bit_rate, frequency + 100) number_of_frames = int(bit_rate * length) rest_frames = number_of_frames % bit_rate wave_data = ""
Aquí, inicializamos el
bit_rate
con16000
, que muestra el número de fotogramas por segundo. Lafrecuencia
se establece en500
Hz que denota las ondas por segundo (261.63=nota C4
) mientras que lalongitud
se inicializa con1
.Después de eso, usamos la función
max()
para encontrar el máximo debit_rate
yfrequency+100
y asignamos el valor máximo abit_rate
. Luego, multiplicamos elbit_rate
y lalongitud
, lo convertimos al tipoint
usando la funciónint()
y lo asignamos anumber_of_frames
.A continuación, usamos el operador de módulo (
%
) para dividirnumber_of_frames
conbit_rate
y asignamos el resto arest_frames
. Finalmente, inicializamoswave_data
con una cadena vacía. -
Generar ondas.
for x in range(number_of_frames): wave_data = wave_data + chr( int(math.sin(x / ((bit_rate / frequency) / math.pi)) * 127 + 128) ) for x in range(rest_frames): wave_data = wave_data + chr(128)
Aquí, usamos dos bucles
for
que iteran hasta elnumber_of_frames
para generar ondas. -
Grabar audio.
p = PyAudio() stream = p.open( format=p.get_format_from_width(1), channels=1, rate=bit_rate, output=True ) stream.write(wave_data) stream.stop_stream() stream.close() p.terminate()
Aquí, creamos una instancia de
PyAudio
, guardamos la referencia enp
, y usamos esa referencia para abrir una secuencia usando el métodoopen()
, que grabará audio. A continuación, escribimoswave_data
, detuvimos la transmisión y la cerramos. Finalmente, termine también la instanciaPyAudio
(p
).Puede leer sobre
open()
,write()
,stop_stream()
yclose()
aquí en detalle. -
Aquí está el código fuente completo.
import math import pyaudio PyAudio = pyaudio.PyAudio bit_rate = 16000 frequency = 500 length = 1 bit_rate = max(bit_rate, frequency + 100) number_of_frames = int(bit_rate * length) rest_frames = number_of_frames % bit_rate wave_data = "" for x in range(number_of_frames): wave_data = wave_data + chr( int(math.sin(x / ((bit_rate / frequency) / math.pi)) * 127 + 128) ) for x in range(rest_frames): wave_data = wave_data + chr(128) p = PyAudio() stream = p.open( format=p.get_format_from_width(1), channels=1, rate=bit_rate, output=True ) stream.write(wave_data) stream.stop_stream() stream.close() p.terminate()
Una vez que ejecutamos el código anterior, podemos escuchar una onda. Tenga en cuenta que no estamos guardando esta ola en un archivo
.wav
.Puede leer aquí para aprender a guardar en un archivo
.wav
.