Me gustaría reproducir música usando R. Si bien R puede no ser la mejor herramienta para este propósito, es la herramienta con la que estoy familiarizado y sería bueno demostrar a otros su flexibilidad en una ocasión tan feliz.
¿Cómo podría lograr esto?
I would like to play video using R
.rasterImage
renderizar cada cuadro)Respuestas:
Si realmente quisieras hacer esto:
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)
Tenga en cuenta que
install.packages("audio")
primero deberá hacerlo . Si ya tiene un archivo específico, primero deberá convertirlo a formato WAV.Si deseaba algo un poco más de programación que reproducir un archivo WAV, aquí hay una versión que genera la melodía a partir de una serie de ondas sinusoidales:
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)
Hay algunos puntos a tener en cuenta. La octava predeterminada para las notas es la octava 4, donde A4 está a 440 Hz (la nota utilizada para afinar la orquesta). Las octavas cambian en C, por lo que C3 es un semitono más alto que B2. El motivo del fundido de entrada
make_sine
es que sin él hay estallidos audibles al iniciar y detener notas.fuente
c
endo.call
, y la última asignación demake_sine
un carácter superfluo.do.call
. Es muy fácil caer en la trampa de haber hecho algo asía <- 1; b <- 2; c <- 3
en el camino, y en esa situacióndo.call(c, ...)
fallará, mientrasc(1, 2, 3)
que no. Sin embargo, estoy completamente de acuerdo con el último punto y ¡hemos eliminado la tarea innecesaria!do.call("c", ...)
funcionará. Pruebac <- 4; do.call("c", list(1, 2))
. R es razonablemente consistente en que, en la mayoría de los casos, un argumento que acepta una función aceptará la función en sí o el nombre de la función. En algunos casos (plapply
. Ej. ), Esto es víamatch.fun
, mientras que en otros, p. Ejdo.call
.getMethod
, La implementación está en el código C (para este último a través de una llamada aC_R_getGeneric
). Puedo ver por qué estilísticamente puede preferir pasar la función en lugar de su nombre, pero este último comportamiento está bien documentado.symbol
está seguida de paréntesis, incluso sisymbol
existe otra más adelante en la ruta de búsqueda. Esto permitec <- 4; c(1, 2)
trabajar con normalidad, mientrasc <- paste0; c(1, 2)
que no utilizará la basec
. He visto confusión creada por esto donde alguien ha estado llamando felizmentec(1, 2)
en su código, pero luegodo.call(c, ...)
no funciona. Al final del día, no estoy muy seguro de si las funciones se proporcionan por nombre o directamente.