{-# LANGUAGE FlexibleContexts #-}
module SDR.Demod (
fmDemodStr,
fmDemodVec,
fmDemod
) where
import Data.Complex
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Fusion.Stream.Monadic as VFSM
import qualified Data.Vector.Fusion.Bundle.Monadic as VFBM
import qualified Data.Vector.Fusion.Bundle.Size as VFBS
import SDR.VectorUtils
import Pipes
{-# INLINE fmDemodStr #-}
fmDemodStr :: (RealFloat a, Monad m)
=> Complex a
-> VFSM.Stream m (Complex a)
-> VFSM.Stream m a
fmDemodStr = mapAccumMV func
where
{-# INLINE func #-}
func last sample = return (sample, phase (sample * conjugate last))
{-# INLINE fmDemodVec #-}
fmDemodVec :: (RealFloat a, VG.Vector v (Complex a), VG.Vector v a)
=> Complex a
-> v (Complex a)
-> v a
fmDemodVec init inp = VG.unstream $ flip VFBM.fromStream (VFBS.Exact $ VG.length inp) $ fmDemodStr init $ VFBM.elements $ VG.stream inp
{-# INLINE fmDemod #-}
fmDemod :: (RealFloat a, VG.Vector v (Complex a), VG.Vector v a) => Pipe (v (Complex a)) (v a) IO ()
fmDemod = func 0
where
func lastSample = do
dat <- await
yield $ fmDemodVec lastSample dat
func $ VG.unsafeIndex dat (VG.length dat - 1)