音频课程文档
音频数据介绍
并获得增强的文档体验
开始使用
音频数据介绍
从本质上讲,声波是一种连续信号,这意味着它在给定时间内包含无限数量的信号值。这给期望有限数组的数字设备带来了问题。为了通过数字设备进行处理、存储和传输,连续声波需要转换为一系列离散值,即数字表示。
如果你查看任何音频数据集,你会发现包含声音片段的数字文件,例如文本旁白或音乐。你可能会遇到不同的文件格式,例如.wav
(波形音频文件)、.flac
(自由无损音频编解码器)和.mp3
(MPEG-1 音频层 3)。这些格式主要在于它们如何压缩音频信号的数字表示。
让我们来看看我们如何从连续信号到达这种表示。模拟信号首先由麦克风捕获,麦克风将声波转换为电信号。然后,电信号通过模数转换器进行数字化,通过采样获得数字表示。
采样和采样率
采样是在固定时间步长测量连续信号值的过程。采样波形是离散的,因为它在均匀间隔处包含有限数量的信号值。

来自维基百科文章的插图:采样(信号处理)
采样率(也称为采样频率)是一秒钟内采样的数量,以赫兹(Hz)为单位测量。作为参考,CD 质量音频的采样率为 44,100 Hz,这意味着每秒采样 44,100 次。相比之下,高分辨率音频的采样率为 192,000 Hz 或 192 kHz。训练语音模型常用的采样率为 16,000 Hz 或 16 kHz。
采样率的选择主要决定了可以从信号中捕获的最高频率。这也被称为奈奎斯特极限,正好是采样率的一半。人耳可听的语音频率低于 8 kHz,因此以 16 kHz 采样语音就足够了。使用更高的采样率不会捕获更多信息,只会导致处理此类文件的计算成本增加。另一方面,以过低的采样率采样音频会导致信息丢失。以 8 kHz 采样的语音会听起来沉闷,因为无法以这种速率捕获更高频率。
在处理任何音频任务时,确保数据集中所有音频示例都具有相同的采样率非常重要。如果你打算使用自定义音频数据对预训练模型进行微调,则你的数据的采样率应与模型预训练数据匹配。采样率决定了连续音频样本之间的时间间隔,这会影响音频数据的时间分辨率。考虑一个示例:5 秒的 16,000 Hz 采样率的声音将表示为 80,000 个值序列,而相同的 5 秒的 8,000 Hz 采样率的声音将表示为 40,000 个值序列。解决音频任务的 Transformer 模型将示例视为序列,并依赖注意力机制来学习音频或多模态表示。由于不同采样率的音频示例的序列不同,模型将难以在采样率之间进行泛化。重采样是使采样率匹配的过程,是音频数据预处理的一部分。
振幅和位深
采样率告诉你样本多久取一次,那么每个样本中的值到底是什么?
声音是由气压变化产生的,其频率在人类可听范围内。声音的振幅描述了在任何给定时刻的声压级,以分贝(dB)为单位测量。我们将振幅感知为响度。举例来说,正常的说话声音低于 60 dB,而摇滚音乐会可能达到 125 dB 左右,这已接近人类听力的极限。
在数字音频中,每个音频样本记录了音频波在某个时间点的振幅。样本的位深决定了描述此振幅值的精确度。位深越高,数字表示就越能忠实地近似原始连续声波。
最常见的音频位深是 16 位和 24 位。每个都是二进制术语,表示将振幅值从连续值转换为离散值时可以量化的可能步数:16 位音频为 65,536 步,24 位音频为惊人的 16,777,216 步。由于量化涉及将连续值四舍五入为离散值,因此采样过程会引入噪声。位深越高,这种量化噪声越小。实际上,16 位音频的量化噪声已经足够小,听不见了,通常不需要使用更高的位深。
您可能还会遇到 32 位音频。它将样本存储为浮点值,而 16 位和 24 位音频使用整数样本。32 位浮点值的精度为 24 位,使其与 24 位音频具有相同的位深。浮点音频样本预期位于 [-1.0, 1.0] 范围内。由于机器学习模型天生就处理浮点数据,因此音频必须首先转换为浮点格式才能用于训练模型。我们将在下一节预处理中看到如何实现这一点。
与连续音频信号一样,数字音频的振幅通常以分贝 (dB) 表示。由于人类听觉本质上是呈对数性质的——我们的耳朵对安静声音中的微小波动比对响亮声音中的波动更敏感——如果振幅以分贝表示,声音的响度更容易解释,分贝也是对数单位。真实世界音频的分贝刻度从 0 dB 开始,代表人类能听到的最安静的声音,而更响亮的声音具有更大的值。然而,对于数字音频信号,0 dB 是最大可能振幅,而所有其他振幅都是负数。一个快速的经验法则:每减少 6 dB,振幅就减半,而低于 -60 dB 的任何声音通常都是听不见的,除非你把音量调得非常大。
音频作为波形
您可能见过声音以波形的形式可视化,它绘制了样本值随时间的变化,并说明了声音振幅的变化。这也被称为声音的时域表示。
这种可视化类型对于识别音频信号的特定特征非常有用,例如单个声音事件的时序、信号的整体响度以及音频中存在的任何不规则或噪声。
要绘制音频信号的波形,我们可以使用一个名为 `librosa` 的 Python 库。
pip install librosa
我们以库中自带的“trumpet”(小号)声音为例。
import librosa
array, sampling_rate = librosa.load(librosa.ex("trumpet"))
该示例以音频时间序列(这里我们称之为 `array`)和采样率(`sampling_rate`)的元组形式加载。让我们使用 librosa 的 `waveshow()` 函数来查看此声音的波形。
import matplotlib.pyplot as plt
import librosa.display
plt.figure().set_figwidth(12)
librosa.display.waveshow(array, sr=sampling_rate)

这会绘制信号的振幅(y 轴)和时间(x 轴)。换句话说,每个点对应于此声音采样时获取的单个采样值。另请注意,librosa 返回的音频已经是浮点值,并且振幅值确实在 [-1.0, 1.0] 范围内。
将音频可视化并同时聆听是理解您正在处理的数据的有用工具。您可以查看信号的形状、观察模式、学习发现噪声或失真。如果您以某种方式预处理数据,例如归一化、重采样或滤波,您可以直观地确认预处理步骤已按预期应用。训练模型后,您还可以可视化发生错误的样本(例如在音频分类任务中)以调试问题。
频谱
另一种可视化音频数据的方法是绘制音频信号的频谱,也称为频域表示。频谱是使用离散傅里叶变换(DFT)计算的。它描述了构成信号的各个频率及其强度。
让我们使用 numpy 的 `rfft()` 函数,通过对相同的小号声音进行 DFT,来绘制其频谱。虽然可以绘制整个声音的频谱,但查看一个小区域会更有用。这里我们将在前 4096 个样本上进行 DFT,这大致是第一个音符的长度。
import numpy as np
dft_input = array[:4096]
# calculate the DFT
window = np.hanning(len(dft_input))
windowed_input = dft_input * window
dft = np.fft.rfft(windowed_input)
# get the amplitude spectrum in decibels
amplitude = np.abs(dft)
amplitude_db = librosa.amplitude_to_db(amplitude, ref=np.max)
# get the frequency bins
frequency = librosa.fft_frequencies(sr=sampling_rate, n_fft=len(dft_input))
plt.figure().set_figwidth(12)
plt.plot(frequency, amplitude_db)
plt.xlabel("Frequency (Hz)")
plt.ylabel("Amplitude (dB)")
plt.xscale("log")

这会绘制此音频片段中存在的各种频率分量的强度。频率值在 x 轴上,通常以对数刻度绘制,而它们的振幅在 y 轴上。
我们绘制的频谱显示了几个峰值。这些峰值对应于正在播放的音符的谐波,其中较高谐波更安静。由于第一个峰值约为 620 Hz,因此这是 E♭ 音符的频谱。
DFT 的输出是一个复数数组,由实部和虚部组成。使用 `np.abs(dft)` 取模可以从频谱图中提取振幅信息。实部和虚部之间的角度提供了所谓的相位谱,但在机器学习应用中通常会丢弃此信息。
您使用 `librosa.amplitude_to_db()` 将振幅值转换为分贝刻度,以便更容易地看到频谱中的细节。有时人们使用功率谱,它测量能量而不是振幅;这只是一个振幅值平方的频谱。
音频信号的频谱与其波形包含完全相同的信息——它们只是查看相同数据(这里是小号声音的前 4096 个样本)的两种不同方式。波形绘制了音频信号随时间变化的振幅,而频谱则可视化了在固定时间点上各个频率的振幅。
频谱图
如果我们想看看音频信号中的频率是如何变化的呢?小号演奏几个音符,它们都有不同的频率。问题在于频谱只显示了给定瞬间频率的冻结快照。解决方案是进行多个 DFT,每个 DFT 只覆盖一小段时间,并将生成的频谱堆叠在一起形成频谱图。
频谱图绘制了音频信号随时间变化的频率内容。它允许您在一个图中同时查看时间、频率和振幅。执行此计算的算法是 STFT 或短时傅里叶变换。
频谱图是您可用的最有用的音频工具之一。例如,在处理音乐录音时,您可以看到各种乐器和人声轨道以及它们对整体声音的贡献。在语音中,您可以识别不同的元音,因为每个元音都以特定的频率为特征。
让我们使用 librosa 的 `stft()` 和 `specshow()` 函数来绘制相同小号声音的频谱图。
import numpy as np
D = librosa.stft(array)
S_db = librosa.amplitude_to_db(np.abs(D), ref=np.max)
plt.figure().set_figwidth(12)
librosa.display.specshow(S_db, x_axis="time", y_axis="hz")
plt.colorbar()

在此图中,x 轴表示时间,与波形可视化相同,但现在 y 轴表示频率(单位为 Hz)。颜色的强度表示在每个时间点上频率分量的振幅或功率,以分贝(dB)为单位测量。
频谱图是通过将音频信号分成短片段(通常持续几毫秒),并计算每个片段的离散傅里叶变换以获得其频谱来创建的。然后将得到的频谱沿时间轴堆叠在一起以创建频谱图。此图像中的每个垂直切片都对应一个单独的频谱,从顶部看。默认情况下,`librosa.stft()` 将音频信号分成 2048 个样本的片段,这在频率分辨率和时间分辨率之间提供了良好的权衡。
由于频谱图和波形是相同数据的不同视图,因此可以使用逆 STFT 将频谱图转换回原始波形。但是,这除了振幅信息外还需要相位信息。如果频谱图是由机器学习模型生成的,它通常只输出振幅。在这种情况下,我们可以使用相位重建算法(例如经典的 Griffin-Lim 算法)或使用称为声码器的神经网络,从频谱图重建波形。
频谱图不仅仅用于可视化。许多机器学习模型会以频谱图作为输入——而不是波形——并以频谱图作为输出。
现在我们知道了什么是频谱图以及它是如何生成的,让我们来看看它在语音处理中广泛使用的一个变体:梅尔频谱图。
梅尔频谱图
梅尔频谱图是频谱图的一种变体,常用于语音处理和机器学习任务。它与频谱图相似,都显示音频信号随时间变化的频率内容,但频率轴不同。
在标准频谱图中,频率轴是线性的,以赫兹 (Hz) 为单位测量。然而,人类听觉系统对低频变化的敏感度高于高频变化,并且这种敏感度随着频率的增加而对数下降。梅尔刻度是一种感知刻度,它近似于人耳的非线性频率响应。
要创建梅尔频谱图,与以前一样使用 STFT,将音频分成短片段以获取一系列频谱。此外,每个频谱都会通过一组滤波器(即梅尔滤波器组)进行处理,以将频率转换为梅尔刻度。
让我们看看如何使用 librosa 的 `melspectrogram()` 函数绘制梅尔频谱图,该函数为我们执行所有这些步骤。
S = librosa.feature.melspectrogram(y=array, sr=sampling_rate, n_mels=128, fmax=8000)
S_dB = librosa.power_to_db(S, ref=np.max)
plt.figure().set_figwidth(12)
librosa.display.specshow(S_dB, x_axis="time", y_axis="mel", sr=sampling_rate, fmax=8000)
plt.colorbar()

在上面的示例中,`n_mels` 表示要生成的梅尔频带数量。梅尔频带定义了一组频率范围,这些范围将频谱划分为感知上有意义的成分,使用一组滤波器的形状和间距来模拟人耳对不同频率的响应方式。`n_mels` 的常见值为 40 或 80。`fmax` 表示我们关心的最高频率(单位为 Hz)。
与常规频谱图一样,通常将梅尔频率分量的强度表示为分贝。这通常被称为对数梅尔频谱图,因为转换为分贝涉及对数运算。上面的示例使用 `librosa.power_to_db()`,因为 `librosa.feature.melspectrogram()` 创建功率频谱图。
创建梅尔频谱图是一个有损操作,因为它涉及过滤信号。将梅尔频谱图转换回波形比将常规频谱图转换回波形更困难,因为它需要估计被丢弃的频率。这就是为什么需要像 HiFiGAN 声码器这样的机器学习模型来从梅尔频谱图生成波形。
与标准频谱图相比,梅尔频谱图可以捕获更多对人类感知有意义的音频信号特征,使其成为语音识别、说话人识别和音乐流派分类等任务中的热门选择。
现在您已经知道如何可视化音频数据示例,快去看看您最喜欢的声音是什么样的吧!:)
< > 在 GitHub 上更新