Building a noise level dashboard for your office with a Raspberry Pi
or every decibel counts
TLDR
If you are a software engineer, go play with technologies or hardware you don’t normally touch at work; insight you gain from that is invaluable and will make you productive in ways you would never expect.
Also, you can do fun things with Raspberry Pi.
Here’s a noise-o-meter for your office:
Introduction
If your job has anything to do with software, chances are you work in an open-plan office (or simply open office). This basically means sharing a single workspace with a bunch of other people.
Now, enough has been said about how these office designs actually reduce collaboration, or how people feel about them, so today I would like to concentrate on one aspect of a typical open plan office: the (ambient) noise level — and see what we can do about it.
The problem
Imagine the following: you have a few product/engineering teams sharing a single spacious open office, about twenty people overall.
Teams sit next to each other, and quite often one colleague asks another a question — especially if it needs a quick discussion that would take too long in Slack.
So, there’s a couple of people chatting about something now. Nothing dramatic.
But if at the same time there’s another colleague who needs to talk to someone else, and then another — everyone ends up raising their voices since it gets harder to hear each other, and in a few moments it gets so loud that you could easily mistake the office for a train station.
This often comes unnoticed for the actual speakers, as people are getting deep into their discussions.
But if you are a software engineer trying to tackle some new, complex and urgent engineering problem™, the hum and babble around you that is loud enough to get through your headphones will break your concentration and will prevent you from working.
Of course, you can raise your voice and ask everyone to be quiet please, and it will work. It will.
Until the next occasion in about fifteen minutes.
Also, if you do it too often, it’s easy to acquire a feeling of guilt for being the, uhm, fun killer who always wants too much and enforces his/her own rules on everyone.
The solution
One approach to the problem above is to make it visible — show everyone how loud it may get, and how a normal noise level in the office looks like. If you have a noise-o-meter with a dashboard that shows you, in real time, how loud it is, you have objective data, or facts. And it’s hard to argue the facts.
So one way to approach the issue would be to build a noise level monitor that would provide noise level data, and a dashboard to visualize that.
Before we start figuring out what kind of hardware can be used to monitor noise level, let me make an executive decision™ and say we’re going to use a Raspberry Pi, because
- it’s fun
- it’s portable enough to be placed anywhere and
- because I have one laying around.
So how could the implementation look like?
Well, the Raspberry PI would take the signal level off the microphone, and then something (which we can figure later) can provide that data to the clients.
First, let’s see about that microphone. Raspberry Pi has an audio card with the standard 3.5mm output jack, but no microphone by default. There is, however, a huge selection of extension boards, or HATs, for the PI.
Picking a HAT for the Pi
Raspberry Pi has a lot of different extension boards for audio: DACs, integrated amplifiers, microphone arrays. After checking the options, I have picked a Respeaker 4-microphone array, mainly because having several microphones means you can also track signal source.
As I was looking around for some simple software to monitor signal level using the Respeaker, I came across something much more powerful: Odas by Introlab.
Odas, among other things, offers sound source localization (that tells you where the sound comes from) along with sound source tracking ( telling you what source the sound came from). This opens up a lot of interesting possibilities: theoretically, our dashboard could show where most noise is coming from, or even track the movement of the speaker :) But since this may be getting a bit creepy, let’s stay with the original goal of simply tracking the noise level.
(Side note: There’s a paper describing sound source tracking and localization and a way to implement that on hardware with relatively limited processing power, such as the Pi. Take a look if you’re interested.)
Getting the Respeaker to work
Having installed both the driver for the Respeaker codec and Odas, we can run the binary that’s called odaslive to get some sound data:
bin/odaslive -c config/odaslive/respeaker_4_mic_array.cfg
Aaand.. we’re greeted with an error:
Sink pots: Cannot connect to server
Interesting. After digging through the odaslive config and having a look at their own GUI, I realized a few things:
- odaslive is meant to be started and controlled from the GUI or some other “server”;
- by default, odaslive connects to a TCP socket and sends the sound param data there as JSON.
Our setup actually assumes the reverse: the dashboard is going to run in a browser, so the browser will connect to the sound source.
Alright, let’s get back to the drawing board and sketch the updated solution with the information we now have.
The solution, updated
The modification we need to do to get everything to work is pretty simple: we need to add a layer that odaslive can stream data to, and which would echo the data it receives to the clients.
So our revised solution is going to have three main components:
- odaslive running on the Pi, taking the data off the respeaker board;
- the TCP server accepting data from `odaslive` and echoing it to any clients connected to it;
- dashboard. Dashboard will run on the client machines, to offload any data processing from the Pi.
Naming is one of the hardest things in software, so let’s call the TCP server mumble for the lack of better name, and continue.
So, we introduce Mumble™, a tcp server that consumes sound data [1] from the odaslive [2] and echoes the data to any clients connected to it [3].
While we’re at it, let’s use websockets to communicate between mumble and the clients.
Implementation
Mumble
Mumble is implemented in Javascript with node.js and is available on github if you want to check it out.
Javascript was an easy choice here since the Odas GUI is written in Javascript and I could borrow some code from there, just adding some WebSocket connection logic, the forEach loop to send data clients, and a couple of tests.
Here’s how the TCP server code looks like:
The `clients` is an array of Websocket connections, each of which is:
That’s all there’s to it — a TCP server echoing its received data to an array of WebSocket clients.
The dashboard
For the noise level dashboard, all you really need to do is to find a visualization tool, and you have quite a few options:
- D3.js, the mother of all the visualization tools, or so it seems
- Three.js
- Highcharts
- Raphael
- plot.ly
For the dashboard, I have chosen plot.ly since it had the necessary widgets and charts available out of the box, and had ample configuration options. It also seems to perform very well for a lot of data or for data that changes very often.
A sample dashboard, quickly piled together with some minimal javascript, is available in this github repo.
Demo
Below are some gifs of how the dashboard looks like in a few setups, ranging from quiet to pretty loud.
Note: Since I could not sample our office due to everyone working from home these days, I used this nice office simulator to generate some office-style noise.
Ambient noise / working from home (typing on the keyboard, clicking the mouse, and so on)
The office getting loud
Bonus: noise level over time
Performance
On the Raspberry PI 3b, running the odaslive and its sound tracking algorithms puts all four cores at around 25–30% CPU Usage.
Adding mumble on top doesn’t seem to load the CPUs more, and having ten connected clients still doesn’t raise the CPUs above 50% — pretty good for a computer that fits on your palm.
Some proper benchmarking is an interesting topic, but this article is getting too long, so maybe it will be a topic for the next one :)
Conclusion
We have built a simple noise meter based on the Raspberry Pi, and got to play with node.js, websockets, and some math in between.
We have found that it’s more than easy to create a TCP server with node.js, and the Pi is fast enough to run it without any major hiccups; likewise, a WebSocket server is pretty easy to put up (and probably pretty hard to do right).
What’s more important, none of the things we have seen here is something a Ruby developer touches while on the job, and doing things like these works wonders for perspective and broadening one’s choice of options when developing software.
I hope this article motivates you to try some of the things you don’t do in your daily work :)
Do you like what you see?
Give us a clap, leave a comment, or share anywhere. We appreciate feedback.
Also, check out other articles in our blog. We deal with many interesting things, for example:
- Machine learning: xgboost and treelite
- Interactive rent/sell price maps
- VueJS components
- No-bullshit illustrations
- and more :)
And if you like what we do and could consider joining our dev team, check out our openings!