Estoy construyendo un modelo de aprendizaje profundo basado en audio. Como parte del procesamiento previo, quiero aumentar el audio en mis conjuntos de datos. Un aumento que quiero hacer es aplicar la función RIR (respuesta de impulso de la habitación). Estoy trabajando con Python 3.9.5 y TensorFlow 2.8 .
En Python, la forma estándar de hacerlo es, si el RIR se da como una respuesta de impulso finito (FIR) de n toques, está usando SciPy lfilter
import numpy as np from scipy import signal import soundfile as sf h = np.load("rir.npy") x, fs = sf.read("audio.wav") y = signal.lfilter(h, 1, x) La ejecución en bucle de todos los archivos puede llevar mucho tiempo. Hacerlo con la utilidad de map TensorFlow en conjuntos de datos de TensorFlow:
# define filter function def h_filt(audio, label): h = np.load("rir.npy") x = audio.numpy() y = signal.lfilter(h, 1, x) return tf.convert_to_tensor(y, dtype=tf.float32), label # apply it via TF map on dataset aug_ds = ds.map(h_filt) Usando tf.numpy_function :
tf_h_filt = tf.numpy_function(h_filt, [audio, label], [tf.float32, tf.string]) # apply it via TF map on dataset aug_ds = ds.map(tf_h_filt)Tengo dos preguntas:
lfilter o convolve de SciPy .Aquí hay una forma en que podrías hacer
Tenga en cuenta que la función de flujo de tensor está diseñada para recibir lotes de entradas con múltiples canales, y el filtro puede tener múltiples canales de entrada y múltiples canales de salida. Sea N el tamaño del lote I , el número de canales de entrada, F el ancho del filtro, L el ancho de entrada y O el número de canales de salida. Al usar padding='SAME' , asigna una entrada de forma (N, L, I) y un filtro de forma (F, I, O) a una salida de forma (N, L, O) .
import numpy as np from scipy import signal import tensorflow as tf # data to compare the two approaches x = np.random.randn(100) h = np.random.randn(11) # h y_lfilt = signal.lfilter(h, 1, x) # Since the denominator of your filter transfer function is 1 # the output of lfiler matches the convolution y_np = np.convolve(h, x) assert np.allclose(y_lfilt, y_np[:len(y_lfilt)]) # now let's do the convolution using tensorflow y_tf = tf.nn.conv1d( # x must be padded with half of the size of h # to use padding 'SAME' np.pad(x, len(h) // 2).reshape(1, -1, 1), # the time axis of h must be flipped h[::-1].reshape(-1, 1, 1), # a 1x1 matrix of filters stride=1, padding='SAME', data_format='NWC') assert np.allclose(y_lfilt, np.squeeze(y_tf)[:len(y_lfilt)])