Using a raspberry pi with a microphone to hear an audio alarm using FFT in python

If your smoke alarm or, in my case, water alarm goes off you want to know right away – even if you are currently half way across the world traveling in China. I run a fish tank. I take many precautions but you really can’t be too safe. I bought a set of Honeywell water sensors which I highly recommend. Sadly, this particular alarm is not IoT enabled. In fact, last I checked all the IoT alarm systems were terribly reviewed and overpriced. Hopefully that gets fixed soon. Until then, I needed to make do with what I had.

Rather than ripping the alarms open and hard wiring in a detection, I wanted to use an audio detection method so I could listen to many devices around the house. I wanted to receive a text message if any alarm went off and my raspberry pi could hear it. I saw some commercial devices for sale but what is the fun in that, honestly? I scoured github and google for some example code, but did not find much. So, here is my quick and dirty audio alarm sensor code.

DISCLAIMER: Under no circumstances should this code be used in any safety or production setting. Using an audio mechanism to listen for safety alerts is just plain dumb and could easily malfunction causing serious injury or death. This is for education purposes only.

This code works on a set of moving windows to detect¬†confirmed alarm beeps. My alarm beeps at 3500Hz with a regular interval. I used a fast fourier transform with numpy in python to isolate¬†the most intense sounds. I then use quadratic interpolation to determine the frequency of the most intense sound wave. If enough “blips” fill a window to detect a “beep,” and enough “beeps” fill a larger window, then the program indicates the alarm is active. If enough non-beep detected windows pass, it will clear the alarm detection.

At some point I’ll need to learn machine learning and teach it how to automatically recognize different types of alarms! Anyone have some tips?

5 thoughts on “Using a raspberry pi with a microphone to hear an audio alarm using FFT in python”

  1. Thanks for sharing this, the code looks like exactly what I was looking for…except I want to modify it to detect when our doorbell goes off!

    What did you use as a microphone and how did you connect it up to the Pi?

    1. I use a blue yeti USB microphone connected to my raspberry pi. It works great! I have a cheaper USB input too but I have not tested it yet… it likely will require lowering the sample rate.

  2. I had this code running on a Mac, no problem. I am trying to run it on an RPi now, and not having much success. arecord and aplay run fine, like: “arecord example.wav -D sysdefault:CARD=1”

    When I try to run your code, I get:

    {bunch of ALSA warnings not shown}

    Alarm detector working. Press CTRL-C to quit.
    freq= 42.4418160133
    Traceback (most recent call last):
    File “chodroff.py”, line 49, in
    _stream.get_read_available()), dtype=short)[-NUM_SAMPLES:]
    File “/usr/local/lib/python2.7/dist-packages/pyaudio.py”, line 608, in read
    return pa.read_stream(self._stream, num_frames, exception_on_overflow)
    IOError: [Errno -9981] Input overflowed

    Maybe those ALSA warnings are significant, but overflow sounds like a memory issue. How much memory is installed on the RPi you’re using, please?

    1. What external microphone are you using and what is the sample rate it supports? I believe your memory issue may actually be that you are exceeding the sample rate of your external microphone sound card. I have a very nice usb microphone (blue yeti – supports 48khz) but many cheap sound cards may require a smaller sample rate.

      1. Oh, my mic is a piece of junk! I had no idea it could be the mic — I suppose PNP mics must have a built -in sound card. I’ll try turning the sample rate down for a test. Thanks so much!

        I do a radio show for print-disabled people, and I’ve been looking for an excuse to get a better mic, so thanks twice!

        Ron

Leave a Reply

Your email address will not be published. Required fields are marked *