写在前面

因为喜欢玩儿音乐游戏,所以打算研究一下如何用深度学习的模型生成音游的谱面。这篇文章主要目的是介绍或者总结一些音频的知识和代码。

恩。如果没玩儿过的话,音乐游戏大概是下面这个样子。

下面进入正题。

我Google了一下,找到了这篇文章:Music Feature Extraction in Python。然后这篇文章介绍完了还有一个歌曲分类的实践:Classification of Music into different Genres using Keras。

下面的内容会主要参考一下这两篇文章,并加入一些我的理解。内容如下:

  • 声音信号介绍
  • 使用Python对音频进行特征提取
  • 使用Keras对歌曲的题材进行分类

主要涉及的背景知识有:

  • 傅里叶变换
  • 采样定理
  • Python
  • 机器学习

声音基础知识

音频信号

首先先百度一下音频信号,

音频信号是(Audio)带有语音、音乐和音效的有规律的声波的频率、幅度变化信息载体。 根据声波的特征,可把音频信息分类为规则音频和不规则声音。其中规则音频又可以分为语音、音乐和音效。规则音频是一种连续变化的模拟信号,可用一条连续的曲线来表示,称为声波。声音的三个要素是音调、音强和音色。声波或正弦波有三个重要参数:频率 、幅度和相位 ,这也就决定了音频信号的特征。

这里多说一句,小编是一名python开发工程师,这里有我自己整理了一套最新的python系统学习教程,包括从基础的python脚本到web开发、爬虫、数据分析、数据可视化、机器学习等。想要这些资料的可以关注小编,并私信“01”即可领取。

总体来说:音频信号就是不同频率和相位的正弦波的一个叠加。

一般的声音大概就是这个样子。

横轴是时间,纵轴是声音的幅度。因为本质上就是正弦波的一个叠加,所以看到其实是有正有负的。

人耳听力频率范围

生活中存在各种正弦波,但并不是所有的波都能被人耳听到。比如说我们手机通信的信号,wifi信号,以及阳光都是一种波,但并不能被人听见。

正常人耳听见声音的频率范围是 20Hz 到 2 万 Hz 。相同强度的声音如频率不同的话,听起来的响度是不一样的。至敏感的频率是 3000 和 4000Hz 。

所以声波的信号基本上只要关注2wHz以内就好了。

奈奎斯特采样定理

声音本质上是一种模拟信号,但在计算机或者在其他数字设备上传输时,我们要把模拟信号转换为数字信号,需要进行采样。

奈奎斯特采样定理如下:

在进行模拟/数字信号的转换过程中,当采样频率fs.max大于信号中最高频率fmax的2倍时(fs.max>2fmax),采样之后的数字信号完整地保留了原始信号中的信息。

这个定理描述的很简单,证明其实也不难,对于声音信号,只要采样的频率大于2*2wHz=4WHz的话,我们就可以听到无损的音质了。

上面说人耳听力敏感的范围主要是在4000Hz,所以我们一般听到的音乐其实是使用8000Hz频率进行采样的。这里可以看下最近比较火的芒种这首歌。

这首歌的时间是3分36秒也就是216秒,它的标准品质的大小是3.3M。这里可以计算下使用8000Hz频率,16bit进行采样的话,那么这个文件的大小是:

大概也就是3.3兆了。

使用Python对音频进行特征提取

背景知识大概就上面那些,下面开始实践环节。

准备工作

这里使用到了librosa,numpy, sklearn与keras。当然为了方便开发,我这里还用了IPython NoteBook。

pip install librosa numpy sklearn tensorflow keras

加载音乐

接下来开始在python中加载音乐,这里我选的是一首我超级喜欢的一首音游的歌曲。链接在这里:visions.mp3

import librosax , sr = librosa.load("visions.mp3", sr=8000)
print(x.shape, sr)

这里x是音频信号的数字信息,可以看到是一维的,sr是采样频率,用8000就好了。

然后可以看下这首歌在时域上的波形。

%matplotlib inlineimport matplotlib.pyplot as pltimport librosa.displayplt.figure
(figsize=(14, 5))
librosa.display.waveplot(x, sr=sr)

运行后,效果如下:

横轴为时间,纵轴为幅度(amplitude)。

Spectogram

上面是音乐时域上的信息。接下来需要对音乐的频率信息进行分析。

Spectogram这里没找到好的翻译, 大概表示的意思就是:时变的频谱图。

短时傅里叶变换-STFT

我们知道对于周期信号,可以使用傅里叶变换可以将时间域的信息变换到频率域上。

比如说看上面这张图的这个波其实是由三个频率的正弦波构成的,可以看到从频率域的原点往上延伸,频率越来越高,可以看到对应的波形越来越密集。

在文章中提到了一个短时傅里叶变换的概念,原作者给了个视频:The Short Time Fourier Transform | Digital Signal Processing

不过在看视频之前,凭借我的想象,感觉这个变换既然叫短时傅里叶变换,那应该是把音频信号拆分开,然后进行傅里叶变换。因为如果对整个音乐进行傅里叶变换的话,我们只能看到所有的频率信息,但不能确定每个频率的发生的大概时间。只能看到有某些频率的声音而已。

后来在网上找了一个我感觉比较好的解释:

短时傅立叶变换基本思想是将信号加滑动时间窗,并对窗内信号做傅立叶变换,得到信号的时变频谱。

另外,还有一个东西可以感受STFT,这里可以打开网易云音乐,找到一首歌,打开动效。

[图片上传失败…(image-6cd4e8-1636529998203)]

可以看到不断变化的各波形,拆分开来看,其实代表着就当前这一短时间内包含的声音的频率信息。上面的这张图其实也就是对当前时刻的音频信号,进行DFT得到的。

画出时变的频谱图

接下来我们调用librosa的stft方法可以直接得到短时傅里叶变换的结果。

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()复制代码

效果如下:

这里横轴是时间,纵轴是频率,颜色则代表分贝(声音的响度),可以看到越红的地方信号音量越大。

特征提取

接下来,介绍了一些音乐中的主要特征,这里主要翻译原作者的内容。

过零率(Zero Crossing Rate)

过零率(Zero Crossing Rate,ZCR)是指在每帧中,语音信号通过零点(从正变为负或从负变为正)的次数。这个特征已在语音识别和音乐信息检索领域得到广泛使用,是金属声音和摇滚乐的关键特征。

回到上面的图,我们把一个时间上放大。

n0 = 9000n1 = 9100plt.figure(figsize=(14, 5))plt.plot(x[n0:n1])plt.grid()复制代码

效果如下:

这里有7个过零点,可以通过下面的方法进行计算。

zero_crossings = librosa.zero_crossings(x[n0:n1], pad=False)print(sum(zero_crossings))复制代码

频谱中心(Spectral Centroid)

频谱中心代表声音的“质心”,又称为频谱一阶距。频谱中心的值越小,表明越多的频谱能量集中在低频范围内。

#spectral centroid -- centre of mass -- weighted mean of the frequencies present in the soundimport sklearnspectral_centroids = librosa.feature.spectral_centroid(x[:80000], sr=sr)[0]# Computing the time variable for visualizationframes = range(len(spectral_centroids))t = librosa.frames_to_time(frames, sr=8000)# Normalising the spectral centroid for visualisationdef normalize(x, axis=0):    return sklearn.preprocessing.minmax_scale(x, axis=axis)#Plotting the Spectral Centroid along the waveformlibrosa.display.waveplot(x[:80000], sr=sr, alpha=0.4)plt.plot(t, normalize(spectral_centroids), color='r')复制代码

这里用x[:80000]表示音乐的前10秒。

.spectral_centroid 来计算每一帧的频谱中心。

.frames_to_time将帧转换为时间,time[i] == frame[i]。【因为stft是一个窗口(帧)一个窗口取的,和采样频率并不对应,所以有个转换】

为了更好的可视化,对频谱中心进行了归一化。

频谱滚降点(Spectral Rolloff)

频谱滚降点的意思,我翻译过来大概是:比该频率低的频率的所有能量大于一定比例的整个频谱的能量,通常这个比例为0.85。

感觉还是有点儿别扭,用公式比较好理解一些。

[图片上传失败…(image-2963c0-1636529998203)]

下面看下代码,和上面频谱中心的代码其实类似,也是一帧一帧的进行特征抽取。

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

.spectral_rolloff 来计算每一帧的频谱滚降点。

MFCC (梅尔频率倒谱系数)

MFCC是音频信号特征中最重要的一个,基本上处理音频信号就会用到。(作为一名通信学士,我也是才知道的)。

信号的MFCC参数是一个小集合的特征(一般10-20个),它能够简洁的表示频谱的包络。

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

.mfcc 用来计算信号的MFCC参数。

通过打印mfccs.shape,可以看看每一帧里面有多少维的MFCC特征。第一个参数是mfcc参数的维度,第二个参数是帧数。

这里一共3177帧,每一帧有20维特征。

使用Keras对歌曲的题材进行分类

接下来,完成了以上的对音频信号的特征提取,就可以进行一波机器学习了。(这里不会涉及到机器学习的背景知识,默认读者不是机器学习的小白。)

数据准备

数据集下载

这里将要使用GTZAN genre collection。这个数据集包含了10个题材,每个题材包含了100个30s长的音乐。

这里将使用Tensorflow后端的Keras进行编码。

加载数据到内存

这里首先加载这些数据。

import librosaimport numpy as npimport osgenres = 'blues classical country disco hiphop jazz metal pop reggae rock'.split()data_set = []label_set = []label2id = {genre:i for i,genre in enumerate(genres)}
id2label = {i:genre for i,genre in enumerate(genres)}
print(label2id)for g in genres:
print(g)
for filename in os.listdir(f'./genres/{g}/'):
songname = f'./genres/{g}/{filename}'
y, sr = librosa.load(songname, mono=True, duration=30)
chroma_stft = librosa.feature.chroma_stft(y=y, sr=sr)        rmse = librosa.feature.rms(y=y)
spec_cent = librosa.feature.spectral_centroid(y=y, sr=sr)
spec_bw = librosa.feature.spectral_bandwidth(y=y, sr=sr)
rolloff = librosa.feature.spectral_rolloff(y=y, sr=sr)        zcr = librosa.feature.zero_crossing_rate(y)
mfcc = librosa.feature.mfcc(y=y, sr=sr)
to_append = f
'{
np.mean(chroma_stft)
}
{
np.mean(rmse)
}
{
np.mean(spec_cent)
}
{
np.mean(spec_bw)
}
{
np.mean(rolloff)} {np.mean(zcr)}'
for e in mfcc:
to_append += f' {np.mean(e)}'        data_set.append([float(i)
for i in to_append.split(" ")])        label_set.append(label2id[g])

可以看到除了上面讲到的一些特征之外,原作者这里还说了一些其他的特征,比如说rmse,chroma_stft这种。这里就不再一一介绍了。

总体来说,这里使用chroma_stft,rmse,spec_cent,spec_bw,rolloff,zcr的六个特征的均值,再加上mfcc的20个特征的均值,总共26个特征,来表示一个音乐的。

创建数据集

接下来我们对数据进行一下归一化,对标签进行one-hot编码。

from sklearn.preprocessing import StandardScalerfrom keras.utils import np_utilsscaler = StandardScaler()X = scaler.fit_transform(np.array(data_set, dtype = float))y = np_utils.to_categorical(np.array(label_set))

效果如下:

然后把测试集和训练集进行分割。

from sklearn.model_selection import train_test_splitX_train,
X_test,
y_train,
y_test = train_test_split(X, y, test_size=0.2)

创建模型

这里的我们的特征很少,所以用几层神经网络就可以了。

from keras import modelsfrom keras.layers import Dense, Dropoutdef create_model():
model = models.Sequential()
model.add(Dense(256, activation='relu', input_shape=(X_train.shape[1],)))
model.add(Dense(128, activation='relu'))    model.add(Dense(64, activation='relu'))    model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))
return modelmodel = create_model()

这里创建了一个包含三个隐藏层的神经网络,最后一层输出的是分类层,因为是10类,所以最后一层是10个单元。(这里相比原作者的代码多了一层Dropout减少数据过拟合)

编译模型

然后是编译模型,我们这里是一个分类问题,所以使用类别交叉熵函数categorical_crossentropy,然后优化器选择Adam,评价指标选择正确率。

model.compile(optimizer='adam', loss='categorical_crossentropy',
metrics=['accuracy'])

训练与评估

接下来使用fit方法进行训练,训练50轮。

model.fit(X_train, y_train, epochs=50, batch_size=128)

训练很快就完了,然后使用evaluate方法进行评估。

test_loss, test_acc = model.evaluate(X_test,y_test)
print('test_acc: ',test_acc)

这里的测试准确率也就百分之70不到,原作者后面还有使用模型预测的代码,感觉都没有必要了。

总结

这篇博客主要是介绍了一些声音方面的特征提取的知识和代码,关于最后的案例看着玩玩儿就行,基本不具有实用性。

最后多说一句,小编是一名python开发工程师,这里有我自己整理了一套最新的python系统学习教程,包括从基础的python脚本到web开发、爬虫、数据分析、数据可视化、机器学习等。想要这些资料的可以关注小编,并私信“01”领取。

python技巧:如何使用Python对音频进行特征提取?相关推荐

  1. jdom编写xml自动缩进_2020学习python技巧资料之python缩进规则

    2020学习python技巧之python缩进规则 Python语言要求编写的代码最好全部使用缩进来分层(块).代码缩进一般用在函数定义.类的定义以及一 些控制语句中.一 般来说,行尾的": ...

  2. editplus里python技巧_editplus调试python

    ) IPython VIM– 主要在linux下使用 其它编辑器 UE,notepad++,editplus-工...事必先利其器 PDB调试 Python –m pdb xxx.py b --设置断 ...

  3. python初学者_面向初学者的20种重要的Python技巧

    python初学者 Python is among the most widely used market programming languages in the world. This is be ...

  4. python合并音频和视频_ffmpeg+Python实现B站MP4格式音频与视频的合并

    安装 官网下载 环境变量 此电脑--属性--高级系统设置--环境变量 在系统变量(也就是下面那一半)处找到新建,按如下所示的方法填写 再将%FFMPEG_HOME%以及%FFMPEG_HOME%\bi ...

  5. python合并音频和视频_ffmpeg+Python实现B站MP4格式音频与视频的合并示例代码

    安装 官网下载 选择需要的版本 将解压后得到的以下几个文件放置在E:\FFmpeg下 环境变量 此电脑--属性--高级系统设置--环境变量 在系统变量(也就是下面那一半)处找到新建,按如下所示的方法填 ...

  6. 程序员必知的20个Python技巧

    作者 | Duomly 译者 | 弯月,编辑 | 郭芮 出品 | CSDN(ID:CSDNnews) Python是一门流行且应用广泛的通用编程语言,其应用包括数据科学.机器学习.科学计算等领域,以及 ...

  7. 你需要知道的20个常用的Python技巧

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自|机器学习算法那些事 Python的可读性和简单性是其广受 ...

  8. python%20语言 20培训_Python语言学习之20个值得学习的Python技巧

    点击蓝字获取更多精彩信息 1.字符串反转 使用切片反转字符串. str1="qwert"   rev_str1=str1[::-1]   #输出    # trewq 2.使首字母 ...

  9. 如何打开python的交互窗口-Python多版本情况下四种快速进入交互式命令行的操作技巧...

    原标题:Python多版本情况下四种快速进入交互式命令行的操作技巧 因为工作需求或者学习需要等原因,部分小伙伴的电脑中同时安装了Python2和Python3,相信在Python多版本的切换中常常会遇 ...

最新文章

  1. Sound Forge Pro 3使用教程
  2. python中wraps的详解
  3. 山西职称计算机考试报名时间 2014,2014山西省6月份职称计算机考试报名入口
  4. 机器人学习--电子指南针定位导航
  5. Win10+vs2013+Caffe静态库配置自己的工程
  6. linux wifi关闭5g,TP-Link路由器如何关闭5G无线Wi-Fi信号?
  7. 控件setVisible为false会导致控件被移除
  8. bitmap 转byte[]后读取_闲谈redis的bitmap
  9. 利用Visio 2007图形化项目进度和项目跟踪
  10. node命令错误--nodemon : 无法将“nodemon”项识别
  11. 状压DP【洛谷P1896】 [SCOI2005]互不侵犯
  12. 【赶紧收藏】平面设计必备字体,广告设计常用字体
  13. 面试题(两个栈实现一个队列和两个队列实现一个栈)
  14. linux打印机设置密码,linux桌面打印机配置指南 | 高蛋白网
  15. 酸辣土豆丝的做法你知道几个?
  16. OSPF报文与LSA
  17. LINQ SelectMany cannot be inferred from the usage. Try specifying the type arguments explicitly.
  18. linux怎么打开ppt文件格式,PPT 文件扩展名: 它是什么以及如何打开它?
  19. java基础复习之不死神兔
  20. UE/UI/UCD/UED 区别

热门文章

  1. Python 练习实例100例—7
  2. 防火墙、WAF、IPS、IDS、堡垒机的区别
  3. 一经开源就爆了!谷歌这个脚本工具注定要火
  4. 彻底解决高版本 mac Kernel_task占CPU问题
  5. 基本功:线程上下文切换
  6. 【学术相关】国家自然科学基金申请——函评等级与上会
  7. IntelliJ IDEA的常用设置和快捷键
  8. 艾德克斯充电测试软件_艾德克斯ITECH 交流充电桩模拟系统
  9. 大数据的主要特征是什么?
  10. sed命令删除行操作