Subaudible Tone Decoder


I am very new to Arduino development. One thing I would love to create is a subaudible tone decoder.

For those that don't know what these are. Satellite radio networks send down a 25hz, or 35 hz audio tone that the local radio station detects in order to play its local spots.

I was wondering if I could build such a decoder using the Arduino, via one of the analog input pins.

After doing some research, I think I have come up with a few ideas. I was thinking of using the pulsein function, but their is going to be so much junk on the line (music, talking, ect) that I don't think that would work too well.

On the plus side, the subaudible tone is only on the positive side of the spectrum, so I can use a diode to filter out all the negative voltages, and a voltage pre-limiter of some sort to keep it under 5v.

So measuring audio level (voltage) seems to be the easy problem. Measuring time(frequency), while only paying attention to a certain frequency seems to be hard part.

I saw that arduino has a micro() function, that might be used to solve this problem, but I was wondering how accurate it was. I know that when I did work on the basic stamp years ago, you could never count of any time measurements generated by the stamp since they would change depending on how long it took the processor to make a loop. Would I have the same problem on the arduino? Or would micro() be pretty accurate?

I suspect this will help...

Ouch, not going to lie to you that formula scares the h e double hockey sticks out of me (too many flash backs to collage math courses).

None the less I will see if I can understand it. Right off the top of my head I don't know what is going on with it, though I am sure it will become more clear once I get a piece of paper out and start plugging some numbers into it.

Before trying to understand the formula, spend some time searching. Similar questions have been asked before. It's possible some kind soul is willing to help or is willing to provide source code.

while only paying attention to a certain frequency seems to be hard part.

Hint: a low-pass filter may be helpful here.

If you don't mind a hardware solution, look at the xr2211 or ne567 tone detectors.


Thanks kg, I might pick up the detectors for the short term (and the low-pass filter was a very good, and simple idea that I just didn’t think of for some reason), but now I have my curiosity peaked I am going to try to crack that formula, if nothing else I should learn a bunch along the way.

I hate to ask a dumb question, but I still wonder why I have to resort to trig in order to solve this problem.

What I mean, is this is pretty low frequency stuff (25hz), and square wave, with the time on high, the same as the time on low, and very consistent for about 2 seconds.

Couldn't I just sample the input voltage on the analog pin say 50 times a second, looking for a high, then fast drop to low. If the arduino sees that, it would wait 40 milliseconds (or maybe keep taking samples to make sure its a flat wave), and then see if the voltage goes back up to the same level (or pretty close) as the first high. If it doesn't see this the frequency is wrong, it dumps the subroutine, and starts from the beginning.

If it does the arduino would look for the same thing on the low voltage (40ms of low, followed by a sudden spike of high). The arduino could keep doing this for several cycles to make sure it was a generated pulse and not random noise.

I am pretty sure I am missing something big that is a real show stopper, or that I am overlooking something important, but I can't see what it is.

A little off topic, but one of the reasons I want to do this in software is that someday I would love to create my own subaudible tones, but instead of having 25hz of high and low evenly spaced, I could alter the highs and lows somewhat. If the arduino could catch the first 8 pules of a subaudible tone, and knew the frequency I could use the next 4 pules to send a binary code out. Giving my single 25hz tone the ability to make up to 15 different closures. Perhaps I am just asking too much.

What I mean, is this is pretty low frequency stuff (25hz), and square wave, with the time on high, the same as the time on low, and very consistent for about 2 seconds.

Are there other frequencies included with the local spot indicator? I assumed the 25Hz thing was comingle with an audio signal (DJ chatter; a song). Or is there a "moment of silence" during which the 25Hz signal is emitted?

Are subaudible frequencies removed from the audio signal so that the only 25Hz signal would be the local spot indicator?

By and large, during the time of the tone, the audio is either cut, or brought down very low as to not overwhelm the sub-audible tone. This is basically 1950’s tech, when this was established, so it had to be done with tubes, and resistors at the time, and they had no way of filtering out the tone from everything else. The entire sub-audible tone sort of just evolved into satellite since the infrastructure was already their.

For simplicity I don’t have to mute the sub audible in my application. I suppose I could mute it out, but that would make things more complex than I feel they have to be, especially at this stage, with me being a newbie and all.

In most broadcast situations the subaudible detector is able to pick up the tone pretty fast (usually after a few pulses), and quickly mute it out for the duration of the local break, or a local id, so that the listener only hears a slight and very fast rumble. For what I need to do, it doesn’t matter if the listener hears it. I am not that picky.

this is pretty low frequency stuff (25hz), and square wave,

Square wave? Are you sure?

Usually these tones are textbook sine waves.


Hey Captain,

I understand, that's nicer to go without a LM567 (about 0.75 US$) or other tone decoders, but when you want to go without any hardware (even a low pass filter), you should have your low pass filter anyway by software.

F.e., you could install a software FIFO RAM space (play with it's size for best results) and get the arithmetic middle out of these values to create a new (low passed) stream of values (Hope, you know what I mean).

Within these low passed values, you can easily check for a 25Hz or 35Hz tone, (nearly) as you mentioned above. BUT take into account, that this will be more a sin wave, than a simple HIGH/LOW-"function".

Without such (or similar) filters, you will get spikes (or other tones) in your data, and then, you often won't be able to detect the (not really) subaudible tones with ease.

But you could also go the more mathematical way with a FFT: see here:

Just my two Cents ...


Who stops getting better, has stopped being good. (Philip Rosenthal)