Wie kann ich mit R Geburtstagsmusik spielen? [geschlossen]


81

Ich würde gerne Musik mit R spielen. Während R vielleicht nicht das beste Werkzeug für diesen Zweck ist, ist es das Werkzeug, mit dem ich vertraut bin, und es wäre schön, anderen seine Flexibilität bei solch einer freudigen Gelegenheit zu demonstrieren.

Wie könnte ich das erreichen?


7
Warum sollten Sie BD-Musik über R abspielen? R ist eine statistische Programmiersprache. Ich bin mir sicher, dass es für solche Aufgaben bessere Plattformen gibt.
David Arenburg

12
@DavidArenburg das ist sicherlich wahr, aber werfen Sie einen Blick auf Seite 33 dieser Datei tinyurl.com/odlurth (es ist Paul Murrells "R Graphics"). Die Tatsache, dass es bessere Programme gibt, um etwas zu tun, sollte uns nicht daran hindern, Feng Tian zu helfen (wahrscheinlich etwas Neues im Prozess)
MaZe

11
IMHO kann diese Frage einen gewissen Wert haben. Die Schallanalyse ( 2 ) ist eine legitime analytische Aufgabe, daher kann man sich eine Situation vorstellen, in der derjenige bereit sein könnte, Schallproben während der analytischen Arbeit organoleptisch zu verifizieren. Trotzdem ist die Geburtstagsmusik im Titel ziemlich seltsam.
Konrad

8
Ermutigen Sie diese Art von Fragen nicht, da möglicherweise die Möglichkeit besteht, Fragen zu stellen I would like to play video using R.
Avinash Raj

7
@AvinashRaj Interessanterweise hatte ich das als Folge betrachtet :) In aller Ernsthaftigkeit wären die Optionen wahrscheinlich entweder trivial (ein externes Programm starten), sinnlos (Neuimplementierung eines Videoplayers in externen Code) oder unbrauchbar (unter Verwendung von R-Code) um einen Videostream zu dekodieren und rasterImagejedes Bild zu rendern)
Nick Kennedy

Antworten:


236

Wenn Sie das wirklich wollten:

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)

Beachten Sie, dass Sie install.packages("audio")zuerst müssen. Wenn Sie bereits eine bestimmte Datei haben, müssen Sie diese zuerst in das WAV-Format konvertieren.

Wenn Sie etwas mehr Programmierprogramm als das Abspielen einer WAV-Datei wünschen, finden Sie hier eine Version, die die Melodie aus einer Reihe von Sinuswellen generiert:

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)

Es gibt ein paar Punkte zu beachten. Die Standardoktave für die Noten ist Oktave 4, wobei A4 bei 440 Hz liegt (die Note, mit der das Orchester gestimmt wird). Die Oktaven wechseln bei C, sodass C3 einen Halbton höher als B2 ist. Der Grund für das Einblenden make_sineist, dass ohne das Einblenden beim Starten und Stoppen von Noten hörbare Knallgeräusche zu hören sind.


6
@ DavidArenburg Danke. Um die Dinge etwas lächerlicher zu machen, habe ich jetzt einen Code hinzugefügt, der die Melodie aus ersten Prinzipien unter Verwendung von Sinuswellen generiert :)
Nick Kennedy

Tolle Antwort. Ich habe etwas Neues gelernt: Ich wusste nichts über das Verblassen, und ein kürzlich durchgeführtes Experiment von mir hatte genau dieses Problem. Nitpick: kein Grund zu zitieren cin do.call, und die letzte Aufgabe in make_sineist nicht erforderlich.
Konrad Rudolph

1
@KonradRudolph danke. Ich neige dazu, immer den Funktionsnamen in zu zitieren do.call. Es ist allzu leicht, in die Falle zu tappen, so etwas a <- 1; b <- 2; c <- 3auf dem Weg getan zu haben , und in dieser Situation do.call(c, ...)wird es scheitern, während c(1, 2, 3)es nicht so ist. Stimmen Sie dem letzteren Punkt jedoch voll und ganz zu und haben Sie die unnötige Zuordnung entfernt!
Nick Kennedy

1
@KonradRudolph Eigentlich do.call("c", ...)wird funktionieren. Versuchen Sie es c <- 4; do.call("c", list(1, 2)). R ist insofern einigermaßen konsistent, als in den meisten Fällen ein Argument, das eine Funktion akzeptiert, entweder die Funktion selbst oder den Namen der Funktion akzeptiert. In einigen Fällen (z. B. lapply) erfolgt dies über match.fun, während in anderen, z. B. do.call, getMethoddie Implementierung im C-Code erfolgt (für letztere über einen Aufruf von C_R_getGeneric). Ich kann sehen, warum Sie stilistisch vielleicht lieber die Funktion als ihren Namen übergeben möchten, aber das letztere Verhalten ist gut dokumentiert.
Nick Kennedy

2
@KonradRudolph Fair genug. Ich denke, das damit verbundene Problem ist, dass R immer nach einer Funktion sucht, wenn auf a symbolKlammern folgen, selbst wenn eine andere symbolweiter oben im Suchpfad vorhanden ist. Dies ermöglicht es c <- 4; c(1, 2), wie gewohnt zu arbeiten, c <- paste0; c(1, 2)ohne die Basis zu verwenden c. Ich habe Verwirrung dadurch gesehen, dass jemand c(1, 2)seinen Code ziemlich glücklich aufgerufen hat, aber dann do.call(c, ...)nicht funktioniert. Letztendlich ist mir nicht klar, ob Funktionen namentlich oder direkt bereitgestellt werden.
Nick Kennedy
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.