R语言声音音乐分析MusicAnalysis01-初次上手怎么用tuneR和seewave音频分析之一

Music Analysis with R.

为什么要用R来做声音/音乐分析呢?实际上用Python会灵活很多,处理上选择也会比较多。R语言作为统计分析为主的语言也提供了一些有用的包,这里我给目前手上只有R但要做声音分析、却对这一块不太了解的伙伴们提供一个“解(ying)决(ji)方(cuo)案(shi)”。

tuneR和seewave都是用来进行音频处理和分析的R包,seewave一些方法也是使用tuneR实现的,所以它们俩基本上算是“捆绑”了。第一次用这两个包,也是第一次敲代码做音频分析,这一篇里主要尝试tuneR和seewave里的一些常用的方法,记录一下音频分析小白的学习过程。如果有机会的话,我还会再琢磨琢磨,记录一些更针对细节的内容。

官方文档奉上:
tuneR : https://cran.r-project.org/web/packages/tuneR/tuneR.pdf
seewave : https://cran.r-project.org/web/packages/seewave/seewave.pdf

希望可以一起交流!

安装tuneR和seewave包

我用的OS是Win10。我这里本来是R3.6.1的,但是安装居然还是会出问题,所以干脆更新到R最新版本2020年3月发布的R3.6.3,而tuneR和seewave的版本也当然是最新版本,tuneR 1.3.3,seewave 2.1.5。

其实在R安装的话基本都用的同一句话:

install.packages(‘package_name’)

安装tuneR和seewave就直接:

install.packages(‘tuneR’)
install.packages(‘seewave’)

或者更直接地 install.packages(c(‘tuneR’,‘seewave’))
再用library(tuneR),library(seewave)分别确认一下。

readWave导入WAV文件

这一篇里我们都用WAV文件。WAV文件是一种常见的标准音频文件格式,通常编码方式是LPCM格式,每个样本sample占用16 bits,采样率sampling rate是44100 Hz(现在音频常见的采样率是44100 Hz或者48000 Hz),记录双声道。能保证声音不失真,真实记录自然声波波形,基本没有数据压缩,数据量大。

s<-readWave("C:/Users/Admin/Documents/Music_Analysis/Music_files/amazon_sound.wav")
s
class(s) 
play(s)    // play(s) in tuneR, or listen(s) in seewave 

会有“non-UTF-8 MBCS locale”的相关报错,但是文件确实读进去了,可以用,而且play的时候是有声音的,没毛病。duration是seewave包里的函数,返回文件的持续时间。这些基本信息都可以直接从class返回的内容里看到。我使用的这个文件是单声道的。
readWave时报错
readWave最终还是成功的
注意啦!如果是MacOS的用户,播放WAV文件完全不同Windows那般直接简单,但是还是有办法的!《R语言在Mac上无法播放WAV音频文件》介绍了遇到的报错还有解决方案。

波形图 Oscillogram

官方文档开头就告诉我们,tuneR包里一般是基本的信号处理,而seewave导入的包就有graphics, grDevices, stats, utils, tuneR,可视化的任务基本都用seewave完成了。

绘制基本的波形图,这里简单比较一下两个方法,oscillo和oscilloST:oscillo能显示音频的time wave,声波的波封(envelope,会在另一篇里简单介绍)也会显示出来;oscilloST和oscillo最大的不同就是这个ST,也就是stereo,双声道,适用于stereo time wave。注意这里s是单声道文件

oscillo(s)

整洁好看的oscillo

oscilloST(s)

用oscilloST绘制一个单声道文件导致的报错
用oscilloST绘制的单声道波形图

音频简单剪切 Cut the time wave

做一些基本操作。最简单的操作之一就是简单的音频剪切,取出其中一段音频。这里我们用seewave的cutw方法,它还能把剪切前和剪切后的音频的波形图放在一起做对比,也是很实用了。可以借助前面的波形图找到我们要的切割点,但是最好zoom in放大看一下,因为那个波形图还是太粗略了,很有可能剪出来不干净。上码:

c1<-cutw(s,f=44100, from=0, to=0.3,choose=FALSE, plot=TRUE, marks = TRUE)

cutw的输出
默认输出为"matrix",里面的元素包含着样本信息;还可以是"Wave",“Sample”,“audioSample”,“ts”这些,详见seewave的官方文档。
cutw剪切前vs剪切后
然后我们可以用savewav把输出的结果存为一个新的WAV文件:

savewav(wave=c1, f=44100, filename = "Amazon_sound_c1.wav", rescale = NULL)

如果文件名跟别的文件有重复会直接覆盖之前的同名文件。保存时,默认它还会自动正则化(normalize)音频的响度(amplitude)。

那如果我们之前就输出成“Wav”是不是就不用做这一步了?不是的。调整输出为“Wav”只是将输出的R对象R Object改成了"Wav"这个类型,有一些方法有这个类型的parameter,可以不必输入采样率f(如果是默认输出的“matrix”就一定要写f的值),但是仅仅作为对象储存在R里,并没有生成新文件。还是需要savewav生成WAV文件。

c11<-cutw(s,f=44100, from=0, to=0.3, plot=TRUE, output = "Wave")

cutw输出设置为"Wav"并不能生成新的WAV文件

“时序分析” Temporal Analysis

前面的得到是信号,当我们针对它做出分析,一般还是会需要傅里叶变换(Fourier Transform)之后的频谱信息作为分析材料。要提取

ama调幅分析

acoustat方法会显示time envelope波封,还有frequency spectrum频谱图。

要了解音频对象的响度-频率分析,可以用seewave里的ama(amplitude modulation analysis)。官方文档里介绍说,这个方法是对time wave envelope时间声波波封的傅里叶分析,可以检测出周期性,特别是AM调幅过生成的音频。(可是高中物理已经不记得了)

// acoustat(c1,f=44100)   you may try it, too
ama(c1, f=44100)

不得不说这个线真的太靠近坐标轴,已经很难从中获得关键信息——最重要的其实是,这个方法适用于调幅生成的音频,而很可能不适于分析我们这里的音频。
ama绘制的响度-频率响度分析

env时间波的响度波封 amplitude envelope

退一步,in a rahter genral view,对于每一个音频我们都可以做的处理,其中就有波封,至少它是最显而易见、容易理解的那种信息。前面我们得到了time wave,如果我们要这个波的响度轮廓,也就是要波封本身。要做amplitude envelope of a time wave,时间波的响度波封,也就是相对于时间(x轴),波的振幅或者说声波响度(y轴)的变化。

seewave包里有env可以绘制这样的图,官方文档介绍说方法里还可以使用oscillo方法里的参数,它返回的是绝对响度波封(absolute amplitude envelope)或者希尔伯特响度波封(Hilbert amplitude envelope)。

env(c1,44100)  //默认输出是 absolute amplitude envelope

c1的响度波封amplitude envelope,这里是绝对值
如果想更进一步了解这个波封,比如说,按照我们通常的ADSR Envelope,我们的起音、衰减、延持还有释音其实都是按时间来记的,那对于这样一个波封,我们怎么确切得到这四个参数?

我注意到timer是专门用来做time measurement的方法。那先试试看:

timer(c1,44100,colval = "red")

timer方法参数都用默认值时的输出
0.08s到0.12s左右以及右边0.17s到0.24左右的这两个区间,明显集中了过多的标记点,有点眼瞎的感觉。拿这张被“画”的惨不忍睹的图和之前上面做的绝对波封对比,可以推测,可能是区间以内的变化比较频繁,而且变化不太平缓,很多变化被跟着一起滤出来了,而实际上我们并不想要关注这样“精确”细微的变化。需要给方法加一些限制条件。

因为很难提出准确的条件,所以只能反过来思考,既然在“过滤”的算法上难以提出建议,不如在数据本身做预处理——没错,过了这么久我终于发现我还没做预处理。其实对于音频的预处理,也就是平滑smooth和去噪之类的,我不是非常熟悉,也不确定会不会对后面的操作有没有影响,所以没有第一步就预处理,而是边走边看。

先试着直接在env里smooth,比较简便。那么问题又来了,我该用哪一个平滑函数(smooth function)?一共给了三个选择:msmooth,用平均频率来平滑,需要输入窗口长度(window length)或者窗口大小(window size)还有连续窗口间的重叠率(overlap);ssmooth,用smooth函数和来smooth;asmooth,自动平滑。我逐一尝试了一下,asmooth是我觉得我目前最难把握的,换了几个窗口长度,好像和想象的不大一样,也可能是使用上有些问题;msmooth的话我对于窗口长度特别是重叠率的使用还不太了解,两个参数作为一个二元向量输入,不太有把握;ssmooth,慢慢从1024之类的较大值减小到126,可以发现较明显的变化,最后也是用它上下尝试得到了期望的结果:

timer(c1,44100,colval="red",ssmooth = 128)

smooth平滑过后的信号再做timer时间测量

这一系列很快就会有更新,后面除了继续介绍R语言的音频处理方法,还会介绍声学相关、基本乐理、音乐制作等有助于音乐分析的干货。如果对数据分析、声音硬件、live-coding等等有兴趣也可以关注一下,后续也会有相关文章发布~

发布了2 篇原创文章 · 获赞 9 · 访问量 214

猜你喜欢

转载自blog.csdn.net/dsager/article/details/104934953