Librosa教程
本节涵盖了使用librosa进行开发的基础知识,包括包概述、基本和高级用法以及与scikit-learn包的集成。我们将假设对Python和NumPy/SciPy有基本的熟悉程度。
概述
librosa包的结构是由子模块组成的集合:
- librosa.beat
- 用于估计节奏和检测节拍事件的函数。
- librosa.core
- 核心功能包括从磁盘加载音频、计算各种频谱图表示以及音乐分析中常用的各种工具。为了方便起见,此子模块中的所有功能都可以直接从顶级librosa.*命名空间访问。
- librosa.decompose
- 用于谐波-打击声源分离(HPSS)和使用scikit-learn实现的矩阵分解方法进行通用频谱图分解的函数。
- librosa.display
- 使用matplotlib进行可视化和显示例程。
- librosa.effects
- 时域音频处理,如音高移位和时间拉伸。此子模块还为分解子模块提供时域包装器。
- librosa.feature
- 特征提取和操作。这包括低级特征提取,如色度图、Mel频谱图、MFCC以及各种其他频谱和节奏特征。还提供了特征操作方法,如delta特征和内存嵌入。
- librosa.filters
- 滤波器生成(色度、伪CQT、CQT等)。这些主要是由librosa的其他部分使用的内部函数。
- librosa.onset
- 检测和起始强度计算。
- librosa.segment
- 对于结构性分割有用的函数,例如递归矩阵构建、时间滞后表示和顺序约束聚类。
- librosa.sequence
- 用于顺序建模的函数。各种形式的Viterbi解码,以及构建转移矩阵的辅助函数。
- librosa.util
- 辅助实用程序(归一化、填充、居中等)。
快速入门
在深入了解之前,我们将通过一个简单的示例程序进行演示。
# Beat tracking example import librosa # 1. Get the file path to an included audio example filename = librosa.example('nutcracker') # 2. Load the audio as a waveform `y` # Store the sampling rate as `sr` y, sr = librosa.load(filename) # 3. Run the default beat tracker tempo, beat_frames = librosa.beat.beat_track(y=y, sr=sr) print('Estimated tempo: {:.2f} beats per minute'.format(tempo)) # 4. Convert the frame indices of beat events into timestamps beat_times = librosa.frames_to_time(beat_frames, sr=sr)
程序的第一步:
filename = librosa.example('nutcracker')
获取librosa附带的音频示例文件的路径。在此步骤之后,filename将是一个包含示例音频文件路径的字符串变量。
第二步:
y, sr = librosa.load(filename)
加载并解码音频为表示为一维NumPy浮点数组的时间序列y。变量sr包含y的采样率,即每秒的样本数。默认情况下,所有音频都混合为单声道并在加载时重新采样为22050 Hz。这种行为可以通过向librosa.load提供额外的参数来覆盖。
接下来,我们运行节拍跟踪器:
tempo, beat_frames = librosa.beat.beat_track(y=y, sr=sr)
节拍跟踪器的输出是对节奏(以每分钟的拍数为单位)的估计,以及与检测到的节拍事件对应的帧号数组。
这里的帧对应于信号(y)的短窗口,每个窗口之间相隔hop_length = 512个样本。librosa使用居中帧,因此第k帧围绕样本k * hop_length居中。
下一个操作将帧号beat_frames转换为时间戳:
beat_times = librosa.frames_to_time(beat_frames, sr=sr)
现在,beat_times将是一个与检测到的节拍事件对应的时间戳数组(以秒为单位)。
beat_times的内容应该如下所示:
7.43 8.29 9.218 10.124 ...
高级用法
这里我们将介绍一个更高级的例子,整合谐波-打击声分离、多种频谱特征和节拍同步特征聚合。
# Feature extraction example import numpy as np import librosa # Load the example clip y, sr = librosa.load(librosa.ex('nutcracker')) # Set the hop length; at 22050 Hz, 512 samples ~= 23ms hop_length = 512 # Separate harmonics and percussives into two waveforms y_harmonic, y_percussive = librosa.effects.hpss(y) # Beat track on the percussive signal tempo, beat_frames = librosa.beat.beat_track(y=y_percussive, sr=sr) # Compute MFCC features from the raw signal mfcc = librosa.feature.mfcc(y=y, sr=sr, hop_length=hop_length, n_mfcc=13) # And the first-order differences (delta features) mfcc_delta = librosa.feature.delta(mfcc) # Stack and synchronize between beat events # This time, we'll use the mean value (default) instead of median beat_mfcc_delta = librosa.util.sync(np.vstack([mfcc, mfcc_delta]), beat_frames) # Compute chroma features from the harmonic signal chromagram = librosa.feature.chroma_cqt(y=y_harmonic, sr=sr) # Aggregate chroma features between beat events # We'll use the median value of each feature between beat frames beat_chroma = librosa.util.sync(chromagram, beat_frames, aggregate=np.median) # Finally, stack all beat-synchronous features together beat_features = np.vstack([beat_chroma, beat_mfcc_delta])
这个例子基于我们已经在快速入门示例中介绍过的工具,所以这里我们将专注于新的部分。
第一个区别是使用效果模块进行时间序列谐波-打击声分离:
y_harmonic, y_percussive = librosa.effects.hpss(y)
这一行的结果是将时间序列y分离成两个时间序列,包含信号的谐波(音调)和打击声(瞬态)部分。y_harmonic和y_percussive与y具有相同的形状和持续时间。
进行这种操作的动机有两方面:首先,打击元素往往是节奏内容更强的指示器,可以帮助提供更稳定的节拍跟踪结果;其次,打击元素可以通过在所有频带上贡献能量来污染音调特征表示(如色度),因此没有它们会更好。
接下来,我们引入特征模块并从原始信号y中提取梅尔频率倒谱系数:
mfcc = librosa.feature.mfcc(y=y, sr=sr, hop_length=hop_length, n_mfcc=13)
此函数的输出是矩阵mfcc,它是一个形状为(n_mfcc, T)的numpy.ndarray(其中T表示以帧为单位的跟踪持续时间)。请注意,我们在这里使用与节拍跟踪器相同的hop_length,因此检测到的beat_frames值对应于mfcc的列。
我们引入的第一类特征操作是delta,它计算其输入列之间的(平滑)一阶差值:
mfcc_delta = librosa.feature.delta(mfcc)
生成的矩阵mfcc_delta与输入mfcc具有相同的形状。
第二类特征操作是sync,它在采样索引(例如,节拍帧)之间聚合其输入列:
beat_mfcc_delta = librosa.util.sync(np.vstack([mfcc, mfcc_delta]), beat_frames)
这里,我们将mfcc和mfcc_delta矩阵垂直堆叠在一起。此操作的结果是一个矩阵beat_mfcc_delta,其行数与输入相同,但列数取决于beat_frames。每个beat_mfcc_delta[:, k]将是从beat_frames[k]到beat_frames[k+1]之间的输入列的平均值。(beat_frames将被扩展以覆盖整个范围[0, T],以便所有数据都被考虑在内。)
接下来,我们仅使用谐波分量计算色度图:
chromagram = librosa.feature.chroma_cqt(y=y_harmonic, sr=sr)
在这一行之后,chromagram将是一个形状为(12, T)的numpy.ndarray,每一行对应于一个音高类别(例如,C,C#等)。chromagram的每一列都通过其峰值值进行归一化,尽管可以通过设置norm参数来覆盖这种行为。
一旦我们有了色度图和节拍帧列表,我们再次在节拍事件之间同步色度:
beat_chroma = librosa.util.sync(chromagram, beat_frames, aggregate=np.median)
这一次,我们将默认的聚合操作(如上文用于MFCCs的平均)替换为中位数。一般来说,可以在这里提供任何统计汇总功能,包括np.max(),np.min(),np.std()等。
最后,所有特征再次垂直堆叠:
beat_features = np.vstack([beat_chroma, beat_mfcc_delta])
从而得到一个形状为(12 + 13 + 13, # beat intervals)的特征矩阵beat_features。