module DSP.Filter.FIR.Taps (lpf, hpf, bpf, bsf, mbf, rc) where
import Data.Array
indexes :: (Integral a, Num b, Enum b) => a -> [b]
indexes m = [ 0 .. fromIntegral m ]
lpf_tap :: (Integral a, Floating b, Eq b) => b -> a -> b -> b
lpf_tap wc m n | n-a == 0 = wc / pi
| otherwise = sin (wc * (n-a)) / (pi * (n-a))
where a = (fromIntegral m) / 2
hpf_tap :: (Integral a, Floating b, Eq b) => b -> a -> b -> b
hpf_tap wc m n | n-a == 0 = 1 - wc / pi
| otherwise = sin (pi * (n-a)) / (pi * (n-a)) - lpf_tap wc m n
where a = (fromIntegral m) / 2
mbf_tap :: (Integral a, Floating b, Eq b) => [b] -> [b] -> a -> b -> b
mbf_tap (g:[]) (w:[]) m n = g * lpf_tap w m n
mbf_tap (g1:g2:gs) (w:ws) m n = (g1-g2) * lpf_tap w m n + mbf_tap (g2:gs) ws m n
mbf_tap _ _ _ _ = error "mbf_tap: bands out of sync"
rc_tap :: (Integral a, Floating b, Eq b) => b -> b -> a -> b -> b
rc_tap ws b m n | n-a == 0 = 1
| den == 0 = 0
| otherwise = sin sarg / sarg * cos carg / den
where sarg = ws * (n-a) / 2
carg = b * ws * (n-a) / 2
den = 1 - 4 * ((b*ws*(n-a)) / (2*pi)) ^ (2::Int)
a = (fromIntegral m) / 2
lpf :: (Ix a, Integral a, Enum b, Floating b, Eq b) => b
-> a
-> Array a b
lpf wc m = listArray (0,m) $ map (lpf_tap wc m) (indexes m)
hpf :: (Ix a, Integral a, Enum b, Floating b, Eq b) => b
-> a
-> Array a b
hpf wc m = listArray (0,m) $ map (hpf_tap wc m) (indexes m)
bpf :: (Ix a, Integral a, Enum b, Floating b, Eq b) => b
-> b
-> a
-> Array a b
bpf wl wu m = listArray (0,m) $ zipWith (+) (elems $ lpf wu m) (elems $ hpf wl m)
bsf :: (Ix a, Integral a, Enum b, Floating b, Eq b) => b
-> b
-> a
-> Array a b
bsf wl wu m = listArray (0,m) $ zipWith (+) (elems $ lpf wl m) (elems $ hpf wu m)
mbf :: (Ix a, Integral a, Enum b, Floating b, Eq b) => [b]
-> [b]
-> a
-> Array a b
mbf g w m = listArray (0,m) $ map (mbf_tap g w m) (indexes m)
rc :: (Ix a, Integral a, Enum b, Floating b, Eq b) => b
-> b
-> a
-> Array a b
rc ws b m = listArray (0,m) $ map (rc_tap ws b m) (indexes m)