packages feed

dsp-0.1: Numeric/Transform/Fourier/Goertzel.hs

-----------------------------------------------------------------------------
-- |
-- Module      :  Numeric.Transform.Fourier.Goertzel
-- Copyright   :  (c) Matthew Donadio 2003
-- License     :  GPL
--
-- Maintainer  :  m.p.donadio@ieee.org
-- Stability   :  experimental
-- Portability :  portable
--
-- This is an implementation of Goertzel's algorithm, which computes on
-- bin of a DFT.  A description can be found in Oppenheim and Schafer's
-- /Discrete Time Signal Processing/, pp 585-587.
--
-----------------------------------------------------------------------------

-- TODO: do the cipherin' to figure out the best simplification for the
-- cgoertzel_power case

-- TODO: Bonzanigo's phase correction

module Numeric.Transform.Fourier.Goertzel where

import Data.Array
import Data.Complex

-- | Goertzel's algorithm for complex inputs

cgoertzel :: (RealFloat a, Ix b, Integral b) => Array b (Complex a) -- ^ x[n]
	  -> b -- ^ k
	  -> Complex a -- ^ X[k]

cgoertzel x k = g (elems x) 0 0
    where w = 2 * pi * fromIntegral k / fromIntegral n
          a = 2 * cos w
	  g []     x1 x2 = x1 * cis w - x2
	  g (x:xs) x1@(x1r:+x1i) x2 = g xs (x + (a*x1r:+a*x1i) - x2) x1
	  n = (snd $ bounds x) - 1

-- | Power via Goertzel's algorithm for complex inputs

cgoertzel_power :: (RealFloat a, Ix b, Integral b) => Array b (Complex a) -- ^ x[n]
		-> b -- ^ k
		-> a -- ^ |X[k]|^2

cgoertzel_power x k = (magnitude $ cgoertzel x k)^2

-- | Goertzel's algorithm for real inputs

rgoertzel :: (RealFloat a, Ix b, Integral b) => Array b a -- ^ x[n]
	  -> b -- ^ k
	  -> Complex a -- ^ X[k]

rgoertzel x k = g (elems x) 0 0
    where w = 2 * pi * fromIntegral k / fromIntegral n
          a = 2 * cos w
	  g []     x1 x2 = ((x1 - cos w * x2) :+ x2 * sin w)
	  g (x:xs) x1 x2 = g xs (x + a * x1 - x2) x1
	  n = (snd $ bounds x) - 1

-- | Power via Goertzel's algorithm for real inputs

rgoertzel_power :: (RealFloat a, Ix b, Integral b) => Array b a -- ^ x[n]
		-> b -- ^ k
		-> a -- ^ |X[k]|^2

rgoertzel_power x k = g (elems x) 0 0
    where w = 2 * pi * fromIntegral k / fromIntegral n
          a = 2 * cos w
	  g []     x1 x2 = x1^2 + x2^2 - a * x1 * x2
	  g (x:xs) x1 x2 = g xs (x + a * x1 - x2) x1
	  n = (snd $ bounds x) - 1