Python: time stretch wave files - 三种方法的比较

Python: time stretch wave files - comparison between three methods

我正在对语音数据集进行一些数据增强,我想 stretch/squeeze 时域中的每个音频文件。

我发现了以下三种方法,但我不确定哪一种是最好的或更优化的方法:

dimension = int(len(signal) * speed)
res = librosa.effects.time_stretch(signal, speed)
res = cv2.resize(signal, (1, dimension)).squeeze()
res = skimage.transform.resize(signal, (dimension, 1)).squeeze()

但是,我发现 librosa.effects.time_stretch 向信号添加了不需要的回声(或类似的东西)。

所以,我的问题是:这三种方式的主要区别是什么?还有更好的方法吗?

librosa.effects.time_stretch(信号, 速度) (docs)

本质上,这种方法使用 stft (short time Fourier transform), stretches it using a phase vocoder 转换信号,并使用逆 stft 重构时域信号。通常,当这样做时,一个引入了一点 "phasiness",即金属碰撞声,因为相位无法 100% 重建。这可能就是您确定的 "echo."

请注意,虽然这种方法在时域中有效地拉伸了音频(即输入和输出都在时域中),但实际上是在频域中进行的。

cv2.resize(信号, (1, 维度)).squeeze() (docs)

所有这种方法所做的就是使用 bilinear interpolation 对给定信号进行插值。这种方法适用于图像,但我觉得不适合音频信号。你听过结果了吗?它听起来完全像原始信号 faster/slower 吗?我认为不仅节奏会发生变化,而且频率和其他影响也会发生变化。

skimage.transform.resize(信号, (维度, 1)).squeeze() (docs)

同样,这是针对图像而非声音的。除了插值 (spline interpolation with the order 1 by default), this function also does anti-aliasing for images. Note that this has nothing to do with avoiding audio aliasing effects (Nyqist/Aliasing),因此您可能应该通过传递 anti_aliasing=False 来关闭它。同样,我假设结果可能不是您想要的(改变频率、其他伪影)。

怎么办?

IMO,你有几个选择。

  1. 如果您输入 ML 算法的内容最终变成类似于 Mel 频谱图的东西,您可以简单地将其视为图像并使用 skimage 或 opencv 方法对其进行拉伸。频率范围将被保留。我在 this music tempo estimation paper.

  2. 中成功地使用了这种方法
  3. 使用更好的 time_stretch 库,例如rubberband. librosa is great, but its current time scale modification (TSM) algorithm is not state of the art. For a review of TSM algorithms, see for example this article.

  4. 忽略频率变化的事实,简单地定期向信号添加 0 个样本或定期从信号中删除样本(很像图像插值)。如果你不伸展太远,它可能仍然适用于数据扩充目的。毕竟文字内容没有变化,如果音频内容有更高或更低的频率。

  5. 将信号重新采样到另一个采样频率,例如44100 Hz -> 43000 Hz44100 Hz -> 46000 Hz 使用像 resampy and then pretend that it's still 44100 Hz. This still change the frequencies, but at least you get the benefit that resampy does proper filtering of the result so that you avoid the aforementioned aliasing 这样的库,否则会发生这种情况。