|
- package dsp
-
- import "math"
-
- // LowpassFIR returns windowed-sinc lowpass taps (Hann).
- func LowpassFIR(cutoffHz float64, sampleRate int, taps int) []float64 {
- if taps%2 == 0 {
- taps++
- }
- out := make([]float64, taps)
- fc := cutoffHz / float64(sampleRate)
- if fc <= 0 {
- return out
- }
- m := float64(taps-1) / 2.0
- for n := 0; n < taps; n++ {
- x := float64(n) - m
- var sinc float64
- if x == 0 {
- sinc = 2 * fc
- } else {
- sinc = math.Sin(2*math.Pi*fc*x) / (math.Pi * x)
- }
- w := 0.5 * (1 - math.Cos(2*math.Pi*float64(n)/float64(taps-1)))
- out[n] = float64(sinc) * w
- }
- return out
- }
-
- // ApplyFIR applies real FIR taps to complex IQ.
- func ApplyFIR(iq []complex64, taps []float64) []complex64 {
- if len(iq) == 0 || len(taps) == 0 {
- return nil
- }
- out := make([]complex64, len(iq))
- n := len(taps)
- for i := 0; i < len(iq); i++ {
- var accR, accI float64
- for k := 0; k < n; k++ {
- idx := i - k
- if idx < 0 {
- break
- }
- v := iq[idx]
- w := taps[k]
- accR += float64(real(v)) * w
- accI += float64(imag(v)) * w
- }
- out[i] = complex(float32(accR), float32(accI))
- }
- return out
- }
-
- // Decimate keeps every nth sample.
- func Decimate(iq []complex64, factor int) []complex64 {
- if factor <= 1 {
- out := make([]complex64, len(iq))
- copy(out, iq)
- return out
- }
- out := make([]complex64, 0, len(iq)/factor+1)
- for i := 0; i < len(iq); i += factor {
- out = append(out, iq[i])
- }
- return out
- }
|