我想使用R播放音乐。尽管R可能不是达到此目的的最佳工具,但它是我熟悉的工具,很高兴在这样的欢乐时刻向他人展示其灵活性。
我该怎么做?
我想使用R播放音乐。尽管R可能不是达到此目的的最佳工具,但它是我熟悉的工具,很高兴在这样的欢乐时刻向他人展示其灵活性。
我该怎么做?
I would like to play video using R
。
rasterImage
渲染每个帧)
Answers:
如果您真的想这样做:
library("audio")
bday_file <- tempfile()
download.file("http://www.happybirthdaymusic.info/01_happy_birthday_song.wav", bday_file, mode = "wb")
bday <- load.wave(bday_file)
play(bday)
请注意,您需要install.packages("audio")
先。如果您已有特定文件,则需要先将其转换为WAV格式。
如果您需要比播放WAV文件更多的编程知识,请使用以下版本,可通过一系列正弦波生成音调:
library("dplyr")
library("audio")
notes <- c(A = 0, B = 2, C = 3, D = 5, E = 7, F = 8, G = 10)
pitch <- "D D E D G F# D D E D A G D D D5 B G F# E C5 C5 B G A G"
duration <- c(rep(c(0.75, 0.25, 1, 1, 1, 2), 2),
0.75, 0.25, 1, 1, 1, 1, 1, 0.75, 0.25, 1, 1, 1, 2)
bday <- data_frame(pitch = strsplit(pitch, " ")[[1]],
duration = duration)
bday <-
bday %>%
mutate(octave = substring(pitch, nchar(pitch)) %>%
{suppressWarnings(as.numeric(.))} %>%
ifelse(is.na(.), 4, .),
note = notes[substr(pitch, 1, 1)],
note = note + grepl("#", pitch) -
grepl("b", pitch) + octave * 12 +
12 * (note < 3),
freq = 2 ^ ((note - 60) / 12) * 440)
tempo <- 120
sample_rate <- 44100
make_sine <- function(freq, duration) {
wave <- sin(seq(0, duration / tempo * 60, 1 / sample_rate) *
freq * 2 * pi)
fade <- seq(0, 1, 50 / sample_rate)
wave * c(fade, rep(1, length(wave) - 2 * length(fade)), rev(fade))
}
bday_wave <-
mapply(make_sine, bday$freq, bday$duration) %>%
do.call("c", .)
play(bday_wave)
有几点需要注意。音符的默认八度为八度,其中A4为440 Hz(用于调整乐团的音符)。八度在C处转换,因此C3比B2高一个半音。淡入淡出的原因make_sine
是,如果没有淡入淡出,则在开始和停止音符时会发出可听的声音。
c
中do.call
,并在最后的分配make_sine
是不必要的。
do.call
。很容易陷入a <- 1; b <- 2; c <- 3
沿途做某事的陷阱,在那种情况下do.call(c, ...)
将失败,而c(1, 2, 3)
不会。不过,完全同意后一点,并删除了不必要的作业!
do.call("c", ...)
会工作。尝试c <- 4; do.call("c", list(1, 2))
。R是合理一致的,因为在大多数情况下,接受函数的参数将接受函数本身或函数名称。在一些情况下(例如lapply
),这是通过match.fun
,而在其他,例如do.call
,getMethod
,执行(通过调用后者是在C代码C_R_getGeneric
)。我可以看到为什么在样式上您可能更喜欢传递函数而不是其名称,但是后一种行为已被详细记录。
symbol
,即使symbol
在seach路径的后面还有一个函数。这样可以c <- 4; c(1, 2)
正常使用,而c <- paste0; c(1, 2)
不会使用base c
。我已经看到由此引起的混乱,即有人已经很高兴地c(1, 2)
在他们的代码中调用,但是随后却do.call(c, ...)
无法正常工作。归根结底,我对功能是按名称提供还是直接提供的功能并不太满意。