python - 在 Python 中比较两个音频信号(歌唱录音)之间的相似度

标签 python audio signal-processing wave

我正在开展一个项目,以比较某人的歌声与原艺术家的相似程度。主要对声音的音高感兴趣,看看它们是否合拍。

音频文件采用 .wav 格式,我已经能够使用 Wave 模块加载它们并将它们转换为 Numpy 数组。然后我构建了一个频率和一个时间向量来绘制信号。

raw_audio = wave.open("myAudio.WAV", "r")
audio = raw_audio.readframes(-1)
signal = np.frombuffer(audio, dtype='int16')
fs = raw_audio.getframerate()
timeDelta = 1/(2*fs)

#Get time and frequency vectors
start = 0
end = len(signal)*timeDelta
points = len(signal)

t = np.linspace(start, end, points)
f = np.linspace(0,fs,points)

如果我有另一个相同持续时间的信号(它们在大约 5-10 秒后着陆)。比较这两个信号相似性的最佳方法是什么?

我想过比较频域和自相关,但我觉得这两种方法都有很多缺点。

最佳答案

我面临着评估两个音频信号(一个是真实的,一个是由机器学习管道生成的)相似性的类似问题。我有信号部分,其中比较对时间非常关键(代表不同早期反射到达的峰值之间的时间差),为此我将尝试计算信号之间的互相关(更多信息请参见:https://www.researchgate.net/post/how_to_measure_the_similarity_between_two_signal )

由于两种不同声音的自然录音在时域上会有很大不同,因此这可能不适合您的问题。

对于频率信息(如音高和音色)更感兴趣的信号,我会在频域中工作。例如,您可以计算两个信号的短时 ffts (stft) 或 cqt(频谱的更具音乐性的表示,因为它映射到 Octave 音阶),然后通过计算均方误差 ( MSE)位于两个信号的时间窗口之间。在转换之前,您当然应该对信号进行标准化。使用 librosa 可以轻松完成 STFT、CQT 和标准化并进行可视化

see here: https://librosa.org/doc/latest/generated/librosa.util.normalize.html

here: https://librosa.org/doc/latest/generated/librosa.cqt.html?highlight=cqt

here: https://librosa.org/doc/latest/generated/librosa.stft.html

and here: https://librosa.org/doc/main/generated/librosa.display.specshow.html)

此方法有两点:

  1. 不要让你的时间窗口太短。人体光谱 声音从百赫兹范围内的某个地方开始 (https://av-info.eu/index.html?https&&&av-info.eu/audio/speech-level.html 这里 350 Hz 被指定为低端)。所以样本量 你的 stft-time-windows (或长度)至少应该是:

    (1 / 350 Hz) * sampling frequency

    因此,如果您的录音具有 44100 Hz 采样频率,您的时间 窗口必须至少

    (1 / 350 Hz) * 44100 Hz = 0.002857... sec * 44100 Samples / second = 126 Samples long.

    设为 128,这是一个更好的数字。这样你就可以保证 基频为350赫兹的声波仍然可以“看到” 在一个窗口中至少有一个完整的时期。当然更大 windows 将为您提供更精确的光谱表示。

  2. 在转换之前,您应该确保您的两个信号 正在比较同时代表相同的声音事件。所以 如果两位歌手唱的不是同一首歌,那么这一切都行不通 或速度不同或有不同的背景噪音 信号。前提是您只有以下内容的干录音: 声音和这些声音以相同的速度唱着同样的东西,你只是 需要确保信号开始对齐。一般来说,你 需要确保声音事件(例如 transient 、静音、 注)对齐。当一个信号中出现较长的 AAAH 声音时, 另一个信号中也应该是长的 AAAh 声音。你(们)能做到 通过增加 stft 窗口,您的评估会更加稳健 更进一步,这会降低时间分辨率(你会得到更少 信号的频谱表示)但更多的声音事件是 在一个时间窗口内一起评估。

您当然可以在整个长度上为每个信号生成一个 fft,但如果您在相等长度的短时间窗口上生成 stfts 或 cqts(或更适合人类听觉的其他一些变换),结果将更有意义,然后计算每对时间窗口的均方误差(信号 1 的第一个时间窗口和信号 2 的第一个窗口,然后是第二个窗口对,然后是第三个窗口对,依此类推)。

希望这有帮助。

关于python - 在 Python 中比较两个音频信号(歌唱录音)之间的相似度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71712529/

相关文章:

python - QDate 到 QString

c++ - WASAPI 何时添加了对 AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM 的支持?

java - 我是否在 Java 中正确实现了这个基本的低通滤波器(Phrogz 的滤波器!)?

python - 填充列日期值,直到达到另一个日期值,然后继续填充新达到的值

python - 当存在另一个带有文本的标签时,lxml 库不会提取给定 html 标签中的文本

audio - XNA无法创建AudioEngine

c++ - 使用窗口函数 : implementation problem 进行 FIR 滤波

python - 如何估计噪声层后面的高斯分布?

python - 类实例没有用于在类外部传递对象的属性 'function_name' - python

audio - 检测音频流中的广告?