如何跳到给定频谱图文件中的特定帧

How to skip to a specific frame in a given spectrogram file

我在跳转到找到的 melspec 功能集的特定帧时遇到问题 here. The aim of getting features from the feature set is to analyse the difference in beats per second (BPS) so that i can match up the BPS of two tracks in order to mix between the two tracks or warp the timing of the track to synchronise the two pieces of music together. The feature set does specify the following

Pre-extracted in the "feature" directory are space-delimited floating-point ASCII matrices: 
beat_synchronus: one beat-synchronus vector per line 
non-beat-synchronus: 512-sample hop frames @ 22050Hz sample rate, one vector per line one vector per line:"

我不太确定如何解释这一点 - melspec 是节拍同步还是非节拍同步,它在定界帧方面如何工作?

由于 this 的回答,我已经了解了帧持续时间,但我不知道如何将从帧持续时间获得的知识应用到导航到特定时间码的任务中或框架。我得到的最接近的是计算出偏移量除以帧来计算需要跳过多少帧才能达到偏移量(例如进入轨道 1 秒给出 2583 帧)。但是,该文件没有划分为行,据我所知,它只是一个连续的条目列表。这导致了给定帧的大小是多少的问题(如果这是正确的术语)是否需要跳过第二个条目的 2383 个条目才能到达正确的条目,或者是否是每个帧都有特定数量的条目,我需要跳过 2583 个大小为 x 的帧?什么是尺寸 x(512?)?

我已经能够打开 melspec 文件,但对于 melspec 文件,条目之间没有分隔符。它是一个连续的条目列表。

我目前的代码如下,用于计算帧的持续时间,以及偏移轨道中要跳过的帧数。然而,这并不表示给定帧的大小以及如何从 melspec 的文件中访问它。 spectrogram 是给定功能集的 file_path。 offset 是从曲目开始偏移的时间(以秒为单位)。

def skipToFrame(spectrogram, offset):
    SAMPLE_RATE =22050
    HOP_LENGTH = 512
    #work out the duration of each frame.
    FRAME_TIME = HOP_LENGTH/SAMPLE_RATE
    # work out how many frames are in the offset period (e.g 1 second).
    SHIFT_FRAMES = offset/FRAME_TIME

    # readlines of file so that offset is applied.
    with open(spectrogram) as feature_set:
        indices = int(SHIFT_FRAMES)
        for line in feature_set:
              print(line)
        feature_set.close()

这给出了 10 行结果的列表,这些结果似乎没有自然地按行分隔。

您指的 sample file 是一个 128 x 7392 值的矩阵。 为了更好地理解此文件的格式,您可以查看 extractFeatures.py script used to extract the features. You may notice that the melspec feature is described as "non-beat-synchronus" and computed using librosa.feature.melspectrogram,主要使用默认参数并生成 n_melt 列的输出 S

要计算出 n_mel 的值,您需要将 librosa.filters.mel, which indicates a default value of 128. The number of frames t on the other hand is computed internally in librosa.util.frame 视为 1 + int((len(y) - frame_length) / hop_length),其中 frame_length 使用默认值 2048,而 hop_length 使用默认值 512。

总而言之,128 行对应于 128 个 MEL-frequency 个 bin,7392 列对应于时间范围。 因此,您可以使用以下内容来提取感兴趣的列:

def skipToFrame(spectrogram, offset):
    SAMPLE_RATE =22050
    HOP_LENGTH = 512
    #work out the duration of each frame.
    FRAME_TIME = HOP_LENGTH/SAMPLE_RATE
    # work out how many frames are in the offset period (e.g 1 second).
    SHIFT_FRAMES = offset/FRAME_TIME

    # readlines of file so that offset is applied.
    with open(spectrogram) as feature_set:
        indices = int(SHIFT_FRAMES)
        for line in feature_set:
          print(line.split(" ")[indices])
        feature_set.close()

使用 numpy 您还可以读取整个频谱图并定位特定列:

import numpy as np

def skipToFrame(spectrogram, offset):
    SAMPLE_RATE =22050
    HOP_LENGTH = 512
    #work out the duration of each frame.
    FRAME_TIME = HOP_LENGTH/SAMPLE_RATE
    # work out how many frames are in the offset period (e.g 1 second).
    SHIFT_FRAMES = offset/FRAME_TIME

    data = np.loadtxt(spectrogram)
    column = int(SHIFT_FRAMES)
    print(data[:,column])

回到使用 librosa 完成特征提取的事实,您也可以考虑使用 librosa.core.time_to_frames 而不是手动计算帧数:

def skipToFrame(spectrogram, offset):
    SHIFT_FRAMES = librosa.core.time_to_frames(offset, sr=22050, hop_length=512, n_fft=2048)
    ...

最后一点,您应该知道每个时间帧都使用 2048 个样本,但它们重叠,因此每个连续帧相对于前一个样本前进 512 个样本。所以帧覆盖以下时间间隔:

frame #  | start (s) |  end (s)
================================
1        |   0.000   |   0.093
2        |   0.023   |   0.116
3        |   0.046   |   0.139
...
41       |   0.929   |   1.022
42       |   0.952   |   1.045
...
7392     | 171.619   | 171.712