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

时间:2019-07-14 17:05:58

标签: signal-processing librosa

我在跳到here找到的melspec功能集的特定框架时遇到问题。从功能集中获取功能的目的是分析每秒节拍(BPS)的差异,以便我可以匹配两个音轨的BPS,以便在两个音轨之间混合或扭曲音轨的时间以同步音轨。两首音乐在一起。功能集确实指定了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行结果的列表,这些结果似乎并不是自然地由行分隔的。

1 个答案:

答案 0 :(得分:0)

您所指的sample file是128 x 7392值的矩阵。 为了更好地了解此文件的格式,您可以查看用于提取功能的extractFeatures.py脚本。您可能会注意到,melspec功能被描述为“非节拍同步”,并使用librosa.feature.melspectrogram计算,主要使用默认参数并产生S行的输出n_mel通过t列。

要弄清楚n_mel的值,您需要查看librosa.filters.mel,它指示默认值为128。另一方面,t的帧数是在内部计算的librosa.util.frame1 + int((len(y) - frame_length) / hop_length)相同,其中frame_length使用默认值2048,而hop_length使用默认值512。

总而言之,128行对应于128个MEL频率段,而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