如何使用R播放生日音乐?[关闭]


80

我想使用R播放音乐。尽管R可能不是达到此目的的最佳工具,但它是我熟悉的工具,很高兴在这样的欢乐时刻向他人展示其灵活性。

我该怎么做?


7
您为什么要通过R播放BD音乐?R是一种统计编程语言,请确保存在用于此类任务的更好的平台。
大卫·阿伦堡

13
@DavidArenburg当然是正确的,但请查看此文件tinyurl.com/odlurth的第33页(这是Paul Murrell的“ R Graphics”)。拥有更好的程序来做某事的事实不应该阻止我们尝试帮助冯田(可能是新的过程)
MaZe 2015年

11
恕我直言,这个问题可能有一些好处。声音分析2)是一项合法的分析任务,因此可以设想一种情况,即在进行分析工作时,一个人可能愿意从感官上验证声音样本。话虽如此,标题中的生日音乐还是很奇怪的。
Konrad

8
不要鼓励这样的问题,因为可能会有提问的可能I would like to play video using R
阿维纳什·拉吉

7
@AvinashRaj有趣的是,我认真地认为这是一个后续:),这些选项可能很琐碎(启动外部程序),毫无意义(在外部代码中重新实现视频播放器)或不可用(使用R代码)解码视频流并rasterImage渲染每个帧)
尼克·肯尼迪

Answers:


237

如果您真的想这样做:

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是,如果没有淡入淡出,则在开始和停止音符时会发出可听的声音。


6
@DavidArenburg谢谢。为了使事情变得更加荒谬,我现在添加了一些代码,这些代码使用正弦波根据第一原理生成了音调:)
Nick Kennedy

很棒的答案。我学到了一些新的东西:我不了解衰落,而我最近的一次实验就遇到了这个确切的问题。鸡蛋里挑骨头:没有理由引用cdo.call,并在最后的分配make_sine是不必要的。
康拉德·鲁道夫

1
@KonradRudolph谢谢。我倾向于总是在中引用函数名称do.call。很容易陷入a <- 1; b <- 2; c <- 3沿途做某事的陷阱,在那种情况下do.call(c, ...)将失败,而c(1, 2, 3)不会。不过,完全同意后一点,并删除了不必要的作业!
尼克·肯尼迪

1
@KonradRudolph实际上do.call("c", ...)会工作。尝试c <- 4; do.call("c", list(1, 2))。R是合理一致的,因为在大多数情况下,接受函数的参数将接受函数本身或函数名称。在一些情况下(例如lapply),这是通过match.fun,而在其他,例如do.callgetMethod,执行(通过调用后者是在C代码C_R_getGeneric)。我可以看到为什么在样式上您可能更喜欢传递函数而不是其名称,但是后一种行为已被详细记录。
尼克·肯尼迪

2
@KonradRudolph足够公平。我想相关的问题是,如果a后面加上括号,R总是会寻找一个函数symbol,即使symbol在seach路径的后面还有一个函数。这样可以c <- 4; c(1, 2)正常使用,而c <- paste0; c(1, 2)不会使用base c。我已经看到由此引起的混乱,即有人已经很高兴地c(1, 2)在他们的代码中调用,但是随后却do.call(c, ...)无法正常工作。归根结底,我对功能是按名称提供还是直接提供的功能并不太满意。
尼克·肯尼迪
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.