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

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

Class that allows unified handling of
@SigS.T@ and @SigA.R s u@
whenever the applied function is homogeneous (with degree one),
that is scaling of the input must only result in scaling of the output.
Unfortunately, Haskell's type system cannot check this property,
so use this abstraction only for signal processes that are actually homogeneous.
module Synthesizer.Dimensional.Abstraction.Homogeneous where

import qualified Synthesizer.State.Signal as Sig
import qualified Synthesizer.Dimensional.RatePhantom as RP
import qualified Synthesizer.Dimensional.Straight.Signal as SigS
import qualified Synthesizer.Dimensional.Amplitude.Signal as SigA
import qualified Synthesizer.Dimensional.Amplitude as Amp

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 Number.DimensionTerm ((&/&))

-- import NumericPrelude
-- import PreludeBase
-- import Prelude ()

{-# INLINE processSamples #-}
processSamples :: C sig =>
   (Sig.T y0 -> Sig.T y1) -> RP.T s sig y0 -> RP.T s sig y1
processSamples f =
   RP.fromSignal . unwrappedProcessSamples f . RP.toSignal

{-# INLINE processSampleList #-}
processSampleList :: C sig =>
   ([y0] -> [y1]) ->
   RP.T s sig y0 ->
   RP.T s sig y1
processSampleList f =
   processSamples (Sig.fromList . f . Sig.toList)

class C sig where
   unwrappedProcessSamples :: (Sig.T y0 -> Sig.T y1) -> sig y0 -> sig y1

instance C Sig.T where
   unwrappedProcessSamples f = f

instance C sig => C (SigS.T sig) where
--   processSamples = SigS.processSamples
   unwrappedProcessSamples f =
      SigS.processSamplesPrivate (unwrappedProcessSamples f)

instance (C sig, Amp.C amp) => C (SigA.T amp sig) where
   unwrappedProcessSamples f =
      (\(SigA.Cons amp sig) ->
         SigA.Cons amp (unwrappedProcessSamples f sig))