【问题标题】:How to skip to a specific frame in a given spectrogram file如何跳到给定频谱图文件中的特定帧
【发布时间】:2019-07-14 17:05:58
【问题描述】:

我在跳转到找到 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 是给定功能集的文件路径。 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 行结果的列表,这些结果似乎不是自然地由行分隔的。

【问题讨论】:

    标签: signal-processing librosa


    【解决方案1】:

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

    要计算n_mel 的值,您需要查看librosa.filters.mel,它表示默认值为128。另一方面,t 的帧数在librosa.util.frame 内部计算为@987654337 @,其中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
    

    【讨论】:

    • 如果 7392 响应时间帧,一秒构成多少帧,即给定帧中有多少列条目?
    • 每一列都是一个时间范围。原始输入文件中可能有 3784704 到 3786240 个样本,频率为 22050Hz(最多有 1536 个填充样本),因此约为 171.7 秒。 1 秒钟,您将有大约 41 帧。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-18
    • 1970-01-01
    • 2019-11-29
    • 2019-11-05
    • 2011-12-16
    • 2010-10-11
    相关资源
    最近更新 更多