46

Python处理音频信号实战 : 手把手教你实现音乐流派分类和特征提取

 5 years ago
source link: https://www.jiqizhixin.com/articles/2019-01-11-25?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1986年出版的《音乐心理学》一书中说到“人类和音乐遵循共同的规律”。研究发现,人类大脑的生理信号具有带直线区域的线性规律,在生理上具有普遍性,产生公式:S(f) 1 / f ɑ。

二十世纪八十年代,有专家研究巴赫《第一勃兰登堡协奏曲》的音乐信号时发现,音乐信号的功率谱与人类大脑生理信号的功率谱相似,符合1/f信号公式。还发现, 音乐信号α越靠近数值1越好听 ,从科学上找到一个近似参数来判定音乐的悦耳度。2012年加拿大麦吉尔大学音乐系主任分析发现,音乐节奏也满足这个规律,α值为0.8。不同音乐体裁的α值不一样,所以也可以用这个数值反推音乐的风格体裁。不同作曲家风格音乐的α值不一样,但是作曲家们所作出来的各种风格体裁的音乐的参数是相似的。

现在的公司使用音乐分类,既可以向客户提供推荐,也可以仅仅作为产品。确定音乐类型是朝这个方向迈出的第一步。事实证明,机器学习技术在从大量数据库中提取趋势和模式方面非常成功。同样的原则也适用于音乐分析。

在本文中,我们将研究如何用Python处理音频/音乐信号,再利用所学的技能将音乐片段分类为不同的类型。

使用Python进行音频处理

声音以具有诸如频率、带宽、分贝等参数的音频信号的形式表示,典型的音频信号可以表示为幅度和时间的函数。 aA7VVf6.jpg!web

这些声音有多种格式,使计算机可以读取和分析它们。例如:

  • mp3格式

  • WMA(Windows Media Audio)格式

  • wav(波形音频文件)格式

音频库

Python有一些很棒的音频处理库,比如Librosa和PyAudio。还有一些内置的模块用于一些基本的音频功能。

我们将主要使用两个库进行音频采集和回放:

1. Librosa

它是一个Python模块,通常用于分析音频信号,但更倾向于音乐。它包括用于构建MIR(音乐信息检索)系统的nuts 和 bolts。示例和教程: https://librosa.github.io/librosa/

安装

pip install librosa
or
conda install -c conda-forge librosa

为了提供更多的音频解码能力,您可以安装随许多音频解码器一起提供的ffmpeg。

2. IPython.display.Audio

IPython.display.Audio 让您直接在jupyter笔记本中播放音频。

加载音频文件

import librosa
audio_path = '../T08-violin.wav'
x , sr = librosa.load(audio_path)
print(type(x), type(sr))
<class 'numpy.ndarray'> <class 'int'>
print(x.shape, sr)
(396688,) 22050

这会将音频时间序列作为numpy数组返回,默认采样率(sr)为22KHZ mono。我们可以通过以下方式更改此行为:

librosa.load(audio_path, sr=44100)

以44.1KHz重新采样,或禁用重新采样。采样率是每秒传输的音频样本数,以Hz或kHz为单位。

librosa.load(audio_path, sr=None)

播放音频

使用IPython.display.Audio播放音频。

import IPython.display as ipd
ipd.Audio(audio_path)

然后返回jupyter笔记本中的音频小部件,如下图所示,这个小部件在这里不起作用,但它可以在你的笔记本中使用,你甚至可以使用mp3或WMA格式作为音频示例。

可视化音频

波形

我们可以绘制音频数组librosa.display.waveplot:

%matplotlib inline
import matplotlib.pyplot as plt
import librosa.display
plt.figure(figsize=(14, 5))
librosa.display.waveplot(x, sr=sr)

这里,我们有波形幅度包络图。 uQZFr2Y.jpg!web

谱图

谱图是通过视觉表示频谱的频率、声音或其他信号,因为它们随时间变化。频谱图有时被称为超声波仪,声纹或语音图。当数据在3D图中表示时,它们可以称为waterfalls。在二维阵列中,第一轴是频率,而第二轴是时间。

我们可以使用显示频谱图: librosa.display.specshow.

X = librosa.stft(x)
Xdb = librosa.amplitude_to_db(abs(X))
plt.figure(figsize=(14, 5))
librosa.display.specshow(Xdb, sr=sr, x_axis='time', y_axis='hz')
plt.colorbar()

j6fUVzi.jpg!web 纵轴表示频率(从0到10kHz),横轴表示剪辑的时间。由于我们看到所有动作都发生在频谱的底部,我们可以将频率轴转换为对数轴。

librosa.display.specshow(Xdb, sr=sr, x_axis='time', y_axis='log')
plt.colorbar()

yumAFnU.jpg!web 写音频

librosa.output.write_wav 将NumPy数组保存到WAV文件。

librosa.output.write_wav('example.wav', x, sr)

创建音频信号

现在让我们创建一个220Hz的音频信号,音频信号是一个numpy数组,所以我们将创建一个并将其传递给音频函数。

import numpy as np
sr = 22050 <em># sample rate</em>
T = 5.0    <em># seconds</em>
t = np.linspace(0, T, int(T*sr), endpoint=False) <em># time variable</em>
x = 0.5*np.sin(2*np.pi*220*t)<em># pure sine wave at 220 Hz</em>
Playing the audio
ipd.Audio(x, rate=sr) <em># load a NumPy array</em>
Saving the audio
librosa.output.write_wav('tone_220.wav', x, sr)

特征提取

每个音频信号都包含许多特征。但是,我们必须提取与我们试图解决的问题相关的特征。提取要使用它们进行分析的特征的过程称为特征提取,让我们详细研究一些特征。

  • 过零率

该特征在语音识别和音乐信息检索中都被大量使用。对于像金属和岩石那样的高冲击声,它通常具有更高的值。让我们计算示例音频片段的过零率。

# Load the signal
x, sr = librosa.load('../T08-violin.wav')
#Plot the signal:
plt.figure(figsize=(14, 5))
librosa.display.waveplot(x, sr=sr)
# Zooming in
n0 = 9000
n1 = 9100
plt.figure(figsize=(14, 5))
plt.plot(x[n0:n1])
plt.grid()

nMFrQnY.jpg!web

似乎有6个过零点,让我们用librosa验证。

zero_crossings = librosa.zero_crossings(x[n0:n1], pad=False)
print(sum(zero_crossings))
  • 光谱质心

它指示声音的“质心”位于何处,并计算为声音中存在的频率的加权平均值。如果有两首歌曲,一首来自布鲁斯类型,另一首属于金属。与长度相同的布鲁斯流派歌曲相比,金属歌曲在最后有更多的频率。因此,布鲁斯歌曲的光谱质心将位于其光谱中间附近,而金属歌曲的光谱质心将朝向它的末端。

librosa.feature.spectral_centroid 计算信号中每帧的光谱质心:

spectral_centroids = librosa.feature.spectral_centroid(x, sr=sr)[0]
spectral_centroids.shape
(775,)
# Computing the time variable for visualization
frames = range(len(spectral_centroids))
t = librosa.frames_to_time(frames)
# Normalising the spectral centroid for visualisation
def normalize(x, axis=0):
    return sklearn.preprocessing.minmax_scale(x, axis=axis)
#Plotting the Spectral Centroid along the waveform
librosa.display.waveplot(x, sr=sr, alpha=0.4)
plt.plot(t, normalize(spectral_centroids), color='r')

到最后,光谱质心上升。 Q3uaA3V.jpg!web

  • 光谱衰减

它是信号形状的度量。librosa.feature.spectral_rolloff 计算信号中每帧的滚降系数:

spectral_rolloff = librosa.feature.spectral_rolloff(x+0.01, sr=sr)[0]
librosa.display.waveplot(x, sr=sr, alpha=0.4)
plt.plot(t, normalize(spectral_rolloff), color='r')

mq2Ivay.jpg!web

  • 梅尔频率倒谱系数

信号的Mel频率倒谱系数(MFCC)是一小组特征(通常约10-20),其简明地描述了频谱包络的整体形状,它模拟了人声的特征。让我们这次用一个简单的循环波。 EvmIbmb.jpg!web

x, fs = librosa.load('../simple_loop.wav')
librosa.display.waveplot(x, sr=sr)

librosa.feature.mfcc 通过音频信号计算MFCC:

mfccs = librosa.feature.mfcc(x, sr=fs)
print mfccs.shape
(20, 97)
#Displaying  the MFCCs:
librosa.display.specshow(mfccs, sr=sr, x_axis='time')

ieEvI3N.jpg!web

这里mfcc计算了超过97帧的20个MFCC。我们还可以执行特征缩放,使得每个系数维度具有零均值和单位方差:

import sklearn
mfccs = sklearn.preprocessing.scale(mfccs, axis=1)
print(mfccs.mean(axis=1))
print(mfccs.var(axis=1))
librosa.display.specshow(mfccs, sr=sr, x_axis='time')

mIF77rI.jpg!web

  • 色度频率

色度频率是音乐音频有趣且强大的表示,其中整个频谱被投影到12个区间,代表音乐八度音的12个不同的半音(或色度),librosa.feature.chroma_stft 用于计算。

# Loadign the file
x, sr = librosa.load('../simple_piano.wav')
hop_length = 512
chromagram = librosa.feature.chroma_stft(x, sr=sr, hop_length=hop_length)
plt.figure(figsize=(15, 5))
librosa.display.specshow(chromagram, x_axis='time', y_axis='chroma', hop_length=hop_length, cmap='coolwarm')

jyyue2a.jpg!web

案例研究:将歌曲分类为不同的类型

在概述了声学信号,它们的特征和它们的特征提取过程之后,是时候利用我们新开发的技能来处理机器学习问题了。

目的

在这个部分中,我们将尝试对分类器进行建模,以将歌曲分类为不同的类型。让我们假设一个场景:由于某种原因,我们在硬盘上找到一堆随机命名的MP3文件,我们的任务是根据音乐类型将它们分类到不同的文件夹中,如爵士乐、古典乐、乡村音乐、流行乐、摇滚乐和金属乐。

数据集

我们将使用著名的GITZAN数据集进行案例研究,该数据集曾用于G.Tzanetakis和P.Cook在IEEE Transactions on Audio and Speech Processing 2002 中的“ 音频信号的音乐类型分类”。

数据集由每30秒长的1000个音轨组成,它包含10种类型:蓝调、古典、乡村、迪斯科、嘻哈、爵士、雷鬼、摇滚、金属和流行音乐,每种类型包含100个声音片段。

预处理数据

在训练分类模型之前,我们必须将音频样本中的原始数据转换为更有意义的表示,音频片段需要从.au格式转换为.wav格式,以使其与用于读取音频文件的python波形模块兼容。可开源SoX模块进行转换 (http://sox.sourceforge.net/)

sox input.au output.wav

特征提取

然后,我们需要从音频文件中提取有意义的功能。为了对我们的音频片段进行分类,我们将选择5个特征,即过零率、光谱质心、光谱衰减、梅尔频率倒谱系数和色度频率。然后将所有功能附加到.csv文件中,以便可以使用分类算法。

分类

一旦提取了特征,我们就可以使用现有的分类算法将歌曲分类为不同的类型。您可以直接使用频谱图像进行分类,也可以提取特征并在其上使用分类模型。

无论哪种方式,都可以在模型方面进行大量实验。您可以自由地尝试并改善结果。使用CNN模型(在频谱图像上)可以提供更好的准确度,值得一试。

网址:https://gist.github.com/parulnith/7f8c174e6ac099e86f0495d3d9a4c01e#file-music_genre_classification-ipynb

uiIjyun.jpg!web

音乐类型分类是音乐信息检索的众多分支之一。从这里你可以执行音乐数据的其他任务,如节拍跟踪、音乐生成、推荐系统、音轨分离和乐器识别等。音乐分析是一个多样化的领域,也是一个有趣的领域。音乐会话以某种方式代表用户的时刻,找到这些时刻并描述它们是数据科学领域的一个有趣挑战。

参考资料:https://towardsdatascience.com/music-genre-classification-with-python-c714d032f0d8


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK