packages feed

dsp-0.1: DSP/Filter/FIR/Taps.hs

-----------------------------------------------------------------------------
-- |
-- 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 = 	 "Pretice-Hall",
  year = 	 1989,
  address =	 "Englewood Cliffs",
  series =       {Pretice-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 m = [ 0 .. fromIntegral 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 wc m n | n-a == 0  = wc / pi
               | otherwise = sin (wc * (n-a)) / (pi * (n-a))
    where a = (fromIntegral m) / 2

-- Highpass tap function
 
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

-- Multiband tap function

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

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

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

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
          a = (fromIntegral m) / 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) => b -- ^ wc
       -> a -- ^ M
       -> Array a b -- ^ h[n]

lpf wc m = listArray (0,m) $ map (lpf_tap wc m) (indexes m)

-- | Highpass filter

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

hpf wc m = listArray (0,m) $ map (hpf_tap wc m) (indexes m)

-- | Bandpass filter

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

bpf wl wu m = listArray (0,m) $ zipWith (+) (elems $ lpf wu m) (elems $ hpf wl m)

-- | Bandstop filter

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

bsf wl wu m = listArray (0,m) $ zipWith (+) (elems $ lpf wl m) (elems $ hpf wu m)

-- | Multiband filter

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

mbf g w m = listArray (0,m) $ map (mbf_tap g w m) (indexes m)

-- | Raised-cosine filter

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

rc ws b m = listArray (0,m) $ map (rc_tap ws b m) (indexes m)