利用spleeter分离歌曲人声并借助Parselmouth绘制声波图像
环境准备
Python >=3.7
Python IDE (本文使用PyCharm)
本次演示采用最快速的方式获取结果
提取人声
软件提取【推荐】
https://makenweb.com/SpleeterGUI
下载
软件自带中文,总的来说还是很方便的。
试试代码?
在线提取(需要科学上网环境)
想试用但不想安装任何东西?官方已为我们建立了一个Google Colab。
首先打开spleeter的GitHub页面
找到向下滑找到Quick start
选择底下的Google Colab
会提示授权,直接同意即可。
为了方便我们后续操作,先按顺序点击 小三角 执行命令【按顺序全部执行】(忽略我前面的[**]和绿色对勾,因为我执行过一遍),执行完成后会返回实例音频的分离结果。
接下来我们分离自己的音频。
打开代码文件夹,删除audio_example.mp3
文件并把你要分离人声的音乐文件(mp3格式)上传到此目录下并重命名为audio_example.mp3
(如下图)
上传完成后,不用执行Install spleeter
内的的代码(也就是上面那三个),直接从Separate from command line
内的第三个代码开始执行。
等待命令全部执行,音乐和人声就分离出来了,有时会遇到下面问题。
解决方法是打开下方目录, vocals.wav
就是你刚才分离的人声文件,accompaniment.wav
是背景音乐文件,直接右键下载即可。
此时,你已经成功分离了人声和背景音乐。
本地分离
https://github.com/deezer/spleeter/wiki 去他们的wiki看看吧,这里偷个懒,我就不演示了。
φ(* ̄0 ̄)
绘制声波波幅图像
打开PyCharm,假设你会用PyCharm。
新建一个文件夹,在里面,新建一个test.py
文件和audio
文件夹,把你刚才提取的人声(名字为vocals.wav 不要改名字)放进audio文件夹,venv
和.idea
不用创建PyCharm会自己创建。
安装软件包
用PyCharm打开test.py
文件,安装下方软件包。
-
praat-parselmouth
-
numpy
-
matplotlib
-
seaborn
最后安装成下面这样就差不多,只用去安装上面四个,他会自动帮你安装下面那一堆。
获取音频图像
输入下方代码并执行
import parselmouth
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# import math
sns.set() # Use seaborn's default style to make attractive graphs
snd = parselmouth.Sound(r"audio/vocals.wav")
def draw_pitch(pitch):
# Extract selected pitch contour, and
# replace unvoiced samples by NaN to not plot
pitch_values = pitch.selected_array['frequency']
pitch_values[pitch_values == 0] = np.nan
plt.plot(pitch.xs(), pitch_values, 'o', markersize=2, color='w')
plt.plot(pitch.xs(), pitch_values, 'o', markersize=2)
plt.grid(False)
plt.ylim(0, pitch.ceiling)
plt.ylabel("fundamental frequency [Hz]")
# def draw_spectrogram(spectrogram, dynamic_range=70):
# X, Y = spectrogram.x_grid(), spectrogram.y_grid()
# sg_db = 10 * np.log10(spectrogram.values)
# plt.pcolormesh(X, Y, sg_db, vmin=sg_db.max() - dynamic_range, cmap='afmhot')
# plt.ylim([spectrogram.ymin, spectrogram.ymax])
# plt.xlabel("time [s]")
# plt.ylabel("frequency [Hz]")
# def draw_intensity(intensity):
# plt.plot(intensity.xs(), intensity.values.T, linewidth=3, color='w')
# plt.plot(intensity.xs(), intensity.values.T, linewidth=1)
# plt.grid(False)
# plt.ylim(0)
# plt.ylabel("intensity [dB]")
class Tonality:
base_diff = [0, 2, 4, 5, 7, 9, 11]
tones = ['A', 'A#', 'B', 'C', 'C#', 'D', "D#", 'E', 'F', 'F#', 'G', 'G#']
def __init__(self, tone):
assert tone in self.tones
self.base_freq = self.tone_to_freq(tone)
def tone_to_freq(self, tone):
A_freq = 440
return A_freq * (2 ** (self.tones.index(tone) / 12))
def get_freq(self):
ret = []
for r in range(-3, 2):
base = self.base_freq * (2 ** r)
ret.extend([base * (2 ** (diff / 12)) for diff in self.base_diff])
return ret
def draw_standard(tone):
for f in Tonality(tone).get_freq():
plt.axline((0, f), (1, f), lw=1)
pitch = snd.to_pitch()
# If desired, pre-emphasize the sound fragment before calculating the spectrogram
# pre_emphasized_snd = snd.copy()
# pre_emphasized_snd.pre_emphasize()
# spectrogram = pre_emphasized_snd.to_spectrogram(window_length=0.03, maximum_frequency=8000)
plt.figure()
# draw_spectrogram(spectrogram)
plt.twinx()
tone = 'F#'
draw_standard(tone)
draw_pitch(pitch)
plt.xlim([snd.xmin, snd.xmax])
plt.show() # or plt.savefig("spectrogram_0.03.pdf")
我们以给自己的歌 (Live) - 李宗盛
这首歌来举例,首先我们要知道这首歌是什么调的,直接百度给自己的歌谱子,画圈的便是这首歌的调,可以看到是A调。
或者你可以用QQ音乐的智能曲谱,右键相关歌曲,随便选一个乐器,生成的谱子右上方写了歌曲的原调。
当我们知道了这首歌的调,接下来修改代码,代码第43行,这是代码可以分析的调。
来到代码第75行,我们已经知道了刚才的歌是A调,填入即可。
执行成功截图,右键最右边那一溜可以保存图像,由于我用了整首歌,所以这个图看起来特别密集,你可以截取相关片段来进行分析。
Parselmouth当前支持8类:声音,频谱,频谱图,强度,音高,共振峰,谐波和MFCC(以及它们之间的转换),例如:
你可以访问它的GitHub页面获取相关代码。由于本人不懂乐理知识,所以这个图也看不懂,也无法给出建议,教程至此,快去试试吧。