go-dsp
go-dsp copied to clipboard
Arctan-less Frequency Demodulation
Have you given any thought to implementing a frequency demodulator that doesn't require atan2? The trigonometric calculations can be avoided by calculating the time-derivative of atan(imag(i)/real(i)):

Which simplifies out to something like:
func Discriminate(in []complex64, out []float32) {
for idx := range out {
n := in[idx] // n
np := in[idx+1] // n'
out[idx] = -(real(n)*imag(np) - imag(n)*real(np)) / (real(n)*real(n) + imag(n)*imag(n))
}
}
BenchmarkPolarDiscriminator32-4 10000000 140 ns/op
BenchmarkFMDemodulation-4 5000 349066 ns/op 11.73 MB/s
BenchmarkFMDemodulation_Go-4 3000 572701 ns/op 7.15 MB/s
BenchmarkDiscriminate-4 5000 337096 ns/op 12.15 MB/s
Where input is of length n+1 and output of length n.
I've compared this with your implementation on an RPi2 and the code go generates for ARM (GOARM=7) is slightly faster than your optimized assembly version. I imagine there's some room for improvement if this was implemented in asm.