-----------------------------------------------------------------------------
-- |
-- Module      :  DSP.Basic
-- Copyright   :  (c) Matthew Donadio 1998
-- License     :  GPL
--
-- Maintainer  :  m.p.donadio@ieee.org
-- Stability   :  experimental
-- Portability :  portable
--
-- Basic functions for manipulating signals
--
-----------------------------------------------------------------------------

module DSP.Basic where

import DSP.Source.Basic (zeros)

import Data.Array (Array, Ix, listArray, elems)

-- * Functions

-- | 'linspace' generates a list of values linearly spaced between specified
-- start and end values (array will include both start and end values).
--
-- @linspace 0.0 1.0 5 == [ 0.0, 0.25, 0.5, 0.75 1.0 ]@

linspace :: Double -> Double -> Int -> [Double]
linspace :: Double -> Double -> Int -> [Double]
linspace Double
a Double
b Int
n =
   forall a b. (a -> b) -> [a] -> [b]
map (\ Int
i -> Double
a forall a. Num a => a -> a -> a
+ (forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i) forall a. Num a => a -> a -> a
* Double
inc) [(Int
0::Int) .. (Int
n forall a. Num a => a -> a -> a
- Int
1)]
  where
   inc :: Double
inc = (Double
b forall a. Num a => a -> a -> a
- Double
a) forall a. Fractional a => a -> a -> a
/ (forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
n forall a. Num a => a -> a -> a
- Int
1))


-- | 'logspace' generates a list of values logarithmically spaced between the
-- values 10 ** start and 10 ** end (array will include both start and end values).
--
-- @logspace 0.0 1.0 4 == [ 1.0, 2.1544, 4.6416, 10.0 ]@

logspace :: Double -> Double -> Int -> [Double]
logspace :: Double -> Double -> Int -> [Double]
logspace Double
a Double
b Int
n =
   forall a b. (a -> b) -> [a] -> [b]
map (\ Double
x -> Double
10.0 forall a. Floating a => a -> a -> a
** Double
x) forall a b. (a -> b) -> a -> b
$ Double -> Double -> Int -> [Double]
linspace Double
a Double
b Int
n


-- | 'delay' is the unit delay function, eg,
--
-- @delay1 [ 1, 2, 3 ] == [ 0, 1, 2, 3 ]@

delay1 :: (Num a) => [a] -> [a]
delay1 :: forall a. Num a => [a] -> [a]
delay1 [a]
a = a
0 forall a. a -> [a] -> [a]
: [a]
a

-- | 'delay' is the n sample delay function, eg,
--
-- @delay 3 [ 1, 2, 3 ] == [ 0, 0, 0, 1, 2, 3 ]@

delay :: (Num a) => Int -> [a] -> [a]
delay :: forall a. Num a => Int -> [a] -> [a]
delay Int
n [a]
a = forall a. Int -> a -> [a]
replicate Int
n a
0 forall a. [a] -> [a] -> [a]
++ [a]
a

-- | @downsample@ throws away every n'th sample, eg,
--
-- @downsample 2 [ 1, 2, 3, 4, 5, 6 ] == [ 1, 3, 5 ]@

downsample :: Int -> [a] -> [a]
downsample :: forall a. Int -> [a] -> [a]
downsample Int
n =
   forall a b. (a -> b) -> [a] -> [b]
map forall a. [a] -> a
head forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> Bool
null) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> a) -> a -> [a]
iterate (forall a. Int -> [a] -> [a]
drop Int
n)

downsampleRec :: Int -> [a] -> [a]
downsampleRec :: forall a. Int -> [a] -> [a]
downsampleRec Int
_ []     = []
downsampleRec Int
n (a
x:[a]
xs) = a
x forall a. a -> [a] -> [a]
: forall a. Int -> [a] -> [a]
downsample Int
n (forall a. Int -> [a] -> [a]
drop (Int
n forall a. Num a => a -> a -> a
- Int
1) [a]
xs)

-- | @upsample@ inserts n-1 zeros between each sample, eg,
--
-- @upsample 2 [ 1, 2, 3 ] == [ 1, 0, 2, 0, 3, 0 ]@

upsample :: (Num a) => Int -> [a] -> [a]
upsample :: forall a. Num a => Int -> [a] -> [a]
upsample Int
n = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (forall a. a -> [a] -> [a]
: forall a. Int -> a -> [a]
replicate (Int
nforall a. Num a => a -> a -> a
-Int
1) a
0)

upsampleRec :: (Num a) => Int -> [a] -> [a]
upsampleRec :: forall a. Num a => Int -> [a] -> [a]
upsampleRec Int
_ []     = []
upsampleRec Int
n (a
x:[a]
xs) = a
x forall a. a -> [a] -> [a]
: forall {t} {a}. (Eq t, Num t, Num a) => t -> [a] -> [a]
zero Int
n [a]
xs
    where zero :: t -> [a] -> [a]
zero t
1 [a]
ys = forall a. Num a => Int -> [a] -> [a]
upsample Int
n [a]
ys
	  zero t
i [a]
ys = a
0 forall a. a -> [a] -> [a]
: t -> [a] -> [a]
zero (t
iforall a. Num a => a -> a -> a
-t
1) [a]
ys

-- | @upsampleAndHold@ replicates each sample n times, eg,
--
-- @upsampleAndHold 3 [ 1, 2, 3 ] == [ 1, 1, 1, 2, 2, 2, 3, 3, 3 ]@

upsampleAndHold :: Int -> [a] -> [a]
upsampleAndHold :: forall a. Int -> [a] -> [a]
upsampleAndHold Int
n = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (forall a. Int -> a -> [a]
replicate Int
n)


-- | merges elements from two lists into one list in an alternating way
--
-- @interleave [0,1,2,3] [10,11,12,13] == [0,10,1,11,2,12,3,13]@

interleave :: [a] -> [a] -> [a]
interleave :: forall a. [a] -> [a] -> [a]
interleave (a
e:[a]
es) (a
o:[a]
os) = a
e forall a. a -> [a] -> [a]
: a
o forall a. a -> [a] -> [a]
: forall a. [a] -> [a] -> [a]
interleave [a]
es [a]
os
interleave [a]
_      [a]
_      = []

-- | split a list into two lists in an alternating way
--
-- @uninterleave [1,2,3,4,5,6] == ([1,3,5],[2,4,6])@
--
-- It's a special case of 'Numeric.Random.Spectrum.Pink.split'.

uninterleave :: [a] -> ([a],[a])
uninterleave :: forall a. [a] -> ([a], [a])
uninterleave = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\a
x ~([a]
xs,[a]
ys) -> (a
xforall a. a -> [a] -> [a]
:[a]
ys,[a]
xs)) ([],[])


-- | pad a sequence with zeros to length n
--
-- @pad [ 1, 2, 3 ] 6 == [ 1, 2, 3, 0, 0, 0 ]@

pad :: (Ix a, Integral a, Num b) => Array a b -> a -> Array a b
pad :: forall a b.
(Ix a, Integral a, Num b) =>
Array a b -> a -> Array a b
pad Array a b
x a
n = forall i e. Ix i => (i, i) -> [e] -> Array i e
listArray (a
0,a
nforall a. Num a => a -> a -> a
-a
1) forall a b. (a -> b) -> a -> b
$ forall i e. Array i e -> [e]
elems Array a b
x forall a. [a] -> [a] -> [a]
++ forall a. Num a => [a]
zeros


-- | generates a 'Just' if the given condition holds

toMaybe :: Bool -> a -> Maybe a
toMaybe :: forall a. Bool -> a -> Maybe a
toMaybe Bool
False a
_ = forall a. Maybe a
Nothing
toMaybe Bool
True  a
x = forall a. a -> Maybe a
Just a
x

-- | Computes the square of the Euclidean norm of a 2D point

norm2sqr :: Num a => (a,a) -> a
norm2sqr :: forall a. Num a => (a, a) -> a
norm2sqr (a
x,a
y) = a
xforall a. Num a => a -> Int -> a
^!Int
2 forall a. Num a => a -> a -> a
+ a
yforall a. Num a => a -> Int -> a
^!Int
2

-- | Power with fixed exponent type.
-- This eliminates warnings about using default types.

infixr 8 ^!

(^!) :: Num a => a -> Int -> a
^! :: forall a. Num a => a -> Int -> a
(^!) a
x Int
n = a
xforall a b. (Num a, Integral b) => a -> b -> a
^Int
n