Borgström   Semantics, pragmatism and cynicism.

Slumber — A Python & Raspberry Pi sleep project

06 Aug 2015

The initial prototype build

I’ve always been an easy-going sleeper, able to have a restful sleep no matter where I’m sleeping, and able to tune out most noise while I am sleeping to stay asleep until fully recharged. However, it’s recently become helpful to have a “white noise” machine on at home to ensure that everyone gets the best sleep possible. Initially we tried some off-the-shelf products, but they were unsatisfactory — I could hear the loop points in the sounds being played back, the sound quality was terrible, etc. Being the type of person that can often build it better than I can buy it, and seeing as I’ve had some time to work on a side-project recently, this seemed to be a perfect opportunity to build something using Python & a Raspberry Pi!

Learning about sleep

The first thing I wanted to know more about was the cycles that we go through while sleeping. Most people follow a “monophasic sleep cycle” where you sleep for 6-8 hours each night, stay awake for the next 16-18 hours and then repeat. There are other sleep cycles though, like the “uberman sleep cycle” that consists of 20 to 30 minute naps every 4 hours, resulting in 6 naps each day — that often include very lucid dreams! Blogger Steve Pavlina experimented with the uberman sleep cycle for about 5 months, it’s a fascinating read! However, after learning more about sleep cycles I concluded that it wouldn’t really be possible to coordinate with someone’s sleep cycles without some sort of EEG hookup, and I didn’t think people would be OK with sleeping with electrodes on their heads… (I did originally experiment with an accelerometer, but it proved too difficult to do anything useful with the data and there is lots of doubt about how accurately you can track sleep cycles without an EEG)

After that I spent about a week collecting and reading information on the introduction of “white noise” into a sleepers environment and how it affects sleep. Going into the research I knew that it was generally accepted that white noise was good for babies since the womb is a very loud environment and adjusting to sleeping in a quiet house can be a big adjustment. But the real question I had was; is it good for adults too?

Williamson investigated the influence of ocean sounds (white noise) on the night sleep pattern of postoperative coronary artery bypass graft patients after being transferred from an ICU. The group receiving ocean sounds reported higher scores in sleep depth, awakening, return to sleep, quality of sleep, and total sleep scores, indicating better sleep than the controlled group. The study by Stanchina and colleagues suggested that white noise increased arousal thresholds in healthy individuals exposed to recorded ICU noise. The change in sound from baseline to peak, rather than the peak sound level, determined whether an arousal occurred. From [The Table] it can be seen that sound masking has the most significant effect in promoting ICU patients' sleep, producing an improvement of 42.7%.

Seems so.

I also researched what other “white noise” generators existed out there, how they worked, what sounds they included, etc. It’s good to know what the competition is doing to inform your choices.

I knew what I wanted to build; something that could layer and playback different pre-selected sounds with a pinch of randomness thrown in.

As an aside, if I hadn’t settled on building something myself using nature sounds I would totally have gotten a “noise conditioner” that actually creates real white noise through the use of something mechanical. (Like the Marpac Dohm)

The sounds and the theory

I spent a good amount of time on listening to different sounds and evaluating them. If you’ve never been on it is a great resource for people to upload things they’ve recorded, and many offer them under Creative Commons licenses — making them perfect for our project!

My theory for this project is that the sound created by the device needs to be as non-loop like as possible, and to achieve that we can layer different sounds on top of each other using different playback intervals so that the likely hood of two sounds playing on top of each other in the exact same way is minimal.

I tried 3 layers at first, but found that it could get to be a little too much with 3 things playing at the same time, so I ended up settling on 2 layers with the first being the primary sound (running water, waves, etc) and the second being complimentary sounds (wind, rain, etc).

The first layer plays for 80 minutes and then cross fades with another sound from the first layer. The second layer fades in over ~8 minutes and then fades out over another ~8 minutes before switching to a new sound and repeating. This produces non-deterministic sounds that result in combinations that do not sound like one another — ensuring that I never hear the same thing more than once.

All sounds are played as loops (so we obviously prefer sounds that are already setup to loop perfect, which there are quite a few of on and are adequately long so that you get a good amount of natural entropy.

All of the sounds can be found on GitHub. They have been converted to uncompressed wav files, and some have been normalized. The freesound ID is still in the filename (you can search by ID) and the README.rst contains full attributions.

The Python code

All of the code can be found on GitHub: (with tests & CI, of course)

Knowing that I wanted to build this on a Raspberry Pi I began to play with the available options for playing back audio in Python. The biggest criteria I had was that I wanted an easy interface that can play multiple sounds at the same time with independent volume control. Working on OS X was another criteria for me, so that I could build the code on my laptop.

This made pygame the clear winner. It’s pygame.mixer module contains a Sound object that is very straight forward to use and it’s pre-installed with Raspbian! (I initially went down a road of trying to use the Channel object, but found that I over-complicated things too much and that just using Sound worked way better).

I built a simple command language (things like play, fadeout, etc) and then tied it into the pygame code. You can find this all in the slumber.playback module.

The other portion of the code is a straight-forward event loop that is used to coordinate everything. I initially thought about trying to use the event loop from pygame, but found that it was heavily tied to their display code and since I was only using the mixer module it wouldn’t work. The event loop itself is pretty basic, it only supports callbacks with optional deadlines (i.e. to schedule things in the future). It does have a @coroutine decorator that is inspired by tornado to simplify writing the callback based code:

def some_function():
    yield do_something_right_now()
    yield do_something_next_event_loop()

You can find this all in the slumber.eventloop module.

The Raspberry Pi

Click to enlarge

For this build I want the option to eventually run this off of a battery pack, so I choose the Raspberry Pi A+ as it’s got the lowest power footprint and I don’t need any I/O (aside from a 802.11 card for debugging).

I used a 5V 3W+3W amp to drive two little 4 Ohm 3W speakers. The amp is connected to the 5V rail and ground of the Pi and an audio cable is connected from the 3.5mm headphone jack of the Pi into the input of the amp, then the two speakers are connected to the outputs, and finally everything is held in place with some velcro tape. Overall, this is a pretty straight forward build – but reminded me how out of shape I was soldering, even with only 13 connections to make.

Right now the Pi is set to start slumber on startup so we’re just plugging it in and unplugging it as necessary, but in the future I hope to add a button to control start/stop and also move it into some type of proper housing (maybe an old speaker housing, intercom, or something).

“White noise”

So why did I keep quoting “white noise”? What I wanted to build, and what I ended up building is really playing back nature sounds instead of real white noise. But, it’s just easier to call it a white noise generator.

Wrapping up

We’ve been running this for about a week (first on my laptop, and now off of the Pi prototype) and so far I can say that this has been a successful experiment and build. It was a fun project to work on from both a hardware and software standpoint as it wasn’t too much work, but was challenging enough to make it rewarding. I plan on building another one of these and refining the casing & power for the project over the next little while. I hope to eventually be able to travel with one of these devices!

If you’re interested in introducing some “white noise” into your sleeping environment I encourage you to checkout the code and provide any feedback you have. Contributions to the code or the sounds is also always welcomed!


All of the useful sources I read along the way:

comments powered by Disqus