Post by James Cook [home]
November 18, 2020
I've been thinking lately about synthesizing sounds that convey information. As an exercise, I decided to try making a countdown timer: if you leave it playing in the background, you should be able to tell how much time is left just by passively listening.
A voice simply reciting the time would be boring and grating. How about just the right length of recorded music? That would work, but I'd like to be able to apply what I learn here more generally. Maybe "5 minute timer" can sound the same every time, but what if I'm trying to translate the stock market into sound? I'm also interested in creating interesting new sounds, not just recycling old ones. My goal is to try different things and have fun.
Here are some of the sounds I ended up with. Some of them could plausibly be used as timers, and others just sound interesting.
This sound is made of two beats, one slightly slower than the other. They start out perfectly synchronized, and the timer reaches zero when the faster beat gets exactly one cycle ahead so they're perfectly synchronized again. The faster tone beats exactly once per second.
This works pretty well if you just want to get a general sense of how much time is left, but it doesn't give much precision. Suppose the timer were an hour long: by listening, you could tell whether you're closer to the start or end of the timer, but you probably couldn't say whether there are 15 or 14 minutes left.
Here's an attempt to give a bit more information. It's the same as the last sound, but with two more beats added in. The first new beat goes through two full cycles of getting out of sync and then back in sync with the base beat, and the last (highest) one goes through four cycles. Here's a picture of what you're hearing: the four lines correspond to the four beats, from highest to lowest pitch.
The vertical lines show how different beats line up every 8 seconds. Try listening for the 16-second mark in the middle, when three of the four beats are in sync. The 8- and 24-second marks are less obvious, because only two of the four beats are in sync, and the other two distract from it. If we added more voices, the 4-second and 2-second points would be similarly marked out.
This approach seems promising to me. With some study and practice, it should be possible to figure out the number of seconds left, even with a fairly long timer: comparing the bottom two beats gives a rough idea, and each successive beat should let the trained listener add another bit of precision to their estimate.
If you want to play with the code I used to make this, see
the instructions below. This sounds are
called cycle_timer
and multi_cycle_timer
.
What's that weird music?
Oh, that's just my egg timer.
This one's not the most practical, but I like it. It's a Shepard tone that descends faster and faster, with speed approaching infinity as the countdown reaches zero, giving an intuitive sense of impending... something.
In this recording, the sound reverses once the timer reaches zero, 60 seconds in.
A sliding Shepard tone is supposed to create an illusion of going up or down forever, without ever getting so high or low you can't hear it. When I made this, I was curious to hear what the illusion would sound like as the speed increases. Unfortunately, the answer seems to be that the illusion breaks: when the pitch is changing very rapidly, it sounds like an oscillating rather than a descending tone.
This sound is called shepard_timer
if you're running the program.
The number of seconds left is a number, so why not just say it? In binary, of course. This sound encodes the remaining number of eighths of a second in binary, and plays a chord with one frequency for each possible digit:
So, for example, when 3 1/4 seconds are left, since 3 1/4 = 2 + 1 + 1/4, the chord will have three notes: 550Hz, 440Hz, 220Hz.
I don't think it's practical for a listener to decode a binary number from the chord, but it still makes an interesting sound. The rhythm makes it easy to count seconds, even if you don't know how many are left overall. Try listening for the highest note playing at any given time: it gradually goes down in pitch as the length of the binary representation decreases.
This sound is called bit_chord
.
The rest of the sounds turned out not to be so useful as timers, but they're still interesting.
I like simple mathematical functions. It would be really cool if my ideal timer sound turned out to be a waveform described by a one-line formula.
This first sound is the graph of the Hamming weight function, piped directly to your speakers as audio samples: the displacement of your speaker at time (well, sample number) t is proportional to the number of 1s in the binary representation of t.
It sounds a bit like a rhythmic crackling sound over an organ. I think this happens because the waveform can be described as a sum of square waves at power-of-2 frequencies. So, it's like an organ playing several pipes separated by octaves. The crackling sound probably comes from events where a number ending in several 1s (in binary) rolls over to a number ending in 0s with a much smaller Hamming weight. (Actually, in the spirit of a countdown timer, the numbers are counting down, so it's the reverse: a bunch of final 0s turning into 1s.)
My hope was that the repetitive nature of the Hamming weight function would somehow help the user count time. I call it a partial success. If you're really determined, you could count time using the beat of the rhythmic crackling sound. On the other hand, there's almost no overall variation: unless you listen very carefully to the intensity of the crackling, it's just the same sound repeated indefinitely.
This sound introduces a little more variation. It's the graph of a function just a little more complicated than the last one. It works like this. To compute the intensity at sample number t, start with x=0, and go through the bits of t one at a time starting with the least significant. If the bit is 1, add 1 to x. If the bit is 0, multiply x by e2πia, where a is a parameter we can choose. The result will be a complex number; as the very last step, take its magnitude.
If we take a=0, this is just the Hamming weight function. For the sample above, I used a=1/14. For example, if t=19, that's 10011 in binary, so the result is |1+3e2iπ/7|=√((1+cos 2π/7)2+(sin 2π/7)2).
The motivation here was just to try to introduce a bit more variation to the sound. The formula I used should cause the different power-of-2 cycles to interact in interesting ways. I don't know how to use it as a timer, though.
Another thing I can do with simple mathematical functions is to make melodies.
This is the same Hamming weight function as before, played as a melody: the pitch is a base frequency of 110 Hz times the hamming weight of the current time measured in in 1/8ths of a second.
The sound clip includes 10 seconds counting down to 0, followed by 30 seconds counting up.
Maybe with enough training someone could learn to use this as a timer. One basic limitation is that you'd have to listen a long time to tell the difference between t=2a+x and t=2b+x seconds left, for large values of a and b and x smaller than 2a and 2b. Both melodies will sound identical until x counts down to 0.
Here's a variation. Again, the clip is 10 seconds counting down to 0 followed by 30 seconds counting up.
This time, instead of directly computing the Hamming weight of the time t, we first replace each bit in t's binary representation with the parity of that bit and all the bits below it. For example, this preprocessing step turns 101001001 into 011000111. If the original number of 1s is odd, that would result in infinitely many 1s; in this case, we play a beat of silence. Otherwise, we play a note with pitch 110 Hz * the Hamming weight of the resulting number. This introduces a bit more variation to the sound, and the beats of silence give it some rhythm. This melody suffers from a similar limitation as the previous one.
The source code
is here. Here's
a snapshot in case I change or remove
any of the above sounds. You can also get the same snapshot using darcs
get --tag 0.0.1.1 https://hub.darcs.net/falsifian/sound_stream
.
Try making some changes, then see
the README
file for instructions to play one of the sounds.
Thanks for listening. I don't know if these are of any practical use, but I had fun making them. Please send me an email if you have questions or comments, or are having trouble getting it working.