{- |
Copyright   :  (c) Henning Thielemann 2008
License     :  GPL

Maintainer  :  synthesizer@henning-thielemann.de
Stability   :  provisional
Portability :  requires multi-parameter type classes

Signals equipped with a phantom type parameter that reflects the sample rate.
-}
module Synthesizer.Dimensional.Cyclic.Signal where

import qualified Synthesizer.Format as Format
import qualified Synthesizer.Dimensional.RatePhantom as RP

import qualified Synthesizer.Dimensional.Straight.Signal as SigS
import qualified Synthesizer.State.Signal as Sig

-- import qualified Number.DimensionTerm        as DN
-- import qualified Algebra.DimensionTerm       as Dim

{-
import qualified Algebra.Module         as Module
import qualified Algebra.Field          as Field
import qualified Algebra.Ring           as Ring
-}
import qualified Algebra.Additive       as Additive

-- import Number.DimensionTerm ((&/&))


import NumericPrelude
import PreludeBase
import Prelude ()


newtype T seq yv =
   Cons {
       samples :: seq yv   {-^ the sampled values -}
     }
--   deriving (Eq, Show)

instance Functor seq => Functor (T seq) where
   fmap f = Cons . fmap f . samples

instance Format.C seq => Format.C (T seq) where
   format p = Format.format p . samples

instance (Format.C seq, Show y) => Show (T seq y) where
   showsPrec = Format.format


type R s yv = RP.T s (T Sig.T) yv


{-
replaceSamples :: Sig.T yv1 -> R s yv0 -> R s yv1
replaceSamples ss _  =  fromSamples ss


processSamples ::
   (Sig.T yv0 -> Sig.T yv1) -> R s yv0 -> R s yv1
processSamples f x =
   replaceSamples (f $ samples $ RP.toSignal x) x
-}


{-# INLINE fromPeriod #-}
fromPeriod :: Sig.T yv -> R s yv
fromPeriod  =  RP.fromSignal . Cons

{-# INLINE fromPeriodList #-}
fromPeriodList :: [yv] -> R s yv
fromPeriodList  =  fromPeriod . Sig.fromList

{-# INLINE toPeriod #-}
toPeriod :: R s yv -> Sig.T yv
toPeriod  =  samples . RP.toSignal


{- |
Periodization of a straight signal.
-}
{-# INLINE fromSignal #-}
fromSignal :: Additive.C yv => Int -> SigS.R s yv -> R s yv
fromSignal n  =
   fromPeriod . sum . Sig.sliceVert n . SigS.toSamples

{- |
Convert a cyclic signal to a straight signal containing a loop.
-}
{-# INLINE toSignal #-}
toSignal :: Additive.C yv => R s yv -> SigS.R s yv
toSignal  =
   SigS.fromSamples . Sig.cycle . toPeriod