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

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

For a description see "Synthesizer.SampleRateContext.Rate".
-}
module Synthesizer.SampleRateContext.Signal (
   T(..),
   toTimeScalar,
   toFrequencyScalar,
   toAmplitudeScalar,
   toGradientScalar,
   scalarSamples,
   vectorSamples,
   replaceAmplitude,
   replaceSamples,
   ($-),
   ) where

import Synthesizer.SampleRateContext.Rate (($:))
import qualified Synthesizer.SampleRateContext.Rate as Rate

import Synthesizer.Amplitude.Signal
import qualified Synthesizer.Amplitude.Control as CtrlV

import qualified Algebra.OccasionallyScalar as OccScalar
-- import qualified Algebra.Module         as Module
import qualified Algebra.Field          as Field
import qualified Algebra.Real           as Real
import qualified Algebra.Ring           as Ring

import Algebra.OccasionallyScalar (toScalar)

import NumericPrelude
-- import PreludeBase as P
import Prelude ()


{-
returnCons ::
   y' -> [yv] -> Rate t t' (T y y' yv)
returnCons amp sig = Proc.pure (Cons amp sig)
-}


toTimeScalar :: (Ring.C t', OccScalar.C t t') =>
   Rate.T t t' -> t' -> t
toTimeScalar sampleRate t =
   toScalar (t * Rate.toNumber sampleRate)

toFrequencyScalar :: (Field.C t', OccScalar.C t t') =>
   Rate.T t t' -> t' -> t
toFrequencyScalar sampleRate f =
   toScalar (f / Rate.toNumber sampleRate)

toGradientScalar :: (Field.C q', OccScalar.C q q') =>
   q' -> Rate.T q q' -> q' -> q
toGradientScalar amp sampleRate steepness =
   toFrequencyScalar sampleRate (steepness / amp)


{- |
Take a scalar argument where a process expects a signal.
Only possible for non-negative values so far.
-}
($-) :: (Field.C y', Real.C y', OccScalar.C y y') =>
    (Rate.T t t' -> T y y' y -> a) -> y' -> (Rate.T t t' -> a)
($-) f x = f $: Rate.pure (CtrlV.constant x)