Skip to content

A real time frequency finder by reading the PCM input.

Notifications You must be signed in to change notification settings

nonprenom/tones_detector

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A real time frequency finder by reading the PCM input.

The tones (ring, busy, etc...) is defined by a frequency and a pattern:

Ring: 425 Hz for 3s then silent for 1 second.

Busy: 400 Hz for 500ms then silent for 500ms

while the DTMF is normalized in the phone protocol, the other tones are specific to a country: the frequency change and the pattern

You can query all the patterns and frequencies for all the country on this online database:

https://www.3amsystems.com/World_Tone_Database?q=Israel,Busy_tone

For example, for Israel, the busy tone is: 400Hs – 0.5s on, 0.5s Off

Implementation

For this I used the Goertzel algorithm which is usually used for DTMF detection. It’s not a FFT (Fourier) because it gives only a magnitude for one frequency. It’s much easier to implement (15 lines in C) and specially adapted for embedded compare to an FFT.

Now, that I’m able to detect a frequency over the time, I implemented a pattern detector.

First, to avoid false detections, I’m not searching for [0.5 On, 0.5 Off] but for 4 of them like this:

0.5 off, 0.5 On, 0.5 off, 0.5 On, 0.5 off

Because the pattern is not 100% perfect on real samples (sometimes it’s 0.45 off, 0.52 on, 0.42 off, ...) I’m working on a statistic: how much % the real signal is close to the one I’m looking for.

I then build a definition file for RING and BUSY for all the country we are working with.

With a required magnitude of 95% and after I downloaded all the samples from the DB above, I’m able to detect all the busy tone.

Note: to clean the signal I'm using the average of the last 20 samples.

Note: I integrated this on a real time embedded platform. For this I start the detector inside a thread which take the PCM sample, not from the file like in this code, but from the PCM device.

Whenever a tone is found it call a callback to the main thread.

Below it’s a representation of the results in excel from a record on a real call. In orange it’s the Goertzel magnitude computed, in gray, it’s after I cleaned it and before pattern detection. The session is RING * 6 > DECLINE > BUSY *25

Below are the results

Israel_call_from_the_CP2.pcm

p=13 res=1 [Israel] [Ring tone] pat_size=1100 dur=11000.000 start=0.000 end=11.000

p=13 res=1 [Israel] [Ring tone] pat_size=1100 dur=11000.000 start=11.370 end=22.370

p=14 res=1 [Israel] [Busy tone] pat_size=250 dur=2500.000 start=23.320 end=25.820

p=14 res=1 [Israel] [Busy tone] pat_size=250 dur=2500.000 start=26.320 end=28.820

p=14 res=1 [Israel] [Busy tone] pat_size=250 dur=2500.000 start=29.320 end=31.820

p=14 res=1 [Israel] [Busy tone] pat_size=250 dur=2500.000 start=32.320 end=34.820

p=14 res=1 [Israel] [Busy tone] pat_size=250 dur=2500.000 start=35.320 end=37.820

p=14 res=1 [Israel] [Busy tone] pat_size=250 dur=2500.000 start=38.320 end=40.820

p=14 res=1 [Israel] [Busy tone] pat_size=250 dur=2500.000 start=41.320 end=43.820

p=14 res=1 [Israel] [Busy tone] pat_size=250 dur=2500.000 start=44.320 end=46.820

p=14 res=1 [Israel] [Busy tone] pat_size=250 dur=2500.000 start=47.320 end=49.820

p=14 res=1 [Israel] [Busy tone] pat_size=250 dur=2500.000 start=50.320 end=52.820

How to build and run (on Linux here)

gcc detect.c -o detect -lm && rm -f detect.txt && ./detect > detect.csv

It will compute all the PCM samples from the directory "pcm8kMono16ble".

It outputs the results in the terminal and the goertzel + the signal after cleaning in a CSV file. You can import this in Excel.

Just keep one sample at the beginning.

Others

Ffmpeg tools on windows

Convert a wav to a wav 8000 Hz / Mono / 16 bits LE

"c:\Program Files\ffmpeg\bin\ffmpeg.exe" -i sample.wav -ar 8000 -ac 1 -acodec pcm_u8 sample8kMono.wav

Convert all the wav of a directory to PCM 8k Mono 16 bits LE

for %i in (../wav/*) do "c:\Program Files\ffmpeg\bin\ffmpeg.exe" -y > -i ../wav/%i -ar 8000 -ac 1 -f s16le -acodec pcm_s16le %~ni.pcm

Useful links

http://en.wikipedia.org/wiki/Goertzel_algorithm

https://www.embedded.com/the-goertzel-algorithm/

https://github.com/Harvie/Programs/blob/master/c/goertzel/goertzel.c

https://stackoverflow.com/questions/67556935/busy-tone-detection-in-audio-pcm-signal