Math sounds

Some demonstrations of using R (the tuneR package) and bc (the Unix utility calculator) to create sounds (music??) in R based on mathematical structures such as (1) iterations of the discrete logistic map in the chaotic regime or (2) the duodecimal digits of \( \pi \).

Basics

library(tuneR)

The basic example from ?Wave: an A-440 sine wave. "play" is the WAV-player that works on my system.

play(Wobj <- sine(440, bit = 16, duration = 2000), "play")

Discrete logistic map

Compute 200 iterations of the discrete logistic map:

params <- list(r = 3.99)
X <- 0.5
n <- 200
X <- Reduce(function(X, i) with(params, r * X * (1 - X)), seq(n), X, accumulate = TRUE)

Convert this to 0.1-second sine tones with frequencies between A-220 and A-440 (since X varies from 0 to 1)

w2 <- do.call(bind, sapply(round(220 * (1 + X)), sine, bit = 16, duration = 0.1, 
    xunit = "time"))
writeWave(w2, "chaos.wav")

I would use play(w2,"play") on my system to play the sound from within R, or get the WAV file online

\( \pi \)

Now I want to play the value of \( \pi \). Various people have discussed musical interpretations of \( \pi \), and in particular the idea of a correspondence between the duodecimal representation of \( \pi \) and a chromatic (12-tone) scale:

I thought briefly about trying to do the base conversion myself (e.g. see this StackOverflow question on base conversion), but dealing with non-integer values in arbitrary precision is more trouble than I want to deal with right now.

Instead, following suggestions in some of the linked material above, the easiest way to do this is to call the bc program. The following call sets the output base to duodecimal (obase=12); specifies 200 digits of precision (scale=200); and computes \( 4\cdot\text{atan}(1) \) (Wikipedia):

if (!file.exists("duodec_pi.txt")) {
    system("echo 'obase=12; scale=230; 4*a(1)' | bc -l >duodec_pi.txt")
}

If you don't have bc on your system you can also get the output file online.

## reformat bc output to a single string
dpi <- paste(gsub("\\\\", "", readLines("duodec_pi.txt")), collapse = "")
## reconvert the [0-9AB] values to integers 1-12
letterstring <- c(0:9, LETTERS[1:2])
dpi_ind <- strsplit(dpi, "")[[1]][-2]  ## drop decimal point!
vals <- match(dpi_ind, letterstring)
## convert to chromatic tones from A-220 up
freq <- exp(log(220) + log(2)/12 * (vals - 1))
w3 <- do.call(bind, sapply(freq, sine, bit = 16, duration = 0.1, xunit = "time"))
writeWave(w3, "dpi.wav")

Again, use play(w3,"play") or get the file online

Does \( \tau \) (i.e \( 2\pi \)) sound much different?

if (!file.exists("duodec_tau.txt")) {
    system("echo 'obase=12; scale=230; 8*a(1)' | bc -l >duodec_tau.txt")
}
## reformat bc output to a single string
dtau <- paste(gsub("\\\\", "", readLines("duodec_tau.txt")), collapse = "")
## reconvert the [0-9AB] values to integers 1-12
letterstring <- c(0:9, LETTERS[1:2])
dtau_ind <- strsplit(dtau, "")[[1]][-2]  ## drop decimal point!
vals <- match(dtau_ind, letterstring)
## convert to chromatic tones from A-220 up
freq <- exp(log(220) + log(2)/12 * (vals - 1))
w4 <- do.call(bind, sapply(freq, sine, bit = 16, duration = 0.1, xunit = "time"))
writeWave(w4, "dtau.wav")

You can get the bc results or the WAV file if you like …

Other ideas:

source(url("http://developer.r-project.org/CRAN/Scripts/depends.R"))
reverse_dependencies_with_maintainers("tuneR", c("Depends", "Imports", "LinkingTo", 
    "Suggests"))
##      Package           Version Maintainer                                 
## [1,] "ProjectTemplate" "0.4-2" "John Myles White <jmw@johnmyleswhite.com>"
## [2,] "seewave"         "1.6.5" "Jerome Sueur <sueur@mnhn.fr>"

library("sos"); findFn("music") may be more useful (although still not too much there).