那里有大量的音乐和语音数据。还有有趣的应用程序与之配合使用。我们将向您展示如何使用 Python 将声音可视化。

近年来,音频数据分析变得越来越重要。各大科技公司纷纷推出流行的虚拟助手产品,这些产品在世界各地的智能手机和家庭中越来越常见。它们主要是在分析语音数据并从中提取信息的模型的基础上开发的。

音频数据分析的应用范围很广,这是一个值得探索的丰富主题。在本文中,我们将重点介绍音频数据分析过程的一个基本部分——绘制音频文件的波形和频谱。

本文面向具有更多数据分析背景知识的人士。如果您是初学者,正在寻找一些资料来快速掌握数据科学,请查看 此主题 .

打开WAV文件

音频文件有多种格式。您可能熟悉 MP3,它使用有损压缩来存储数据。FLAC 等格式使用无损压缩,允许从压缩数据中完美重建原始数据。我们的音频文件采用 WAV(波形音频文件)格式,未经压缩。因此文件大小可能会很大。

我们将要查看的声音文件是一首以钢琴开始的快节奏歌曲。铃声和拍手声等其他声音贯穿整首歌曲,在曲目的两个点处有吉他弹奏部分。值得一提的是音频录音中的这些特征,因为我们可以在稍后绘制波形和频谱时识别其中的一些特征。

要打开我们的 WAV 文件,我们使用 wave 模块,可以按如下方式导入和调用它:

>>> import wave
>>> wav_obj = wave.open('file.wav', 'rb')

' rb ' 模式返回一个 wave_read 对象。使用 ' wb ' 打开文件会返回一个 wave_write 对象,该对象的方法与前一个对象不同。您还可以使用语句 with 打开文件,如我们 在此处 那样。如果您有兴趣了解有关如何以编程方式处理大量文件的更多信息,请查看 本文 .

声波是连续量,需要以一定的时间间隔进行采样才能将其数字化。采样率量化了每秒采集的声音样本数量。我们可以使用以下方法访问此信息:

>>> sample_freq = wav_obj.getframerate()
>>> sample_freq
44100

采样频率量化了每秒的采样数。在本例中,采样频率为每秒 44,100 次,相当于 CD 音质。单个帧或样本的数量由以下公式给出:

>>> n_samples = wav_obj.getnframes()
>>> n_samples
5384326

我们现在可以计算音频文件的长度(以秒为单位):

>>> t_audio = n_samples/sample_freq
>>> t_audio
122.09356009070295

音频文件以立体声录制,即在两个独立的音频通道中录制。这给人一种声音来自两个不同方向的感觉。我们可以按如下方式检查通道数:

>>> n_channels = wav_obj.getnchannels()
>>> n_channels
2

下一步是获取信号的值,即该时间点的波的幅度。为此,我们可以使用该 readframes() 方法,该方法接受一个参数 n,定义要读取的帧数:

>>> signal_wave = wav_obj.readframes(n_samples)

上的内置函数 type() 自行检查 signal_wave 。要从中获取信号值,我们必须求助于 numpy:

>>> import numpy as np
>>> signal_array = np.frombuffer(signal_wave, dtype=np.int16)

这将以一维数组的形式返回两个通道的所有数据。如果你检查 的形状 signal_array ,你会发现它有 10,768,652 个元素,正好是 n_samples * n_channels 。要将数据拆分到各个通道,我们可以使用一个巧妙的小数组切片技巧:

>>> l_channel = signal_array[0::2]
>>> r_channel = signal_array[1::2]

现在,我们的左右声道是分开的,都包含 5,384,326 个整数来表示信号的幅度。

接下来,我们展示一些如何绘制信号值的示例。我们在这里将数据存储在数组中,但对于许多数据科学应用程序来说,pandas 非常有用。查看 这篇 关于可视化存储在数组中的数据的 DataFrame .

绘制信号幅度

在绘制信号值之前,我们需要计算每次采样的时间。这只是以秒为单位的轨道总长度除以样本数。我们可以使用 linspace() from 来 numpy 创建一个时间戳数组:

>>> times = np.linspace(0, n_samples/sample_freq, num=n_samples)

对于绘图,我们将使用 pyplot 中的类 matplotlib 。如果您需要一些有关使用 Python 进行绘图的背景资料,我们有一些文章。以下是 的简介 第 1 部分 和 第 2 部分 matplotlib .

为了简单起见,我们只绘制一个通道的信号。让我们设置图形,并绘制如下时间序列:

>>> import matplotlib.pyplot as plt
>>> plt.figure(figsize=(15, 5))
>>> plt.plot(times, l_channel)
>>> plt.title('Left Channel')
>>> plt.ylabel('Signal Value')
>>> plt.xlabel('Time (s)')
>>> plt.xlim(0, t_audio)
>>> plt.show()

这将在新窗口中打开下图:

How to Visualize Sound in Python

我们看到振幅在前 6 秒内逐渐增大,此时铃声和拍手声开始出现。铃声中有两个短暂的停顿,分别位于 31.5 秒和 44.5 秒,这在信号值中很明显。第二次停顿后,主乐器在吉他和钢琴之间交替,这在信号中大致可见,其中吉他部分的振幅较低。然后,在曲目结尾处有一个振幅较低的结尾。

绘制频谱

现在,让我们看一下频谱,也称为声谱图。这是不同频率信号强度的直观表示,向我们展示了哪些频率在时间函数中占主导地位:

>>> plt.figure(figsize=(15, 5))
>>> plt.specgram(l_channel, Fs=sample_freq, vmin=-20, vmax=50)
>>> plt.title('Left Channel')
>>> plt.ylabel('Frequency (Hz)')
>>> plt.xlabel('Time (s)')
>>> plt.xlim(0, t_audio)
>>> plt.colorbar()
>>> plt.show()

以下图表在新窗口中打开:

How to Visualize Sound in Python

在上面的绘图代码中,vmin 和 vmax 被选择来显示主导此录音的较低频率。事实上,整个音轨的主导频率低于 2.5 kHz。您可以看到不同乐器和音效的效果,特别是在约 10 kHz 到 15 kHz 的频率范围内。每种乐器和音效在频谱中都有自己的特征。

从这往哪儿走

使用 Python 绘制波形和频谱为更深入地分析声音数据奠定了基础。也许您可以进一步量化录音每个部分的频率。与钢琴部分相比,吉他部分的平均频率是多少?在这里,我们只查看了一个通道。这里材料的另一个扩展是绘制两个通道并查看它们的比较情况。尝试绘制通道之间的差异,您会看到波形和频谱中出现了一些新的有趣特征。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部