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?

7 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.

      1. I have found issues with the current approach of using a sound detection:
        https://gist.github.com/benjaminchodroff/7d33a34e389c31a11aaa1ad16ba4c159

        It works pretty well – but it also detects my neighbors buzzing in too… Sadly, the wire which indicates “which button the user pressed outside” only goes to the base station which is in a common area of our building. That wire does not go to my unit where my raspberry pi is located. Instead, the base station detects the signal and broadcasts a (very loud) audio buzz to my unit. For some crazy reason, I am not seeing this signal very loud and I have not had a chance to explore why. I am debating whether to fix this issue (likely I am monitoring the wrong audio?) by using some amplitude detection, or whether to move my raspberry pi system to the common area (risky, but simple) so I can simply use the high/low signal coming from the button rather than trying to audio process it. My project has been on hold for a few months due to this limitation – would love your ideas.

  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 *