-----------------------------------------------------------------------------
-- |
-- Module      :  DSP.Filter.FIR.Taps
-- Copyright   :  (c) Matthew Donadio 1998
-- License     :  GPL
--
-- Maintainer  :  m.p.donadio@ieee.org
-- Stability   :  experimental
-- Portability :  portable
--
-- Functions for creating rectangular windowed FIR filters
--
-----------------------------------------------------------------------------

{-
Reference:

@Book{dsp,
  author = 	 "Alan V. Oppenheim and Ronald W. Schafer",
  title = 	 "Discrete-Time Signal Processing",
  publisher = 	 "Prentice-Hall",
  year = 	 1989,
  address =	 "Englewood Cliffs",
  series =       {Prentice-Hall Signal Processing Series}
}
-}

module DSP.Filter.FIR.Taps (lpf, hpf, bpf, bsf, mbf, rc) where

import Data.Array

-- indexes generates the list of indexes that we will map the prototype
-- functions onto

indexes :: (Integral a, Num b, Enum b) => a -> [b]
indexes :: forall a b. (Integral a, Num b, Enum b) => a -> [b]
indexes a
m = [ b
0 .. forall a b. (Integral a, Num b) => a -> b
fromIntegral a
m ]

-- the _tap functions generate one tap for the given function

-- wc = cutoff frequency in normalized radians
-- m = the order of the filter (length - 1)
-- n = the tap number

-- Lowpass tap function

lpf_tap :: (Integral a, Floating b, Eq b) => b -> a -> b -> b
lpf_tap :: forall a b. (Integral a, Floating b, Eq b) => b -> a -> b -> b
lpf_tap b
wc a
m b
n | b
nforall a. Num a => a -> a -> a
-b
a forall a. Eq a => a -> a -> Bool
== b
0  = b
wc forall a. Fractional a => a -> a -> a
/ forall a. Floating a => a
pi
               | Bool
otherwise = forall a. Floating a => a -> a
sin (b
wc forall a. Num a => a -> a -> a
* (b
nforall a. Num a => a -> a -> a
-b
a)) forall a. Fractional a => a -> a -> a
/ (forall a. Floating a => a
pi forall a. Num a => a -> a -> a
* (b
nforall a. Num a => a -> a -> a
-b
a))
    where a :: b
a = (forall a b. (Integral a, Num b) => a -> b
fromIntegral a
m) forall a. Fractional a => a -> a -> a
/ b
2

-- Highpass tap function

hpf_tap :: (Integral a, Floating b, Eq b) => b -> a -> b -> b
hpf_tap :: forall a b. (Integral a, Floating b, Eq b) => b -> a -> b -> b
hpf_tap b
wc a
m b
n | b
nforall a. Num a => a -> a -> a
-b
a forall a. Eq a => a -> a -> Bool
== b
0  = b
1 forall a. Num a => a -> a -> a
- b
wc forall a. Fractional a => a -> a -> a
/ forall a. Floating a => a
pi
               | Bool
otherwise = forall a. Floating a => a -> a
sin (forall a. Floating a => a
pi forall a. Num a => a -> a -> a
* (b
nforall a. Num a => a -> a -> a
-b
a)) forall a. Fractional a => a -> a -> a
/ (forall a. Floating a => a
pi forall a. Num a => a -> a -> a
* (b
nforall a. Num a => a -> a -> a
-b
a)) forall a. Num a => a -> a -> a
- forall a b. (Integral a, Floating b, Eq b) => b -> a -> b -> b
lpf_tap b
wc a
m b
n
    where a :: b
a = (forall a b. (Integral a, Num b) => a -> b
fromIntegral a
m) forall a. Fractional a => a -> a -> a
/ b
2

-- Multiband tap function

mbf_tap :: (Integral a, Floating b, Eq b) => [b] -> [b] -> a -> b -> b
mbf_tap :: forall a b.
(Integral a, Floating b, Eq b) =>
[b] -> [b] -> a -> b -> b
mbf_tap (b
g:[])     (b
w:[]) a
m b
n = b
g forall a. Num a => a -> a -> a
* forall a b. (Integral a, Floating b, Eq b) => b -> a -> b -> b
lpf_tap b
w a
m b
n
mbf_tap (b
g1:b
g2:[b]
gs) (b
w:[b]
ws) a
m b
n = (b
g1forall a. Num a => a -> a -> a
-b
g2) forall a. Num a => a -> a -> a
* forall a b. (Integral a, Floating b, Eq b) => b -> a -> b -> b
lpf_tap b
w a
m b
n forall a. Num a => a -> a -> a
+ forall a b.
(Integral a, Floating b, Eq b) =>
[b] -> [b] -> a -> b -> b
mbf_tap (b
g2forall a. a -> [a] -> [a]
:[b]
gs) [b]
ws a
m b
n
mbf_tap [b]
_          [b]
_      a
_ b
_ = forall a. HasCallStack => [Char] -> a
error [Char]
"mbf_tap: bands out of sync"

-- Raised-cosine tap function.  This does _not_ have 0 dB DC gain.

-- ws = symbol rate in normalized radians
-- b = filter beta

rc_tap :: (Integral a, Floating b, Eq b) => b -> b -> a -> b -> b
rc_tap :: forall a b. (Integral a, Floating b, Eq b) => b -> b -> a -> b -> b
rc_tap b
ws b
b a
m b
n | b
nforall a. Num a => a -> a -> a
-b
a forall a. Eq a => a -> a -> Bool
== b
0  = b
1
                | b
den forall a. Eq a => a -> a -> Bool
== b
0  = b
0
                | Bool
otherwise = forall a. Floating a => a -> a
sin b
sarg forall a. Fractional a => a -> a -> a
/ b
sarg forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
cos b
carg forall a. Fractional a => a -> a -> a
/ b
den
    where sarg :: b
sarg = b
ws forall a. Num a => a -> a -> a
* (b
nforall a. Num a => a -> a -> a
-b
a) forall a. Fractional a => a -> a -> a
/ b
2
          carg :: b
carg = b
b forall a. Num a => a -> a -> a
* b
ws forall a. Num a => a -> a -> a
* (b
nforall a. Num a => a -> a -> a
-b
a) forall a. Fractional a => a -> a -> a
/ b
2
          den :: b
den = b
1 forall a. Num a => a -> a -> a
- b
4 forall a. Num a => a -> a -> a
* ((b
bforall a. Num a => a -> a -> a
*b
wsforall a. Num a => a -> a -> a
*(b
nforall a. Num a => a -> a -> a
-b
a)) forall a. Fractional a => a -> a -> a
/ (b
2forall a. Num a => a -> a -> a
*forall a. Floating a => a
pi)) forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
2::Int)
          a :: b
a = (forall a b. (Integral a, Num b) => a -> b
fromIntegral a
m) forall a. Fractional a => a -> a -> a
/ b
2

-- The following functions generate a list of the taps for a given set of
-- parameter.

-- | Lowpass filter

lpf :: (Ix a, Integral a, Enum b, Floating b, Eq b) => b -- ^ wc
       -> a -- ^ M
       -> Array a b -- ^ h[n]

lpf :: forall a b.
(Ix a, Integral a, Enum b, Floating b, Eq b) =>
b -> a -> Array a b
lpf b
wc a
m = forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (a
0,a
m) forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall a b. (Integral a, Floating b, Eq b) => b -> a -> b -> b
lpf_tap b
wc a
m) (forall a b. (Integral a, Num b, Enum b) => a -> [b]
indexes a
m)

-- | Highpass filter

hpf :: (Ix a, Integral a, Enum b, Floating b, Eq b) => b -- ^ wc
       -> a -- ^ M
       -> Array a b -- ^ h[n]

hpf :: forall a b.
(Ix a, Integral a, Enum b, Floating b, Eq b) =>
b -> a -> Array a b
hpf b
wc a
m = forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (a
0,a
m) forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall a b. (Integral a, Floating b, Eq b) => b -> a -> b -> b
hpf_tap b
wc a
m) (forall a b. (Integral a, Num b, Enum b) => a -> [b]
indexes a
m)

-- | Bandpass filter

bpf :: (Ix a, Integral a, Enum b, Floating b, Eq b) => b -- ^ wl
       -> b -- ^ wu
       -> a -- ^ M
       -> Array a b -- ^ h[n]

bpf :: forall a b.
(Ix a, Integral a, Enum b, Floating b, Eq b) =>
b -> b -> a -> Array a b
bpf b
wl b
wu a
m = forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (a
0,a
m) forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. Num a => a -> a -> a
(+) (forall i e. Array i e -> [e]
elems forall a b. (a -> b) -> a -> b
$ forall a b.
(Ix a, Integral a, Enum b, Floating b, Eq b) =>
b -> a -> Array a b
lpf b
wu a
m) (forall i e. Array i e -> [e]
elems forall a b. (a -> b) -> a -> b
$ forall a b.
(Ix a, Integral a, Enum b, Floating b, Eq b) =>
b -> a -> Array a b
hpf b
wl a
m)

-- | Bandstop filter

bsf :: (Ix a, Integral a, Enum b, Floating b, Eq b) => b -- ^ wl
       -> b -- ^ wu
       -> a -- ^ M
       -> Array a b -- ^ h[n]

bsf :: forall a b.
(Ix a, Integral a, Enum b, Floating b, Eq b) =>
b -> b -> a -> Array a b
bsf b
wl b
wu a
m = forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (a
0,a
m) forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith forall a. Num a => a -> a -> a
(+) (forall i e. Array i e -> [e]
elems forall a b. (a -> b) -> a -> b
$ forall a b.
(Ix a, Integral a, Enum b, Floating b, Eq b) =>
b -> a -> Array a b
lpf b
wl a
m) (forall i e. Array i e -> [e]
elems forall a b. (a -> b) -> a -> b
$ forall a b.
(Ix a, Integral a, Enum b, Floating b, Eq b) =>
b -> a -> Array a b
hpf b
wu a
m)

-- | Multiband filter

mbf :: (Ix a, Integral a, Enum b, Floating b, Eq b) => [b] -- ^ [mags]
       -> [b] -- ^ [w]
       -> a -- ^ M
       -> Array a b -- ^ h[n]

mbf :: forall a b.
(Ix a, Integral a, Enum b, Floating b, Eq b) =>
[b] -> [b] -> a -> Array a b
mbf [b]
g [b]
w a
m = forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (a
0,a
m) forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall a b.
(Integral a, Floating b, Eq b) =>
[b] -> [b] -> a -> b -> b
mbf_tap [b]
g [b]
w a
m) (forall a b. (Integral a, Num b, Enum b) => a -> [b]
indexes a
m)

-- | Raised-cosine filter

rc :: (Ix a, Integral a, Enum b, Floating b, Eq b) => b -- ^ ws
       -> b -- ^ beta
       -> a -- ^ M
       -> Array a b -- ^ h[n]

rc :: forall a b.
(Ix a, Integral a, Enum b, Floating b, Eq b) =>
b -> b -> a -> Array a b
rc b
ws b
b a
m = forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (a
0,a
m) forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall a b. (Integral a, Floating b, Eq b) => b -> b -> a -> b -> b
rc_tap b
ws b
b a
m) (forall a b. (Integral a, Num b, Enum b) => a -> [b]
indexes a
m)