Comments 5
Не знаю есть ли у вас профильное образование.
Задача определения синусоподобных сигналов решается вот таким алгоритмом, очень легким по вычислениям(по сравнению с FFT — на пару порядков)
https://leonidov.su/goertzel-algorithm-lection-notes/
Лично для меня логика алгоритма чистая магия, но то, что работает — факт.
И да, в исходниках астериска уже есть реализация( у Спенсера профильное есть), на С. Используется в zaptel/dahdi
А если уж хочется именно велосипедом и на го, а не на С, то можно получить поток в реальном времени, к примеру, используя EAGI
Для попадания в войсмейл есть 99% вероятность словить "бип". Тем же алгоритмом.
На моей тестовой выборке были случаи когда частота плавает на +-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 очень привязывает именно к нему и несет дополнительные издержки по деплою в случае модуля.
Не его, а написать на С нужный вам модуль обертку. Если вам нужна толерантность в 10%, просто добаьте еще две частоты и проверки. Даже если вы 10 добавите, в реальной работе Гоертцель сможет выйти на 300 каналов на машину, а FFT — нет.
Если это задача для лабы — то да, тогда пофигу, можно и микроскопом забивать.
Если требуется проанализировать 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
Думаю данной производительности хватит даже без оптимизации по различным потокам.
Простой детектор FAS для Asterisk