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

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

Tone generators
-}
module Synthesizer.State.Oscillator where

import qualified Synthesizer.Causal.Oscillator  as Osci
import qualified Synthesizer.Causal.Oscillator.Core as OsciCore
import qualified Synthesizer.Causal.Process as Causal

import qualified Synthesizer.Basic.WaveSmoothed as WaveSmooth
import qualified Synthesizer.Basic.Wave         as Wave
import qualified Synthesizer.Basic.Phase        as Phase

import qualified Synthesizer.State.Signal as Sig
import qualified Synthesizer.Generic.Signal as SigG
import qualified Synthesizer.Interpolation as Interpolation

import qualified Algebra.Transcendental        as Trans
import qualified Algebra.RealField             as RealField
import qualified Algebra.RealRing              as RealRing

import NumericPrelude.Numeric (Float, Double, )



{- * Oscillators with arbitrary but constant waveforms -}

{-# INLINE static #-}
{- |
Oscillator with constant frequency.
It causes aliasing effects for sharp waveforms and high frequencies.
-}
static :: (RealRing.C a) => Wave.T a b -> (Phase.T a -> a -> Sig.T b)
static :: forall a b. C a => T a b -> T a -> a -> T b
static T a b
wave T a
phase a
freq =
    (T a -> b) -> T (T a) -> T b
forall a b. (a -> b) -> T a -> T b
Sig.map (T a b -> T a -> b
forall t y. T t y -> T t -> y
Wave.apply T a b
wave) (T a -> a -> T (T a)
forall a. C a => T a -> a -> T (T a)
OsciCore.static T a
phase a
freq)

{-# INLINE staticAntiAlias #-}
{- |
Oscillator with constant frequency
that suppresses aliasing effects using waveforms with controllable smoothness.
-}
staticAntiAlias :: (RealRing.C a) =>
    WaveSmooth.T a b -> (Phase.T a -> a -> Sig.T b)
staticAntiAlias :: forall a b. C a => T a b -> T a -> a -> T b
staticAntiAlias T a b
wave T a
phase a
freq =
    (T a -> b) -> T (T a) -> T b
forall a b. (a -> b) -> T a -> T b
Sig.map (T a b -> a -> T a -> b
forall t y. T t y -> t -> T t -> y
WaveSmooth.apply T a b
wave a
freq) (T a -> a -> T (T a)
forall a. C a => T a -> a -> T (T a)
OsciCore.static T a
phase a
freq)

{-# INLINE phaseMod #-}
{- | oscillator with modulated phase -}
phaseMod :: (RealRing.C a) => Wave.T a b -> a -> Sig.T a -> Sig.T b
phaseMod :: forall a b. C a => T a b -> a -> T a -> T b
phaseMod T a b
wave a
freq =
    T a b -> T a -> T b
forall (sig :: * -> *) a b.
(Transform sig a, Transform sig b) =>
T a b -> sig a -> sig b
Causal.apply (T a b -> a -> T a b
forall a b. C a => T a b -> a -> T a b
Osci.phaseMod T a b
wave a
freq)

{-# INLINE shapeMod #-}
{- | oscillator with modulated shape -}
shapeMod :: (RealRing.C a) =>
    (c -> Wave.T a b) -> Phase.T a -> a -> Sig.T c -> Sig.T b
shapeMod :: forall a c b. C a => (c -> T a b) -> T a -> a -> T c -> T b
shapeMod c -> T a b
wave T a
phase a
freq =
    T c b -> T c -> T b
forall (sig :: * -> *) a b.
(Transform sig a, Transform sig b) =>
T a b -> sig a -> sig b
Causal.apply ((c -> T a b) -> T a -> a -> T c b
forall a c b. C a => (c -> T a b) -> T a -> a -> T c b
Osci.shapeMod c -> T a b
wave T a
phase a
freq)

{-# INLINE freqMod #-}
{- | oscillator with modulated frequency -}
freqMod :: (RealRing.C a) => Wave.T a b -> Phase.T a -> Sig.T a -> Sig.T b
freqMod :: forall a b. C a => T a b -> T a -> T a -> T b
freqMod T a b
wave T a
phase =
    T a b -> T a -> T b
forall (sig :: * -> *) a b.
(Transform sig a, Transform sig b) =>
T a b -> sig a -> sig b
Causal.apply (T a b -> T a -> T a b
forall a b. C a => T a b -> T a -> T a b
Osci.freqMod T a b
wave T a
phase)

{-# INLINE freqModAntiAlias #-}
{- | oscillator with modulated frequency -}
freqModAntiAlias :: (RealRing.C a) =>
    WaveSmooth.T a b -> Phase.T a -> Sig.T a -> Sig.T b
freqModAntiAlias :: forall a b. C a => T a b -> T a -> T a -> T b
freqModAntiAlias T a b
wave T a
phase =
    T a b -> T a -> T b
forall (sig :: * -> *) a b.
(Transform sig a, Transform sig b) =>
T a b -> sig a -> sig b
Causal.apply (T a b -> T a -> T a b
forall a b. C a => T a b -> T a -> T a b
Osci.freqModAntiAlias T a b
wave T a
phase)

{-# INLINE phaseFreqMod #-}
{- | oscillator with both phase and frequency modulation -}
phaseFreqMod :: (RealRing.C a) =>
    Wave.T a b -> Sig.T a -> Sig.T a -> Sig.T b
phaseFreqMod :: forall a b. C a => T a b -> T a -> T a -> T b
phaseFreqMod T a b
wave =
    T (a, a) b -> T a -> T a -> T b
forall (sig :: * -> *) a b c.
(Read sig a, Transform sig b, Transform sig c) =>
T (a, b) c -> sig a -> sig b -> sig c
Causal.apply2 (T a b -> T (a, a) b
forall a b. C a => T a b -> T (a, a) b
Osci.phaseFreqMod T a b
wave)

{-# INLINE shapeFreqMod #-}
{- | oscillator with both shape and frequency modulation -}
shapeFreqMod :: (RealRing.C a) =>
    (c -> Wave.T a b) -> Phase.T a -> Sig.T c -> Sig.T a -> Sig.T b
shapeFreqMod :: forall a c b. C a => (c -> T a b) -> T a -> T c -> T a -> T b
shapeFreqMod c -> T a b
wave T a
phase =
    T (c, a) b -> T c -> T a -> T b
forall (sig :: * -> *) a b c.
(Read sig a, Transform sig b, Transform sig c) =>
T (a, b) c -> sig a -> sig b -> sig c
Causal.apply2 ((c -> T a b) -> T a -> T (c, a) b
forall a c b. C a => (c -> T a b) -> T a -> T (c, a) b
Osci.shapeFreqMod c -> T a b
wave T a
phase)


{- | oscillator with a sampled waveform with constant frequency
     This essentially an interpolation with cyclic padding. -}
{-# INLINE staticSample #-}
staticSample :: RealRing.C a =>
    Interpolation.T a b -> Sig.T b -> Phase.T a -> a -> Sig.T b
staticSample :: forall a b. C a => T a b -> T b -> T a -> a -> T b
staticSample T a b
ip T b
wave T a
phase a
freq =
    T a b -> T a -> T b
forall (sig :: * -> *) a b.
(Transform sig a, Transform sig b) =>
T a b -> sig a -> sig b
Causal.apply (T a b -> T b -> T a -> T a b
forall a b. C a => T a b -> T b -> T a -> T a b
Osci.freqModSample T a b
ip T b
wave T a
phase) (a -> T a
forall a. a -> T a
Sig.repeat a
freq)

{- | oscillator with a sampled waveform with modulated frequency
     Should behave homogenously for different types of interpolation. -}
{-# INLINE freqModSample #-}
freqModSample :: RealRing.C a =>
    Interpolation.T a b -> Sig.T b -> Phase.T a -> Sig.T a -> Sig.T b
freqModSample :: forall a b. C a => T a b -> T b -> T a -> T a -> T b
freqModSample T a b
ip T b
wave T a
phase =
    T a b -> T a -> T b
forall (sig :: * -> *) a b.
(Transform sig a, Transform sig b) =>
T a b -> sig a -> sig b
Causal.apply (T a b -> T b -> T a -> T a b
forall a b. C a => T a b -> T b -> T a -> T a b
Osci.freqModSample T a b
ip T b
wave T a
phase)

{-# INLINE shapeFreqModSample #-}
shapeFreqModSample :: (RealRing.C c, RealRing.C a) =>
    Interpolation.T c (Wave.T a b) -> Sig.T (Wave.T a b) ->
    c -> Phase.T a ->
    Sig.T c -> Sig.T a -> Sig.T b
shapeFreqModSample :: forall c a b.
(C c, C a) =>
T c (T a b) -> T (T a b) -> c -> T a -> T c -> T a -> T b
shapeFreqModSample T c (T a b)
ip T (T a b)
waves c
shape0 T a
phase =
    T (c, a) b -> T c -> T a -> T b
forall (sig :: * -> *) a b c.
(Read sig a, Transform sig b, Transform sig c) =>
T (a, b) c -> sig a -> sig b -> sig c
Causal.apply2 (T c (T a b) -> T (T a b) -> c -> T a -> T (c, a) b
forall c b a.
(C c, C b) =>
T c (T b a) -> T (T b a) -> c -> T b -> T (c, b) a
Osci.shapeFreqModSample T c (T a b)
ip T (T a b)
waves c
shape0 T a
phase)

{-# INLINE shapeFreqModFromSampledTone #-}
shapeFreqModFromSampledTone ::
    (RealField.C a, SigG.Transform sig b) =>
    Interpolation.T a b ->
    Interpolation.T a b ->
    a -> sig b ->
    a -> Phase.T a ->
    Sig.T a -> Sig.T a -> Sig.T b
shapeFreqModFromSampledTone :: forall a (sig :: * -> *) b.
(C a, Transform sig b) =>
T a b -> T a b -> a -> sig b -> a -> T a -> T a -> T a -> T b
shapeFreqModFromSampledTone
      T a b
ipLeap T a b
ipStep a
period sig b
sampledTone a
shape0 T a
phase =
    T (a, a) b -> T a -> T a -> T b
forall (sig :: * -> *) a b c.
(Read sig a, Transform sig b, Transform sig c) =>
T (a, b) c -> sig a -> sig b -> sig c
Causal.apply2
       (T a b -> T a b -> a -> sig b -> a -> T a -> T (a, a) b
forall t (sig :: * -> *) y.
(C t, Transform sig y) =>
T t y -> T t y -> t -> sig y -> t -> T t -> T (t, t) y
Osci.shapeFreqModFromSampledTone
          T a b
ipLeap T a b
ipStep a
period sig b
sampledTone a
shape0 T a
phase)

{-# INLINE shapePhaseFreqModFromSampledTone #-}
shapePhaseFreqModFromSampledTone ::
    (RealField.C a, SigG.Transform sig b) =>
    Interpolation.T a b ->
    Interpolation.T a b ->
    a -> sig b ->
    a -> Phase.T a ->
    Sig.T a -> Sig.T a -> Sig.T a -> Sig.T b
shapePhaseFreqModFromSampledTone :: forall a (sig :: * -> *) b.
(C a, Transform sig b) =>
T a b
-> T a b -> a -> sig b -> a -> T a -> T a -> T a -> T a -> T b
shapePhaseFreqModFromSampledTone
      T a b
ipLeap T a b
ipStep a
period sig b
sampledTone a
shape0 T a
phase =
    T (a, a, a) b -> T a -> T a -> T a -> T b
forall (sig :: * -> *) a b c d.
(Read sig a, Read sig b, Transform sig c, Transform sig d) =>
T (a, b, c) d -> sig a -> sig b -> sig c -> sig d
Causal.apply3
       (T a b -> T a b -> a -> sig b -> a -> T a -> T (a, a, a) b
forall t (sig :: * -> *) y.
(C t, Transform sig y) =>
T t y -> T t y -> t -> sig y -> t -> T t -> T (t, t, t) y
Osci.shapePhaseFreqModFromSampledTone
          T a b
ipLeap T a b
ipStep a
period sig b
sampledTone a
shape0 T a
phase)



{- * Oscillators with specific waveforms -}

{-# INLINE staticSine #-}
{-# SPECIALISE INLINE staticSine :: Phase.T Float -> Float -> Sig.T Float #-}
{-# SPECIALISE INLINE staticSine :: Phase.T Double -> Double -> Sig.T Double #-}
{- | sine oscillator with static frequency -}
staticSine :: (Trans.C a, RealRing.C a) => Phase.T a -> a -> Sig.T a
staticSine :: forall a. (C a, C a) => T a -> a -> T a
staticSine = T a a -> T a -> a -> T a
forall a b. C a => T a b -> T a -> a -> T b
static T a a
forall a. C a => T a a
Wave.sine

{-# INLINE freqModSine #-}
{-# SPECIALISE INLINE freqModSine :: Phase.T Float -> Sig.T Float -> Sig.T Float #-}
{-# SPECIALISE INLINE freqModSine :: Phase.T Double -> Sig.T Double -> Sig.T Double #-}
{- | sine oscillator with modulated frequency -}
freqModSine :: (Trans.C a, RealRing.C a) => Phase.T a -> Sig.T a -> Sig.T a
freqModSine :: forall a. (C a, C a) => T a -> T a -> T a
freqModSine = T a a -> T a -> T a -> T a
forall a b. C a => T a b -> T a -> T a -> T b
freqMod T a a
forall a. C a => T a a
Wave.sine

{-# INLINE phaseModSine #-}
{-# SPECIALISE INLINE phaseModSine :: Float -> Sig.T Float -> Sig.T Float #-}
{-# SPECIALISE INLINE phaseModSine :: Double -> Sig.T Double -> Sig.T Double #-}
{- | sine oscillator with modulated phase, useful for FM synthesis -}
phaseModSine :: (Trans.C a, RealRing.C a) => a -> Sig.T a -> Sig.T a
phaseModSine :: forall a. (C a, C a) => a -> T a -> T a
phaseModSine = T a a -> a -> T a -> T a
forall a b. C a => T a b -> a -> T a -> T b
phaseMod T a a
forall a. C a => T a a
Wave.sine

{-# INLINE staticSaw #-}
{-# SPECIALISE INLINE staticSaw :: Phase.T Float -> Float -> Sig.T Float #-}
{-# SPECIALISE INLINE staticSaw :: Phase.T Double -> Double -> Sig.T Double #-}
{- | saw tooth oscillator with modulated frequency -}
staticSaw :: RealRing.C a => Phase.T a -> a -> Sig.T a
staticSaw :: forall a. C a => T a -> a -> T a
staticSaw = T a a -> T a -> a -> T a
forall a b. C a => T a b -> T a -> a -> T b
static T a a
forall a. C a => T a a
Wave.saw

{-# INLINE freqModSaw #-}
{-# SPECIALISE INLINE freqModSaw :: Phase.T Float -> Sig.T Float -> Sig.T Float #-}
{-# SPECIALISE INLINE freqModSaw :: Phase.T Double -> Sig.T Double -> Sig.T Double #-}
{- | saw tooth oscillator with modulated frequency -}
freqModSaw :: RealRing.C a => Phase.T a -> Sig.T a -> Sig.T a
freqModSaw :: forall a. C a => T a -> T a -> T a
freqModSaw = T a a -> T a -> T a -> T a
forall a b. C a => T a b -> T a -> T a -> T b
freqMod T a a
forall a. C a => T a a
Wave.saw