FAS (False Answer Supervisor) это техника используемая различными провайдерами VoIP для увеличения длительности и соответственно стоимости звонка.

FAS бывает следующих видов:

  1. Ответ на звонок и трансляция в линию звонящего тишины или гудков

  2. Добавление тишины или записи разговора после того как тот кому звонили повесил трубку.

  3. Округление значения длинны звонка в биллинге оператора

Несмотря на то что вариант 1 является самым простым для детектирования он используется очень часто.

Детектирование гудков после ответа

Поскольку известны частоты для гудка в разных странах возможно понять что в аудио канале есть FAS по наличию следующих частот:

425Hz
440Hz - для Франции
450Hz - для Китая
480Hz - один из тонов оборудования Bell
400Hz - один из тонов используемых в UK

Для детектирования данных тонов необходимо взять запись звонка после ответа и разложить его с помощью FFT на составляющие частоты, если данные частоты являются превалирующими в окне измерения, то можно считать что мы слышим гудок.

Пример dialplan для asterisk

Для записи можно использовать простой пример dialplan для Asterisk который произведет вызов через оператора связи и запишет разговор в файл для дальнейшего анализа.

[fas]
exten => _XX.,1,Set(filename=${EXTEN}-${EPOCH})
exten => _XX.,n,MixMonitor(/tmp/${filename}.wav,b)
exten => _XX.,n,Dial(SIP/trunk/${EXTEN})

exten => h,1,GotoIf($["${DIALSTATUS}" = "ANSWER"]?detect:exit)
exten => h,n(detect),StopMixMonitor()
exten => h,n,Agi(/usr/local/bin/fas-detector,${filename})
exten => h,n,Set(CDR(fas_detected)=${FAS_DETECTED})
exten => h,n(exit),NoOp

Программа распознавания тонов

Для распознования тонов мной был написан простой детектор который проходит по файлу первые 5 секунд и смотрит в окнах размером в 500 миллисекунд есть ли там гудки. Результат детектора пишется в переменную FAS_DETECTED которая может быть использована для записи в CDR.

Исходный код расположен у меня на Github

Выводы

К сожалению данный метод детектирования не защищен от ложноположительной реакции при попадании на VoiceMail и не является решением которое можно использовать в операторской инфраструктуре.

Тем не менее он дает возможность найти вероятные проблемы и разобрать их уже в ручном режиме без необходимости проверять все звонки.

Дальнейшим улучшением может являтся обучение моделей глубинного обучения для улучшения детектирования. С помощью данного фильтра возможно собрать обучающую выборку.

Комментарии (5)


  1. arheops
    05.04.2023 03:50

    Не знаю есть ли у вас профильное образование.
    Задача определения синусоподобных сигналов решается вот таким алгоритмом, очень легким по вычислениям(по сравнению с FFT — на пару порядков)
    https://leonidov.su/goertzel-algorithm-lection-notes/
    Лично для меня логика алгоритма чистая магия, но то, что работает — факт.


    И да, в исходниках астериска уже есть реализация( у Спенсера профильное есть), на С. Используется в zaptel/dahdi
    А если уж хочется именно велосипедом и на го, а не на С, то можно получить поток в реальном времени, к примеру, используя EAGI


    Для попадания в войсмейл есть 99% вероятность словить "бип". Тем же алгоритмом.


    1. UserAd Автор
      05.04.2023 03:50

      На моей тестовой выборке были случаи когда частота плавает на +-50Hz и Герцель показал себя гораздо хуже (порядка 10% ложноотрицательных результатов). Реализация в Asterisk основана на нем. В реализации DSP там проверяются тоны только для US, UK и Costa Rica (Конечно большая часть их будет по всему миру).

      Возможно можно использовать его

      
      [fas_detect]
      exten => s,1,Set(TONE_DETECT(0,,сg(alert-fas,s,1))=))
      exten => s,n,Goto(exit)
      exten => s,n,VERBOSE(${TONESCANSTATUS})
      exten => s,n,(exit),NoOp()
      
      [fas]  
      ...
      exten => _XX.,n,Dial(SIP/trunk/${EXTEN},,U(fas_detect))
      ...
      
      

      Я не проврял данный dialplan, но выглядеть должно примерно так.

      В любом случае я взял Asterisk как систему на которой можно быстро экспериментировать, в нашем случае это один из фильтров включая определение AMD, FAS и некоторые другие характеристики звонка вроде щелчков, потери фреймов приводящие к искажению звука и другие проблемы.

      Использование модулей к Asterisk или EAGI очень привязывает именно к нему и несет дополнительные издержки по деплою в случае модуля.


      1. arheops
        05.04.2023 03:50

        Не его, а написать на С нужный вам модуль обертку. Если вам нужна толерантность в 10%, просто добаьте еще две частоты и проверки. Даже если вы 10 добавите, в реальной работе Гоертцель сможет выйти на 300 каналов на машину, а FFT — нет.
        Если это задача для лабы — то да, тогда пофигу, можно и микроскопом забивать.


        1. UserAd Автор
          05.04.2023 03:50

          Если требуется проанализировать M частотных составляющих в сигнале из N отсчётов, то при M < \log_2 N алгоритм Гёрцеля эффективнее, чем БПФ.

          У меня проверяется 5 частот со сдвигом в +-5Hz, что дает нам для герцеля 54 частоты, если надо 10 добавить, то выйдет уже 88. M=88

          При размере окна в 4096 (1 / 2 секунды) Log2(4096) = 12

          Таким образом даже при +- 5 утверждение 54 < 12 неверно. Так что, согласно статье что вы привели, мы получаем что FFT будет быстрее. Я провел простой бенчмарк:

          package main
          
          import (
            "testing"
          
            "github.com/mjibson/go-dsp/fft"
            "github.com/mjibson/go-dsp/window"
          )
          
          func BenchmarkFFT(b *testing.B) {
            for n := 0; n < b.N; n++ {
              w := make([]float64, 4096)
              window.Apply(w, window.Hamming)
              fft.FFTReal(w)
            }
          }
          

          И получил следующие результаты:

          goos: linux
          goarch: amd64
          pkg: github.com/userad/fas-detector
          cpu: Intel(R) Core(TM) i7-6770HQ CPU @ 2.60GHz
          BenchmarkFFT-8              3362            333615 ns/op
          PASS
          ok      github.com/userad/fas-detector  1.163s
          

          Думаю данной производительности хватит даже без оптимизации по различным потокам.


          1. arheops
            05.04.2023 03:50

            Вам не нужны точные вычисления дла Гоартцеля, смотрите исходники астериска.
            У меня есть кусок кода который вообще от 300 до 2500Hz перебирает(generic beep detect) и все еще быстрее FFT
            Приведенный бенчмарк не особо осмысленный, поскольку вероятно выполняется в кеше процессора.