Howling Winds and Stochastic Tones

March 9, 2011
By

(This article was first published on Statisfactions: The Sounds of Data and Whimsy » R, and kindly contributed to R-bloggers)

My greatest pleasures in mathematics come from observing--and here, listening to--the interplay of simple and complex. With a few axioms and definitions you can create surprising worlds, and in what seems like a mess you can find beautiful regularities. It's damn sexy, frankly.

Here, I use a simple recursive equation to directly generate my sounds in R:

 X_t=\alpha_1 X_{t-1} + \alpha_2 X_{t-2}+ \varepsilon_t


The basic idea is that to get the next value in the sequence, you add  \alpha_1 times the previous value,  \alpha_2 times the value before that, and a random number  \varepsilon_t.  \alpha_1 and  \alpha_2 stay constant, and  t just stands for an integer that represents time, or how far along we are in the process;  \varepsilon stands for a randomly-generated number, which you generate anew for each time instant  t. With a few assumptions and restrictions, this equation characterizes what's called an "autoregression of the second order".

No need for such jargon right now. With  \alpha_1=1.9808 and  \alpha_2= -0.9999 we can generate this tone:

The soundcloud widget shows you the waveform, which is a (very smooshed-together) graph of the function. I generated 100,000 values and then wrangled in R to set the scale and write the sound file. Sound files, after all, are just a bunch of numbers that your speakers turn into pulsations of sound; here I'm generating those numbers directly using an equation I learned about in time series class. (This is why Peaches instructs us, "Stay in school, cuz it's da best.") You're listening to the data at a rate of 10,000 numbers per second--much lower the CD-quality rate of 44,100 but a convenient round number for us 10-fingered folk--which means that since the whole sequence is 100,000 long that it lasts 10 seconds.

Through the awesome powers of math, I picked values of the parameters that generated a recognizable tone--the A below middle C, or 220 Hertz (cycles per second). For certain parameters, this equation can generate periodic behavior that we can hear as a tone. It's close to a pure tone--but not quite, there's a wavering quality to it. You can hear and see that when I did this, there's a moment in the middle where the sound gets much fainter. This is caused by the element of randomness--the  \varepsilon_t in the equation--and likely would happen somewhere else and a different number of times if I ran the exact same computer code in R again.

Here's another couple of possible values plugged into the equation:

 X_t=0.6165 X_{t-1} - 0.995 X_{t-2}+ \varepsilon_t


This generated this tone:

This tone, which has random perturbations on a 2000 Hz tone, has a substantially fuzzier sound, less pure than the above. You can see why this might be the case by comparing the above equation with the values I used to generate the first tone--both of the coefficients in this newer equation are closer to zero. This means that less of what you're hearing is a periodic function that makes a distinct tone, and you're hearing more of the randomness--i.e. white noise like you'd hear on a TV when you're between channels.

It turns out that  \alpha_2, the second parameter, must be between -1 and 0 to be able to generate these tones--if  \alpha_2 is less than -1, the process becomes unstable, and if it's greater than 0, it the function doesn't display the periodic behavior that allows us to hear a tone. But the closer  \alpha_2 is to 0, the less of a non-random periodic effect happens, and the more the sequence just sounds like noise. Most of the action happens right on the precipice of stability, near -1: note that even moving  \alpha_2 from -0.9999 to -0.995 produced a very audible difference. Given  \alpha_2 in this range, I can calculate  \alpha_1 to get any frequency I desire.

What if we try 0.2 for  \alpha_2 , and calculate  \alpha_1 for a frequency of 800 Hz? Here's the equation to produce this:

 X_t=0.7838 X_{t-1} - 0.2 X_{t-2}+ \varepsilon_t


And the result:

And...the noise clearly wins! The periodic aspect of this is too subtle to be audible.

To drive home the point about how  \alpha_2 needs to be close to -1, as well as to create a long, loud, gradually-changing and delightful mess, I've created an 100-second opus.  \alpha_2 starts at -0.01 and ends up at -0.999999, changing every half-second. You can hear this start out as total noise--but slowly you can hear the noise coalesce as the tone emerges. Right at the very end, the tone sounds almost completely pure. For fun and sonic joy, I generated two sounds using the same equations--one in each ear--so you also get a randomized stereo richness to the sound.

I'm looking forward to making some music with these tasty sounds, so stay tuned! The code is available on my github. Much gratitude, again, belongs to Uwe Ligges and the other contributers to the tuneR package for R.

To leave a comment for the author, please follow the link and comment on his blog: Statisfactions: The Sounds of Data and Whimsy » R.

R-bloggers.com offers daily e-mail updates about R news and tutorials on topics such as: visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...



If you got this far, why not subscribe for updates from the site? Choose your flavor: e-mail, twitter, RSS, or facebook...

Comments are closed.