Tone Detection

Hi All,

I’m trying to get FreePBX to automatically hang up the call when it detects a 400hz tone of any duration (preferably 2 seconds) from a pstn trunk

I’m new to using asterisk dialplans and contexts, however…

I’ve created two new contexts in the extensions custom config file.

One which is [hangup-400] and the other is [hangup-c].

The first one includes the from-ptsn (include =>…) and also sets TONE_DETECT(400,2000,h(hangup-c,s,1)).

[hangup-c] simply has
exten => s,1,Hangup()

Strangely this only works if the tone is playing before the phone on the internal side is answered. Afterwards, it is hit and miss and 99% of the time fails.

Interestingly, I added a log verbose to the [hangup-c] context but it isnt appearing in the log file. I assume this is never being reached but for some reason the call is still ending if the tone is played before the call is answered. I tried it again having removed the TONE_DETECT, and this doesn’t happen at all then, proving it’s not a fluke.

As a newbie, Im very confused as to the use of ‘s’ in passing the extension to “TONE_DETECT”. Is this just equivalent of “same”? Otherwise how do you pass in the current extension as a parameter?

I also suspect what might be happening is that the TONE_DETECT function is stoppping/no longer being called due to the effect of the contexts that are generated by FreePBX or that the channel is changing and therefore the function is no longer detecting anything after the call has been transferred through the inbound route. I did try and do this internally and not through an inbound route (direct internal call) by calling these custom contexts before the from-internal context but this also has the same effect.

I would greatly appreciate any advice.

Best Regards
Luke

On this specific point, s stands for “start”. It is a convention used when dialplan processing is required, but there is no meaningful extension number. It’s start, because that is what you typically want for an incoming analogue call, where Asterisk is going to handle the dial tone and handling digits, explicitly.

How does Asterisk connect to the PSTN (FXO gateway, analog card, etc.)?
What kind of PSTN lines do you have (copper pair from central office, cable MTA, fiber ONT, etc.)?

Normally, disconnect tone detection is performed by the gateway or analog card, so an explicit call to TONE_DETECT is not needed. This thread may be useful:

Also, it’s possible that your PSTN service provides some other disconnect indication, such as loop current interruption, which your interface could detect more reliably.

However, if none of the above is applicable and you must use explicit TONE_DETECT, please paste the Asterisk log for a call that failed to disconnect at pastebin.com and post the link here.

Hi Stewart

The PSTN is connected via a FXO gateway (a Cisco SPA232D to be specific). The line is from a modem which splits coax into both internet and phone but the output is analogue for the telephone. I think technically Cable MTA

Based in the UK, its a 400hz tone that lasts precisely 5 seconds. I’ve recorded it and analysed it in audio software, it fluctuates between 399 ane 409hz at -12db and also very faint peaks at -45db at 600hz, 1200hz, 1800hz etc, but these are barely audible.

There is no other indication such as polarity reversal or loop current interruption.

I’ve tried setting this on the cisco with the
400@-30;400@-30;2(3/0/1+2) as per the instructions, and I’ve also changed the frequency and timing around in various combinations to no avail over many hundreds of attempts.

I did play a pure 400hz file to test it but this doesnt work either.

The only other option I’ve got is to use the Asterisk functionality within FreePBX and then set a silence timeout in the FXO gateway as a backup.

I’ll paste the logs here tomorrow (it’s nearly midnight here).

Does there need to be a specific level of verbosity and if so how do I easilly change that within freepbx?

Thanks
Luke

https://docs.asterisk.org/Asterisk_16_Documentation/API_Documentation/Dialplan_Functions/TONE_DETECT/

pay particular attention to options d,g,h,t,r

Also

For the UK we see

Busy signal 400 Hz ---- ---- On 0.75s, Off 0.75s

but who is sending un-stuttered 'busy-tone ?

The default (verbosity 3) should be plenty, at least to start out.
I have an SPA3102 (which I believe is similar in this regard) and set up a test number with: 1s silence, 5s 400Hz@-13dBm, 10s silence, hang up.

I tried various settings:
400@-30;400@-30;6(5/5/1+2)
400@-30;400@-30;6(5/1/1+2)
400@-30;400@-30;10(5/5/1+2)
and all failed to detect the tone. So I believe that these Cisco/Linksys devices need a minimum of two ‘beeps’ for disconnect detection. I’ll PM the number so you can confirm I did it correctly.

Unless I missed something, I guess that leaves getting TONE_DETECT to work properly.

Hi Stewart,

I called the number that you provided and this is virtually identical to the tone that I hear when the line is disconnected.

Here is a google drive link that has the log file, the audio recording from one of the calls and also the dial plans that I’ve added. To prevent my PSTN number being publically available on the internet, I’ve replaced it with in the logs, to prevent it receiving spam calls.

https://drive.google.com/drive/folders/1A2eAoGfeKuM-PLVj8yvn4ibQMjy8DCDc?usp=sharing

The added dialplan to “from-internal” is just temporary to allow me to run internal tests.

The first call from this morning was from extension 002 to 001, during which I emulated the tone down the line. 002 is a softphone where the microphone is looped back to the PC audio output (stereo mix). The line did not hang up. 001 is a Yealink T22P.

The second call was also from 002 to 001, but I had the sound playing on loop before I started to make the call. After 2 seconds of ringing, freePBX rejected the call.

The third call was via the PSTN trunk on an incoming route to 001. I answered the Yealink, rejected the PSTN call and nothing happened.

As for the dialplans, I’m not sure whether I should be using “_X.” or “s” as the extension wildcard within the hangup-phones context (see screenshots). I tried both yesterday to no avail.

Thanks
Luke

Virgin Media (practically the only cable provider in the UK) send a constant busy tone. I did try the option h and also changed the decibel threshold to 5, even 1 but nothing unfortunately. I must be doing something incorrectly or putting the dialplan contexts in the wrong order.

From

It looks like exploring hangup cause 1 would be worth a bash.

What codec are you using? Handling tones requires the codec not be aggressive. ulaw and alaw should work. g729 and gsm may well not work.

@david55

I’ve tried forcing ulaw/alaw codecs, however this still doesnt work. Sometimes the tone will be recognised if played on repeat 3 or more times, sometimes it will be recognised on the first or second time the tone is played. But if played before the phone is picked up, it’s always recognised. It’d be interesting to know what the tolerance is for this function and whether there’s a multithreading issue as it is running asynchronously.

Just to clarify this setup, it is:

ISP modem/MTA with the FXS port connected to the Line/FXO port of the SPA232D which is using a SIP connection back to the PBX?

@BlazeStudios
The MTA line is connected to the FXO on the SPA232D. LAN is connected to the internet port (bridge is disabled) and the gateway SPA232D is connected to the FreePBX which runs on Debian 12 on a Hyper-v VM on the LAN.

I’ve done some debugging today of dsp.c level 10 (core set debug 10 dsp.c). The output is showing that the frequency is only being detected for every second audio sample.

An excerpt from the log:

120680 [2024-08-20 16:05:53] DEBUG[189887][C-00000009] dsp.c: 400 Hz tone Hit! 0 Ew=2.6642E+12, Et=2.6613E+12, s/n= -897.57
120681 [2024-08-20 16:05:53] DEBUG[189887][C-00000009] dsp.c: 400 Hz tone 0 Ew=6.6052E+11, Et=1.3274E+12, s/n= 0.99
120682 [2024-08-20 16:05:53] DEBUG[189887][C-00000009] dsp.c: 400 Hz tone 0 Ew=2.6605E+12, Et=2.6584E+12, s/n= -1276.28
120683 [2024-08-20 16:05:53] DEBUG[189887][C-00000009] dsp.c: 400 Hz tone Hit! 0 Ew=2.6605E+12, Et=2.6584E+12, s/n= -1276.28
120684 [2024-08-20 16:05:53] DEBUG[189887][C-00000009] dsp.c: 400 Hz tone 0 Ew=6.6094E+11, Et=1.3285E+12, s/n= 0.99
120685 [2024-08-20 16:05:53] DEBUG[189887][C-00000009] dsp.c: 400 Hz tone 0 Ew=2.6575E+12, Et=2.6564E+12, s/n= -2358.70
120686 [2024-08-20 16:05:53] DEBUG[189887][C-00000009] dsp.c: 400 Hz tone Hit! 0 Ew=2.6575E+12, Et=2.6564E+12, s/n= -2358.70

The number of milliseconds the tone needs to be detected for is based on the number of consecutive audio samples, hence the issue appears to either be with the Asterisk code, or has something to do with the audio samples that are being fed into the function. Before the call has been answered, it is detecting every sample. Strange.

I’ve actually managed to find the solution to my own problem.

Every odd numbered frame is in the receive direction and each even frame is in the transmit direction. The solution was to add the ‘r’ argument to TONE_DETECT.

That was why it was working before the phone had been answered, because only frames in the rx direction were being processed.

Solved…

TONE_DETECT detects both directions by default. Adding the r option makes it only detect the rx side.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.