在 TensorFlow 中过滤音频信号

Filtering audio signal in TensorFlow

我正在构建一个基于音频的深度学习模型。作为预处理的一部分,我想增强数据集中的音频。我想做的一项增强是应用 RIR(房间脉冲响应)功能。我正在与 Python 3.9.5TensorFlow 2.8.

合作

在 Python 中,如果 RIR 作为 n 个抽头的有限脉冲响应 (FIR) 给出,则使用 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)

运行 在所有文件上循环可能需要很长时间。在 TensorFlow 数据集上使用 TensorFlow map 实用程序进行操作:

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

使用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)

我有两个问题:

  1. 这种方式是否正确且足够快(50,000 个文件不到一分钟)?
  2. 有没有更快的方法?例如。用内置的 TensforFlow 函数替换 SciPy 函数。我没有找到 lfilterSciPy's convolve.
  3. 的等价物

这是您可以采用的一种方法

请注意,张量流函数旨在接收具有多个通道的批量输入,并且过滤器可以具有多个输入通道和多个输出通道。令 N 为批量大小 I、输入通道数、F 滤波器宽度、L 输入宽度和 O 通道数输出通道。使用 padding='SAME' 它将形状 (N, L, I) 的输入和形状 (F, I, O) 的过滤器映射到形状 (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)])