有效地在R中分割大型音频文件 [英] Efficiently split a large audio file in R

查看:68
本文介绍了有效地在R中分割大型音频文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


之前我问过关于分割音频文件的问题.我从@Jean V.Adams得到的答案相对来说比较有效(缺点:输入是立体声,而输出是单声道,而不是立体声)对于小型声音对象来说效果很好:


Previously I asked this question on SO about splitting an audio file. The answer I got from @Jean V. Adams worked relatively (downside: input was stereo and output was mono, not stereo) well for small sound objects:

library(seewave)

# your audio file (using example file from seewave package)
data(tico)
audio <- tico # this is an S4 class object
# the frequency of your audio file
freq <- 22050
# the length and duration of your audio file
totlen <- length(audio)
totsec <- totlen/freq

# the duration that you want to chop the file into
seglen <- 0.5

# defining the break points
breaks <- unique(c(seq(0, totsec, seglen), totsec))
index <- 1:(length(breaks)-1)
# a list of all the segments
subsamps <- lapply(index, function(i) cutw(audio, f=freq, from=breaks[i], to=breaks[i+1]))

我将此解决方案应用到了我准备进行分析的一个文件(约300个)中(约150 MB),我的计算机对其进行了处理(现在> 5个小时),但最终我关闭了该解决方案.会话结束之前.

I applied this solution to one (out of around 300) of the files I'm preparing for analysis (~150 MB), and my computer worked on it for ( > 5 hours now), but I ended up closing the session before it finished.

是否有人有任何想法或解决方案来有效地执行使用R将大音频文件(特别是S4类Wave对象)分割成较小片段的任务?我希望从这些较大的文件中大幅度减少制作较小文件的时间,并且希望使用R.但是,如果我不能让R有效地完成任务,我将感谢您的建议.其他工作工具.上面的示例数据是单声道,但我的数据是立体声的.可以使用以下示例将示例数据设置为立体声:

Does anyone have any thoughts or solutions to efficiently perform this task of splitting up a large audio file (specifically, an S4 class Wave object) into smaller pieces using R? I'm hoping to cut down drastically on the time it takes to make smaller files out of these larger files, and I'm hoping to use R. However, if I cannot get R to do the task efficiently, I would appreciate suggestions of other tools for the job. The example data above is mono, but my data is in stereo. The example data can be made to be stereo using:

tico@stereo <- TRUE
tico@right <- tico@left

更新

我确定了基于第一个解决方案的另一种解决方案:

UPDATE

I identified another solution that builds on work from the first solution:

lapply(index, function(i) audio[(breaks[i]*freq):(breaks[i+1]*freq)])

比较三种解决方案的性能:

Comparing the performance of three solutions:

# Solution suggested by @Jean V. Adams
system.time(replicate(100,lapply(index, function(i) cutw(audio, f=freq, from=breaks[i], to=breaks[i+1], output="Wave"))))
user  system elapsed 
1.19    0.00    1.19 
# my modification of the previous solution
system.time(replicate(100,lapply(index, function(i) audio[(breaks[i]*freq):(breaks[i+1]*freq)])))
user  system elapsed 
0.86    0.00    0.85 

# solution suggested by @CarlWitthoft 
audiomod <- audio[(freq*breaks[1]):(freq*breaks[length(breaks)-1])] # remove unequal part at end
system.time(replicate(100,matrix(audiomod@left,ncol=length(breaks))))+
system.time(replicate(100,matrix(audiomod@right,ncol=length(breaks))))
user  system elapsed 
0.25    0.00    0.26 

使用索引(即 [])的方法似乎更快(3-4倍).@CarlWitthoft的解决方案甚至更快,缺点是它将数据放入一个矩阵中,而不是多个 Wave 对象,我将使用 writeWave 保存这些对象.如果我正确理解如何创建这种类型的S4对象,从矩阵格式转换为单独的 Wave 对象大概是比较简单的.还有进一步的改进空间吗?

The method using indexing (i.e. [) seems to faster (3-4x). @CarlWitthoft's solution is even faster, the downside is that it puts the data into a matrix rather than multiple Wave objects, which I will be saving using writeWave. Presumably, convert from the matrix format to a separate Wave objects will be relatively trivial if I properly understand how to create this type of S4 object. Any further room for improvement?

推荐答案

我最终使用的方法是基于@CarlWitthoft和@ JeanV.Adams提供的解决方案的.与我使用的其他技术相比,它的运行速度非常快,它使我可以在数小时而不是数天的时间内拆分大量文件.

The approach I ended up using builds off of the solutions offered by @CarlWitthoft and @JeanV.Adams. It is quite fast compared to the other techniques I was using, and it has allowed me to split a large number of my files in a matter of hours, rather than days.

例如,这是整个过程,使用一个小Wave对象(我当前的音频文件的大小最大为150 MB,但是将来,我可能会收到更大的文件(例如,声音文件覆盖12-24小时的录音)),内存管理将变得更加重要):

Here is the whole process using a small Wave object for example (my current audio files range up to 150 MB in size, but in the future, I may receive much larger files (i.e. sound files covering 12-24 hours of recording) where memory management will become more important):

library(seewave)
library(tuneR)

data(tico)

# force to stereo
tico@stereo <- TRUE
tico@right <- tico@left    
audio <- tico # this is an S4 class object


# the frequency of your audio file
freq <- 22050
# the length and duration of your audio file
totlen <- length(audio)
totsec <- totlen/freq 

# the duration that you want to chop the file into (in seconds)
seglen <- 0.5

# defining the break points
breaks <- unique(c(seq(0, totsec, seglen), totsec))
index <- 1:(length(breaks)-1)

# the split
leftmat<-matrix(audio@left, ncol=(length(breaks)-2), nrow=seglen*freq) 
rightmat<-matrix(audio@right, ncol=(length(breaks)-2), nrow=seglen*freq)
# the warnings are nothing to worry about here... 

# convert to list of Wave objects.
subsamps0409_180629 <- lapply(1:ncol(leftmat), function(x)Wave(left=leftmat[,x],
         right=rightmat[,x], samp.rate=d@samp.rate,bit=d@bit)) 


# get the last part of the audio file.  the part that is < seglen
lastbitleft <- d@left[(breaks[length(breaks)-1]*freq):length(d)]
lastbitright <- d@right[(breaks[length(breaks)-1]*freq):length(d)]

# convert and add the last bit to the list of Wave objects
subsamps0409_180629[[length(subsamps0409_180629)+1]] <- 
     Wave(left=lastbitleft, right=lastbitright, samp.rate=d@samp.rate, bit=d@bit)

这不是我最初的问题的一部分,但是我的最终目标是保存这些新的,较小的Wave对象.

This wasn't part of my original question, but my ultimate goal was to save these new, smaller Wave objects.

# finally, save the Wave objects
setwd("C:/Users/Whatever/Wave_object_folder")

# I had some memory management issues on my computer when doing this
# process with large (~ 130-150 MB) audio files so I used rm() and gc(),
# which seemed to resolve the problems I had with allocating memory.
rm("breaks","audio","freq","index","lastbitleft","lastbitright","leftmat",
  "rightmat","seglen","totlen","totsec")

gc()

filenames <- paste("audio","_split",1:(length(breaks)-1),".wav",sep="")

# Save the files
sapply(1:length(subsamps0409_180629),
       function(x)writeWave(subsamps0409_180629[[x]], 
       filename=filenames[x]))

这里唯一真正的缺点是输出文件很大.例如,我放入一个130 MB的文件,并将其分成18个文件,每个文件大约50 MB.我认为这是因为我的输入文件是.mp3,而输出是.wav.我将这个问题的答案发布到我自己的问题上,以解决我以前用来解决该问题的完整解决方案所遇到的问题,但是其他答案也值得赞赏,我将花时间研究每种解决方案并评估它们提供的解决方案.我相信,有更好的方法可以完成此任务,并且对于较大的音频文件,它们可以更好地工作.在解决这个问题时,我几乎没有涉及内存管理方面的知识.

The only real downside here is that the output files are pretty big. For example, I put in a 130 MB file and split it into 18 files each approximately 50 MB. I think this is because my input file is .mp3 and the output is .wav. I posted this answer to my own question in order to wrap up the problem I was having with the full solution I used to solve it, but other answers are appreciated and I will take the time to look at each solution and evaluate what they offer. I am sure there are better ways to accomplish this task, and methods that will work better with very large audio files. In solving this problem, I barely scratched the surface on dealing with memory management.

这篇关于有效地在R中分割大型音频文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆