1. ホーム
  2. r

[解決済み] Rを使って誕生日の音楽を演奏するには?[クローズド]

2023-06-29 02:51:08

質問

Rはこの目的には最適なツールではないかもしれませんが、私にとっては使い慣れたツールであり、このような楽しい機会にその柔軟性を他の人に示すことができたらと思います。

どうすればこれを達成できるでしょうか?

どのように解決するのですか?

本当にやりたいのであれば

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)

注意すべき点がいくつかあります。音符のデフォルトのオクターブはオクターブ4で、A4は440Hz(オーケストラのチューニングに使われる音)です。オクターブはCで切り替わるので、C3はB2より半音高くなります。フェードインの理由 make_sine でフェードインする理由は、これがないと音を出したり止めたりするときにポップ音が聞こえるからです。