How to Play Birthday Music Using R

How can I play birthday music using R?

If you really wanted to do this:

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)

Note you'll need to install.packages("audio") first. If you already have a specific file, you'll need to convert it to WAV format first.

If you wanted something a bit more programmery than playing a WAV file, here's a version that generates the tune from a series of sine waves:

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)

There's a few points to note. The default octave for the notes is octave 4, where A4 is at 440 Hz (the note used to tune the orchestra). Octaves change over at C, so C3 is one semitone higher than B2. The reason for the fade in make_sine is that without it there are audible pops when starting and stopping notes.

Is it possible to code music in R and play it back? (Mac OS X)

For the moment, this is the best that I've come up with:

library("audio")
library(tuneR) #import the tuneR library
for (i in 1:10) {
yo=abs(round(rnorm(1,400,500)))
f=yo #frequency of A4 note
sr=1000000
bits=116
secs=5 #length of the note set to 2
amp=1
t=seq(0, secs, 1/sr)
y= amp*sin(2*pi*f*t) #make a sinewave with above attributes
s=floor(2^(bits-2)*y) #floor it to make it an integer value
# u=Wave(s, samp.rate=sr, bit=bits) #make a wave structure
u=audioSample(x = s, rate = sr,bits = bits)
audio::play(u)
}

We could experiment with setWavPlayer('/usr/bin/afplay')

That's my modern random canon.

library(tuneR)
setWavPlayer('/usr/bin/afplay')
muss = NULL
nbnotes = 100
for (i in 1:nbnotes) {
yo = abs(round(rnorm(nbnotes,400,200)))
lengthhtime = abs(rnorm(nbnotes,0.5,0.1))
f=yo[i] #frequency of A4 note
titi = lengthhtime[i]
sr=1000
bits=16
secs=titi
amp=1
t=seq(from = 0, to = secs, by = 1/sr)
y= amp*sin(2*pi*f*t)
s=floor(2^(bits-2)*y)
muss = c(muss,s)
}
u=Wave(left = muss,right = rev(muss), samp.rate=sr, bit=bits) #make a wave structure
tuneR::play(u)

Here is a function I created to generate a random melody:

melodymachine <- function(nbnotes, seed = NULL) {
if(!is.null(seed)){set.seed(seed)}
muss = NULL
for (i in 1:nbnotes) {
yo = abs(round(rnorm(nbnotes,400,200)))
lengthhtime = abs(rnorm(nbnotes,0.0,0.2))
f=yo[i] #frequency of A4 note
titi = lengthhtime[i]
sr=1000
bits=16
secs=titi #length of the note set to 2
amp=0.99
t=seq(from = 0, to = secs, by = 1/sr)
y= amp*sin(2*pi*f*t) #make a sinewave with above attributes
s=floor(2^(bits-2)*y) #floor it to make it an integer value
muss = c(muss,s)
}
return(muss)
}

Here is an example of it:

mel1 = melodymachine(6,seed = 1)
mel2 = melodymachine(6,seed = 1)
mel3 = melodymachine(6,seed = 1)
mel4 = melodymachine(6,seed = 1)
mel5 = melodymachine(6,seed = 1)
u=Wave(left = c(mel1,mel2,mel3,mel4,mel5),
right = rev(c(mel1,mel2,mel3,mel4,mel5)),
samp.rate=sr, bit=bits) #make a wave structure
tuneR::play(u)

You can take a look at the wave here:

plot(u, 
info = TRUE,
xunit = c("time"),
ylim = NULL, main = "My random melody",
sub = "made by me",
xlab = NULL, ylab = NULL,
simplify = FALSE, nr = 2500,
axes = TRUE, yaxt = par("yaxt"),
las = 1,
center = TRUE)

Sample Image

Update:

Below are a couple of function that will help you get started playing chords in R.

library(audio)
library(tuneR)
testit <- function(x)
{
p1 <- proc.time()
Sys.sleep(x)
proc.time() - p1 # The cpu usage should be negligible
}

full.scale = function(root = 440, dist.notes = 2^(1/12), nb.notes=12) {
all.notes = NULL
for (k in 1:nb.notes) {
if(k==1){all.notes = c(all.notes, root)}
my.note = root*(dist.notes)^k
all.notes = c(all.notes, my.note)
}
return(all.notes)
}
fq.gen <- function(f = 440,
octave = 2,
secs=1/2, sr=100000,
bits=116, amp=0.1,
play = FALSE) {
octave.select = 2^c(0:6)
t = seq(0, secs, 1/sr)
y = amp*sin(pi*octave.select[octave]*f*t) #make a sinewave with above attributes
(by = round(2/3*pi*(1/(f*octave.select[octave])),5))
s=floor(2^(bits-2)*y) #floor it to make it an integer value
u = audioSample(x = s, rate = sr,bits = bits)
if (play) {
audio::play(x = u)
}
return(list(u = u, y= y, t =t, by = by, secs=secs))
}

all.notes.from.western.scale = full.scale(root = 16.35,dist.notes = 2^(1/12), nb.notes = 107)
note.name = rep(c("c","cs","d","ds","e","f","fs","g","gs","a","as","b"),9)
octave.note = rep(seq(0,(length(all.notes.from.western.scale)/12-1), by =1), each = 12)

data.notes.wstrn = data.frame(note = note.name,
octv = octave.note,
fq = all.notes.from.western.scale,
note.otv = paste0(note.name,octave.note))

a.scale = full.scale(root = 440,dist.notes = 2^(1/12), nb.notes = 12)
c.scale = full.scale(root = 523.25)
cs.scale = full.scale(root = 554.37)

# Major chord
for (i in 1) {
secs = 2
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "a4","fq"],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "cs4","fq"],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "e4","fq"],octave = 2, secs = secs,play = T)
}

# Minor chord
for (i in 1) {
secs = 2
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "a4","fq"],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "c4","fq"],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "e4","fq"],octave = 2, secs = secs,play = T)
}

# augmented chord
for (i in 1) {
secs = 2
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "a4","fq"],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "cs4","fq"],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "f4","fq"],octave = 2, secs = secs,play = T)
}

# Diminished chord
for (i in 1) {
secs = 2
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "a4","fq"],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "c4","fq"],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "ds4","fq"],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "fs4","fq"],octave = 2, secs = secs,play = T)
}

# Resolution!
for (i in 1) {
secs = 2
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "g4","fq"],octave = 1, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "b4","fq"],octave = 1, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "d5","fq"],octave = 1, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "g5","fq"],octave = 1, secs = secs,play = T)
}

# C13 chord
for (i in 1) {
secs = 4
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "g4","fq"],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "b4","fq"],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "d5","fq"],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "f5","fq"],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "a5","fq"],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "c6","fq"],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = data.notes.wstrn[data.notes.wstrn$note.otv == "e6","fq"],octave = 2, secs = secs,play = T)
}

for (i in 1:length(a.scale)) {
secs = 1/5
datadf = fq.gen(f = a.scale[i], secs = secs,play = T)
datadf = fq.gen(f = a.scale[i],octave = 3, secs = secs,play = T)
datadf = fq.gen(f = a.scale[i],octave = 4, secs = secs,play = T)
datadf = fq.gen(f = a.scale[i],octave = 5, secs = secs,play = T)
datadf = fq.gen(f = a.scale[i],octave = 6, secs = secs,play = T)
datadf = fq.gen(f = a.scale[i],octave = 7, secs = secs,play = T)
datadf.col = do.call(what = cbind, datadf)
total = which(round(datadf.col[,"t"],5) == fq.gen()$by)
datadf.col[which(round(datadf.col[,"t"],5) == fq.gen()$by),]
testit(datadf$secs-.08)
}

for (i in 1:length(a.scale)) {
secs = 1/5
datadf = fq.gen(f = a.scale[i], secs = secs,play = T)
datadf = fq.gen(f = cs.scale[i],octave = 2, secs = secs,play = T)
datadf = fq.gen(f = a.scale[i],octave = 3, secs = secs,play = T)
datadf = fq.gen(f = a.scale[i],octave = 3, secs = secs,play = T)
datadf = fq.gen(f = cs.scale[i],octave = 3, secs = secs,play = T)
datadf = fq.gen(f = a.scale[i],octave = 5, secs = secs,play = T)
datadf.col = do.call(what = cbind, datadf)
total = which(round(datadf.col[,"t"],5) == fq.gen()$by)
datadf.col[which(round(datadf.col[,"t"],5) == fq.gen()$by),]
testit(datadf$secs-.08)
}

Making a random tone-sequence in R

Here is a package to analyze music, that might help.

Here is an example you can try out.

Replicating something similar like the answer to this questions is maybe rather what you want. There the OP requests code to play the happy-birthday song in R. They code in the answer has, notes, pitch and duration, that you can easily define by yourself and sample randomly from to generate a song.

I think that it might be simpler to do most of these things in python.

Hope this helps!

How can I play birthday music using R?

If you really wanted to do this:

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)

Note you'll need to install.packages("audio") first. If you already have a specific file, you'll need to convert it to WAV format first.

If you wanted something a bit more programmery than playing a WAV file, here's a version that generates the tune from a series of sine waves:

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)

There's a few points to note. The default octave for the notes is octave 4, where A4 is at 440 Hz (the note used to tune the orchestra). Octaves change over at C, so C3 is one semitone higher than B2. The reason for the fade in make_sine is that without it there are audible pops when starting and stopping notes.

Can I make one function for all activity, to play, pause music

I can see two options:

  1. Make MediaPlayer static object.
  2. Consider implementing Single Activity approach. You will have two fragments and shared ViewModel in which you can access MediaPlayer.

The correct way to play short sounds Android?

You can use SoundPool. It fits what you want to do perfectly.

You'll just need a way to store the sound effect IDs corresponding to each image (or button).

Perhaps extend Button to store associated sound effect ID. And use a common SoundPool to play the sound effect associated to the id when the button is touched.

You can read more about SoundPool here.



Related Topics



Leave a reply



Submit