module SDR.FilterDesign (
sinc,
hanning,
hamming,
blackman,
windowedSinc,
plotFrequency
) where
import Graphics.Rendering.Chart.Easy
import Graphics.Rendering.Chart.Backend.Cairo
import Data.Complex
import qualified Data.Vector.Generic as VG
sinc :: (Floating n, VG.Vector v n)
=> Int
-> n
-> v n
sinc size cutoff = VG.generate size (func . () ((size 1) `quot` 2))
where
func 0 = cutoff
func idx = sin (pi * cutoff * fromIntegral idx) / (fromIntegral idx * pi)
hanning :: (Floating n, VG.Vector v n)
=> Int
-> v n
hanning size = VG.generate size func
where
func idx = 0.5 * (1 cos((2 * pi * fromIntegral idx) / (fromIntegral size 1)))
hamming :: (Floating n, VG.Vector v n)
=> Int
-> v n
hamming size = VG.generate size func
where
func idx = 0.54 0.46 * cos((2 * pi * fromIntegral idx) / (fromIntegral size 1))
blackman :: (Floating n, VG.Vector v n)
=> Int
-> v n
blackman size = VG.generate size func
where
func idx = 0.42 0.5 * cos((2 * pi * fromIntegral idx) / (fromIntegral size 1)) + 0.08 * cos((4 * pi * fromIntegral idx) / (fromIntegral size 1))
windowedSinc :: (Floating n, VG.Vector v n)
=> Int
-> n
-> (Int -> v n)
-> v n
windowedSinc size cutoff window = VG.zipWith (*) (sinc size cutoff) (window size)
signal :: [Double] -> [Double] -> [(Double, Double)]
signal coeffs xs = [ (x / pi, func x) | x <- xs ]
where
func phase = magnitude $ sum $ zipWith (\index mag -> mkPolar mag (phase * ( index))) (iterate (+ 1) ( ((fromIntegral (length coeffs) 1) / 2))) coeffs
plotFrequency :: [Double]
-> IO ()
plotFrequency coeffs = toFile def "frequency_response.png" $ do
layout_title .= "Frequency Response"
plot (line "Frequency Response" [signal coeffs $ takeWhile (< pi) $ iterate (+ 0.01) 0])