【发布时间】:2013-12-20 23:22:53
【问题描述】:
之前我问过this question on SO about splitting an audio file。我从@Jean V. Adams 那里得到的答案相对来说(缺点:输入是立体声,输出是单声道,而不是立体声)对于小型声音对象来说效果很好:
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 个小时),但我最终关闭了会议结束前。
有没有人有任何想法或解决方案来有效地使用 R 将大型音频文件(特别是 S4 类 Wave 对象)拆分成更小的部分?我希望大大减少从这些大文件中制作小文件所需的时间,并且我希望使用 R。但是,如果我不能让 R 有效地完成任务,我将不胜感激这项工作的其他工具。上面的示例数据是单声道的,但我的数据是立体声的。示例数据可以使用:
tico@stereo <- TRUE
tico@right <- tico@left
更新
我在第一个解决方案的基础上确定了另一个解决方案:
lapply(index, function(i) audio[(breaks[i]*freq):(breaks[i+1]*freq)])
比较三种解决方案的性能:
# 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-4x)。 @CarlWitthoft 的解决方案更快,缺点是它将数据放入矩阵而不是多个 Wave 对象,我将使用 writeWave 保存。据推测,如果我正确理解如何创建这种类型的 S4 对象,从矩阵格式转换为单独的 Wave 对象将相对简单。有没有改进的余地?
【问题讨论】:
-
也许
foo<-matrix(audio,ncol=X)其中X是每个breaks[i]*freq:breaks[i+1]*freq的长度。然后矩阵的每一行都是您的样本之一。这确实取决于具有相同长度的样本。 -
@CarlWitthoft 我尝试了这种方法。
audio是一个 S4 对象。所以,我收到了这个错误Error in as.vector(data) : no method for coercing this S4 class to a vector。我几乎没有使用 S4 对象的经验,这意味着我有一些阅读工作要做。我猜我可能必须分别使用audio@left和audio@right才能使用您建议的方法。 -
是的,听起来(对不起!)是对的。从
audio槽中拉出向量数据。 -
@CarlWitthoft 您的解决方案明显更快,但这确实意味着我需要使用生成的矩阵来创建新的
Wave对象,我之前没有将其指定为所需的输出。如果您想将其发布为答案,我很乐意至少给它一个 +1。 -
@PaulHiemstra 感谢您的建议。我最终发布了我实际用于当前问题的方法。只是试图添加到该网站,我希望我不会惹恼任何羽毛。关于元堆栈溢出的礼仪有很多争论,我尽量不做任何可疑的事情,但如果我做错了什么/没有帮助,请告诉我。
标签: r performance audio file-io split