{-# LANGUAGE NoImplicitPrelude #-}
{- |
Copyright   :  (c) Henning Thielemann 2008
License     :  GPL

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

-}
module Synthesizer.SampleRateContext.Oscillator (
   {- * Oscillators with constant waveforms -}
   static,
   freqMod,
   phaseMod,
   phaseFreqMod,
) where

import qualified Synthesizer.Plain.Oscillator as Osci
import qualified Synthesizer.Basic.Wave       as Wave
-- import qualified Synthesizer.Basic.Phase      as Phase

import qualified Synthesizer.SampleRateContext.Signal as SigC
import qualified Synthesizer.SampleRateContext.Rate   as Rate
import Synthesizer.SampleRateContext.Signal (toFrequencyScalar)

import qualified Algebra.OccasionallyScalar as OccScalar
import qualified Algebra.RealField          as RealField
import qualified Algebra.Field              as Field

-- import NumericPrelude
import PreludeBase as P


{- * Oscillators with constant waveforms -}

{- | oscillator with a functional waveform with constant frequency -}
static :: (RealField.C t, Field.C t', OccScalar.C t t') =>
      Wave.T t yv  {- ^ waveform -}
   -> y'           {- ^ amplitude -}
   -> t            {- ^ start phase from the range [0,1] -}
   -> t'           {- ^ frequency -}
   -> Rate.T t t'
   -> SigC.T y y' yv
static wave amplitude phase freq' sr =
   let freq = toFrequencyScalar sr freq'
   in  SigC.Cons amplitude (Osci.static wave phase freq)

{- | oscillator with a functional waveform with modulated frequency -}
freqMod :: (RealField.C t, Field.C t', OccScalar.C t t') =>
      Wave.T t yv  {- ^ waveform -}
   -> y'           {- ^ amplitude -}
   -> t            {- ^ start phase from the range [0,1] -}
   -> Rate.T t t'
   -> SigC.T t t' t  {- ^ frequency control -}
   -> SigC.T y y' yv
freqMod wave amplitude phase sr xs =
   let freqs = SigC.scalarSamples (toFrequencyScalar sr) xs
   in  SigC.Cons amplitude
          (Osci.freqMod wave phase freqs)

{- | oscillator with modulated phase -}
phaseMod :: (RealField.C t, Field.C t', OccScalar.C t t') =>
      Wave.T t yv  {- ^ waveform -}
   -> y'           {- ^ amplitude -}
   -> t'           {- ^ frequency control -}
   -> Rate.T t t'
   -> SigC.T t t  t  {- ^ phase modulation, phases must have no unit and
                          are from range [0,1] -}
   -> SigC.T y y' yv
phaseMod wave amplitude freq' sr xs =
   let freq = toFrequencyScalar sr freq'
       phases = SigC.scalarSamples id xs
   in  SigC.Cons amplitude
          (Osci.phaseMod wave freq phases)

{- | oscillator with a functional waveform with modulated phase and frequency -}
phaseFreqMod :: (RealField.C t, Field.C t', OccScalar.C t t') =>
      Wave.T t yv  {- ^ waveform -}
   -> y'           {- ^ amplitude -}
   -> Rate.T t t'
   -> SigC.T t t  t  {- ^ phase control -}
   -> SigC.T t t' t  {- ^ frequency control -}
   -> SigC.T y y' yv
phaseFreqMod wave amplitude sr xs ys =
   let phases = SigC.scalarSamples id xs
       freqs  = SigC.scalarSamples (toFrequencyScalar sr) ys
   in  SigC.Cons amplitude
          (Osci.phaseFreqMod wave phases freqs)