{- |
Turn frequency information into signals of phases.
This is mainly the fundament for implementation of oscillators
but you may also use it for generating coherent waves of different form.
-}
module Synthesizer.Dimensional.Causal.Oscillator.Core where

import qualified Synthesizer.Causal.Oscillator.Core as Osci
import qualified Synthesizer.Dimensional.Causal.Process as CausalD
import Synthesizer.Causal.Filter.NonRecursive (amplify, )
import Control.Arrow ((<<<), second, )

import qualified Synthesizer.Dimensional.Sample as Sample
import qualified Synthesizer.Dimensional.Amplitude as Amp
import qualified Synthesizer.Dimensional.Rate as Rate
import qualified Synthesizer.Basic.Phase  as Phase
import Synthesizer.Dimensional.Wave (SamplePhase, )

import qualified Synthesizer.State.Signal as Sig

import qualified Synthesizer.Dimensional.Signal.Private as SigA
import qualified Synthesizer.Dimensional.Process as Proc
import Synthesizer.Dimensional.Process (toFrequencyScalar, )

import qualified Number.DimensionTerm        as DN
import qualified Algebra.DimensionTerm       as Dim
-- import Number.DimensionTerm ((&*&))

import qualified Algebra.RealField          as RealField
-- import qualified Algebra.Field              as Field
-- import qualified Algebra.Ring               as Ring

-- import NumericPrelude.Numeric
-- import NumericPrelude.Base as P


type Frequency u t = Amp.Numeric (DN.T (Dim.Recip u) t)
type SampleFrequency u t = Sample.T (Frequency u t) t


{-# INLINE static #-}
static ::
   (RealField.C t, Dim.C u) =>
      Phase.T t    {- ^ start phase -}
   -> DN.T (Dim.Recip u) t
                   {- ^ frequency -}
   -> Proc.T s u t
         (SigA.T (Rate.Phantom s) Amp.Abstract (Sig.T (Phase.T t)))
--         (Signal s Amp.Abstract (Phase.T t))
static :: forall t u s.
(C t, C u) =>
T t -> T (Recip u) t -> T s u t (T (Phantom s) Abstract (T (T t)))
static T t
phase T (Recip u) t
freq =
   forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall t u s. (C t, C u) => T (Recip u) t -> T s u t t
toFrequencyScalar T (Recip u) t
freq) forall a b. (a -> b) -> a -> b
$ \t
f ->
   forall rate amplitude body.
rate -> amplitude -> body -> T rate amplitude body
SigA.Cons forall s. Phantom s
Rate.Phantom Abstract
Amp.Abstract forall a b. (a -> b) -> a -> b
$
   forall a. C a => T a -> a -> T (T a)
Osci.static T t
phase t
f

{-# INLINE phaseMod #-}
phaseMod :: (RealField.C t, Dim.C u) =>
      DN.T (Dim.Recip u) t    {- ^ frequency -}
   -> Proc.T s u t
         (CausalD.T s (Sample.Flat t) (SamplePhase t))
phaseMod :: forall t u s.
(C t, C u) =>
T (Recip u) t -> T s u t (T s (Flat t) (SamplePhase t))
phaseMod T (Recip u) t
freq =
   forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall t u s. (C t, C u) => T (Recip u) t -> T s u t t
toFrequencyScalar T (Recip u) t
freq) forall a b. (a -> b) -> a -> b
$ \t
f ->
   forall sample0 sample1 s.
(Amplitude sample0
 -> (Amplitude sample1,
     T (Displacement sample0) (Displacement sample1)))
-> T s sample0 sample1
CausalD.consFlip forall a b. (a -> b) -> a -> b
$ \Flat t
Amplitude (Flat t)
Amp.Flat ->
      (Abstract
Amp.Abstract, forall a. C a => a -> T a (T a)
Osci.phaseMod t
f)

{-# INLINE freqMod #-}
freqMod :: (RealField.C t, Dim.C u) =>
      Phase.T t    {- ^ phase -}
   -> Proc.T s u t
         (CausalD.T s (SampleFrequency u t) (SamplePhase t))
freqMod :: forall t u s.
(C t, C u) =>
T t -> T s u t (T s (SampleFrequency u t) (SamplePhase t))
freqMod T t
phase =
   forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a s u t b. (a -> T s u t b) -> T s u t (a -> b)
Proc.withParam forall t u s. (C t, C u) => T (Recip u) t -> T s u t t
toFrequencyScalar) forall a b. (a -> b) -> a -> b
$ \T (Recip u) t -> t
toFreq ->
   forall sample0 sample1 s.
(Amplitude sample0
 -> (Amplitude sample1,
     T (Displacement sample0) (Displacement sample1)))
-> T s sample0 sample1
CausalD.consFlip forall a b. (a -> b) -> a -> b
$ \(Amp.Numeric T (Recip u) t
freqAmp) ->
      (Abstract
Amp.Abstract,
       forall a. C a => T a -> T a (T a)
Osci.freqMod T t
phase forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
<<< forall a. C a => a -> T a a
amplify (T (Recip u) t -> t
toFreq T (Recip u) t
freqAmp))

{-# INLINE phaseFreqMod #-}
phaseFreqMod :: (RealField.C t, Dim.C u) =>
   Proc.T s u t
      (CausalD.T s (Sample.Flat t, SampleFrequency u t) (SamplePhase t))
phaseFreqMod :: forall t u s.
(C t, C u) =>
T s u t (T s (Flat t, SampleFrequency u t) (SamplePhase t))
phaseFreqMod =
   forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a s u t b. (a -> T s u t b) -> T s u t (a -> b)
Proc.withParam forall t u s. (C t, C u) => T (Recip u) t -> T s u t t
toFrequencyScalar) forall a b. (a -> b) -> a -> b
$ \T (Recip u) t -> t
toFreq ->
   forall sample0 sample1 s.
(Amplitude sample0
 -> (Amplitude sample1,
     T (Displacement sample0) (Displacement sample1)))
-> T s sample0 sample1
CausalD.consFlip forall a b. (a -> b) -> a -> b
$ \(Flat t
Amp.Flat, Amp.Numeric T (Recip u) t
freqAmp) ->
      (Abstract
Amp.Abstract,
       forall a. C a => T (a, a) (T a)
Osci.phaseFreqMod forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
<<< forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second (forall a. C a => a -> T a a
amplify (T (Recip u) t -> t
toFreq T (Recip u) t
freqAmp)))