R语言---Seewave包和tuneR在声音分析中的应用①关于声音及简单分析

R语言---Seewave包和tuneR在声音分析中的应用①关于声音及简单分析

关于声音分析

在R中的声音分析主要应用于生物声学和生态声学的分析,当然在情绪调节、城市噪音评估和神经科学中的脑语音处理等许多领域都有相关的涉及和应用。

其声音分析主要原理就是利用傅里叶变换(或傅里叶逆变换)实现时域和频域的相互转换,进行傅里叶分析(Fourier analysis)
举一个简单的例子,人之所以能在同一段歌曲中既能听到鼓点伴奏声,又可以听到唱歌人的声音,其大脑就起到了傅里叶变换的功能,当然这个过程也可以是有选择性的(即提高专注度,可只听人声而忽略鼓声)。

在这里插入图片描述

时振幅参数化

Let’s do it

1.首先,在野外环境收集声音阶段,你需要慎之又慎,需要你尽可能收集到清晰的声音。(该过程是十分重要的,较高的SNR能帮助你在之后的分析中,减少时间的浪费!)

2.加载相关的包
library(audio)
library(seewave)
library(tuneR)
导入声音(需要区分你的音频文件格式)以及保存声音
主要分为MP3,wav,flac三种格式进行文件的读取
.wav:未压缩格式
.mp3: 有损压缩格式,信息减少。时间,幅度和频率参数可能会受损。
.flac: 无损压缩格式
(建议你选取.wav格式或.flac是一个比较适用于数据分析的文件格式)
readWave()
(当然你如果获得的是一堆音频,可以将其文件名导入至file中,以便后续进行循环计算)
file.name.sum<-dir(“Sample”, pattern=“wav∣ m p 3 |mp3mp3”)
最简单的保存方法就是:savewav(wave.sound)(直接将你的声音保存到预先设定的路径)

3.收集wave 不一定都是完美的,你需要进行预剪切,并通过示波器查看效果
sample<-extractWave(sample, from= , to= , xunit=“time”)
cutw(wave, f, channel=1, from = NULL, to = NULL, choose = F,
plot = F)
oscillo(sample)#不需要设置参数,可直接快速查看
oscillo(sample, f=sample@sample_rate, alab=“Amplitude (Pa)”)
axis(side=2, las=2)
在这里插入图片描述
有时候,你收集的音频十分混乱,但你仍想从中找到一些有用的信息
#利用fir()去找寻不同频率下的波段,通过滤波获得你所需的音波
利用from和to来确定你需要分析的时间段
sample_filt <- fir(sample, from=NULL, to=NULL, output=“Wave”)
通过identify=T 来确定波段的位置
在这里插入图片描述
4.SNR检验,以保证你声音质量的高低
如果音波产生过程中,有噪音掺杂其中

sample_SNR_1923_1<- 20*log10(rms(sample_1_cut)/rms(sample_noise_1))

如果杂音没有掺杂其中,
在这里插入图片描述
5. 接下来,你可以通过代码获得一些声音的信息

crest(sample)#波峰,c波峰因数、val样本值、loc最大峰时的样本
max(sample@left) - min(sample@left)#peak-to-peak
E <- sum(sample@left^2)#能量
n <- length(sample@left)#波长
P <- E/n#平均功率
RMS <- sqrt§#均方根
处理一堆文件你可以套用修改下面的循坏
#library(moments)
for (i in 1:length(file.name.sum)) {
kurtosis.sum<-kurtosis(readWave(paste(file.name.sum[i], sep=" "))@left)
print(as.data.frame(kurtosis.sum))
}
data.frame(E,P,RMS)#建立data.frame将这些东西整合起来

还可以通过summary()来获得关于波的一些经典统计量

6.时振幅参数化
测量振幅的方法有两种方式:分别是手动测量和自动测量
a.手动测度
oscillo(sample, identify=TRUE)在这里插入图片描述
for(i in 1:n) { # loop with n iterations
res[[i]] <- oscillo(readWave(file.name.sum[i]), identify=TRUE)
}
如果你的音频文件很多,非常建议你不要使用for循环来进行手动测量。
b.自动测度
其原理:参考设置幅度阈值跟踪振幅随时间的变化。低于固定阈值的任何事件都被视为暂停事件,而高于固定阈值的任何事件都被视为信号事件,则被记录。
envlpe <- env(sample, plot=FALSE)
max.env <- max(envlpe)#利用Hilbert amplitude envelope可获得最大envelope
max.env

timer()#自动测度
具体参数设置可通过?timer()寻求帮助
通过该公式你可获得一下结果:
a. 信号事件的持续时间(以秒为单位)
b. 暂停事件的持续时间(以秒为单位)
c. 间断时间比
d. 信号开始的时间位置
e. 信号结束的时间位置
f. 检测第一个事件是否产生信号(TURE OR FALSE)

*设置timer()参数是十分棘手的,你必须依靠经验而且根据你所测量的音频而决定。
但检测参数精确与否的方法是确定的。
ex:
res <- timer(sample, msmooth=c(49,90),threshold=5,envt=“hil”)
res2 <- timer(sample, msmooth=c(49,90), threshold=4.9,envt=“hil”, dmin=0.18)
res3<-timer(sample, threshold=5.45, ssmooth=140, envt=“hil”)

length(resKaTeX parse error: Expected 'EOF', got '#' at position 3: s)#̲ mean(ress) # mean of signal duration
sd(resKaTeX parse error: Expected 'EOF', got '#' at position 5: s) #̲ standard-devia…p) # mean of pause duration
sd(res$p) # standard-deviation of signal duration
同上,循环如下:
for (i in 1:length(file.name.sum)) {

res<-timer(readWave(paste(file.name.sum[i], sep=" ")),threshold=5, msmooth=c(50,0),envt=“hil”,plot=F)
msd.sum<-mean(resKaTeX parse error: Expected 'EOF', got '#' at position 4: s) #̲ mean of signal…s) # standard-deviation of signal duration
mpd.sum<-mean(resKaTeX parse error: Expected 'EOF', got '#' at position 4: p) #̲ mean of pause …p) # standard-deviation of signal duration
print(data.frame(msd.sum,ssd.sum,mpd.sum,spd.sum))
}

is first event a pause?
res$first==“pause”

calculation of the period
period <- ress + r e s s+ress+resp[-1]
mean of the period
mean(period)
boxplot(ress , r e s 2 s,res2s,res2s,res3$s)
这里我们可以使用**boxplot()**去检测误差分布,以选择较好的自动测度参数
(在实际应用的过程中,针对不同音频文件需要进行不同的调整,已满足你的要求,但随着设置参数和经验累计,针对某一生物的音频所设置的参数可能是在一定区间变化,并不会有较大波动。)
在这里插入图片描述

下期讲着重针对滑动窗口去探讨如何进行时振幅参数化的具体细节。

希望该分享能对大家在声音分析方面有所帮助,
由于笔者水平有限,分享难免有遗漏之处,敬请各位读者批评指正!

关于声音分析的细节和更为详尽的代码,还请你去仔细阅读这本书**《Sound Analysis and Synthesis with R》**,以达到你声音分析的要求。

Peng Han
(E-mail: penghan_eco@qq.com)


版权声明:本文为qq_52186948原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。