{-# LANGUAGE BangPatterns #-} {-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} module Data.ZoomCache.PCM.Internal ( -- * Functions readSummaryPCM , fromSummaryPCM , initSummaryPCMBounded , mkSummaryPCM , appendSummaryPCM , updateSummaryPCM , deltaDecodePCM , deltaEncodePCM ) where import Blaze.ByteString.Builder import Control.Applicative ((<$>)) import Control.Monad (replicateM) import Data.ByteString (ByteString) import Data.Iteratee (Iteratee) import Data.Monoid import Data.ZoomCache.Codec import Data.ZoomCache.PCM.Types ---------------------------------------------------------------------- readSummaryPCM :: (Functor m, Monad m, ZoomPCM a) => Iteratee ByteString m (SummaryData (PCM a)) readSummaryPCM = do [mn,mx] <- replicateM 2 (unPCM <$> readRaw) [avg,rms] <- replicateM 2 readDouble64be return (pcmMkSummary mn mx avg rms) {-# INLINABLE readSummaryPCM #-} fromSummaryPCM :: ZoomPCM a => SummaryData (PCM a) -> Builder fromSummaryPCM s = mconcat $ map pcmFromRaw [pcmMin s, pcmMax s] ++ map fromDouble [pcmAvg s, pcmRMS s] {-# INLINABLE fromSummaryPCM #-} initSummaryPCMBounded :: (Bounded a, ZoomPCM a) => TimeStamp -> SummaryWork (PCM a) initSummaryPCMBounded entry = pcmMkSummaryWork entry 0 maxBound minBound 0.0 0.0 {-# INLINEABLE initSummaryPCMBounded #-} mkSummaryPCM :: ZoomPCM a => TimeStampDiff -> SummaryWork (PCM a) -> SummaryData (PCM a) mkSummaryPCM (TSDiff dur) sw = pcmMkSummary (pcmWorkMin sw) (pcmWorkMax sw) (pcmWorkSum sw / fromIntegral dur) (sqrt $ (pcmWorkSumSq sw) / fromIntegral dur) {-# INLINEABLE mkSummaryPCM #-} appendSummaryPCM :: ZoomPCM a => TimeStampDiff -> SummaryData (PCM a) -> TimeStampDiff -> SummaryData (PCM a) -> SummaryData (PCM a) appendSummaryPCM (TSDiff dur1) s1 (TSDiff dur2) s2 = pcmMkSummary (min (pcmMin s1) (pcmMin s2)) (max (pcmMax s1) (pcmMax s2)) (((pcmAvg s1 * fromIntegral dur1) + (pcmAvg s2 * fromIntegral dur2)) / fromIntegral durSum) (sqrt $ ((pcmRMS s1 * pcmRMS s1 * fromIntegral dur1) + (pcmRMS s2 * pcmRMS s2 * fromIntegral dur2)) / fromIntegral durSum) where !durSum = dur1 + dur2 {-# INLINEABLE appendSummaryPCM #-} updateSummaryPCM :: ZoomPCM a => TimeStamp -> PCM a -> SummaryWork (PCM a) -> SummaryWork (PCM a) updateSummaryPCM t (PCM d) sw = pcmMkSummaryWork t d (min (pcmWorkMin sw) d) (max (pcmWorkMax sw) d) ((pcmWorkSum sw) + realToFrac (d * dur)) ((pcmWorkSumSq sw) + realToFrac (d*d * dur)) where !dur = fromIntegral $ (unTS t) - (unTS (pcmWorkTime sw)) {-# INLINEABLE updateSummaryPCM #-} deltaDecodePCM :: ZoomPCM a => [PCM a] -> [PCM a] deltaDecodePCM = map PCM . deltaDecode . map unPCM {-# INLINE deltaDecodePCM #-} deltaEncodePCM :: ZoomPCM a => SummaryWork (PCM a) -> PCM a -> PCM a deltaEncodePCM sw (PCM d) = PCM (d - pcmWorkLast sw) {-# INLINE deltaEncodePCM #-}