module Synthesizer.Dimensional.Wave where

import qualified Synthesizer.Dimensional.Sample as Sample
import qualified Synthesizer.Dimensional.Map as MapD

import qualified Synthesizer.Basic.Phase as Phase
import qualified Synthesizer.Basic.Wave as Wave
import qualified Synthesizer.Generic.Wave as WaveG
import qualified Synthesizer.Generic.Signal as SigG

import qualified Synthesizer.Interpolation as Interpolation

import qualified Synthesizer.Dimensional.Signal.Private as SigA
import qualified Synthesizer.Dimensional.Amplitude as Amp

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

import qualified Number.DimensionTerm        as DN
import qualified Algebra.DimensionTerm       as Dim

import NumericPrelude.Numeric
import NumericPrelude.Base
import Prelude ()


type SamplePhase t = Sample.Abstract (Phase.T t)

{- |
We define a dimensional waveform in terms of a Map.
This allows any kind and number of result samples
and distortion of waveforms using @(distortion <<<)@
-}
type T t y = MapD.T (SamplePhase t) y

{-# INLINE simple #-}
simple ::
   amp ->
   Wave.T t y ->
   T t (Sample.T amp y)
simple :: forall amp t y. amp -> T t y -> T t (T amp y)
simple amp
amp T t y
wave =
   forall (arrow :: * -> * -> *) sample0 sample1.
Arrow arrow =>
(Amplitude sample0 -> Amplitude sample1)
-> (Displacement sample0 -> Displacement sample1)
-> T arrow sample0 sample1
MapD.independent
      (forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ amp
amp)
      (forall t y. T t y -> T t -> y
Wave.apply T t y
wave)


infix 7 &*~

{-# INLINE (&*~) #-}
(&*~) ::
   amp ->
   Wave.T t y ->
   T t (Sample.Numeric amp y)
&*~ :: forall amp t y. amp -> T t y -> T t (Numeric amp y)
(&*~) = forall amp t y. amp -> T t y -> T t (Numeric amp y)
amplified


{-# INLINE sample #-}
sample ::
   (RealRing.C t, SigG.Transform sig y) =>
   Interpolation.T t y ->
   SigA.T rate amp (sig y) ->
   T t (Sample.T amp y)
sample :: forall t (sig :: * -> *) y rate amp.
(C t, Transform sig y) =>
T t y -> T rate amp (sig y) -> T t (T amp y)
sample T t y
ip T rate amp (sig y)
wave =
   forall amp t y. amp -> T t y -> T t (T amp y)
simple (forall rate amplitude body. T rate amplitude body -> amplitude
SigA.amplitude T rate amp (sig y)
wave) forall a b. (a -> b) -> a -> b
$
   forall a (sig :: * -> *) v.
(C a, Transform sig v) =>
T a v -> sig v -> T a v
WaveG.sample T t y
ip (forall rate amplitude body. T rate amplitude body -> body
SigA.body T rate amp (sig y)
wave)


{-# INLINE flat #-}
flat :: (Ring.C y) =>
   Wave.T t y ->
   T t (Sample.Flat y)
flat :: forall y t. C y => T t y -> T t (Flat y)
flat = forall amp t y. amp -> T t y -> T t (T amp y)
simple forall y. Flat y
Amp.Flat


{-# INLINE abstract #-}
abstract ::
   Wave.T t y ->
   T t (Sample.Abstract y)
abstract :: forall t y. T t y -> T t (Abstract y)
abstract = forall amp t y. amp -> T t y -> T t (T amp y)
simple Abstract
Amp.Abstract


{-# INLINE amplified #-}
amplified ::
   amp ->
   Wave.T t y ->
   T t (Sample.Numeric amp y)
{-
 (Ring.C y, Dim.C u) =>
   DN.T u y ->
   Wave.T t y ->
   T t (Sample.Dimensional u y y)
-}
{-
   amp ->
   Wave.T t y ->
   T amp t y
-}
amplified :: forall amp t y. amp -> T t y -> T t (Numeric amp y)
amplified = forall amp t y. amp -> T t y -> T t (T amp y)
simple forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall amp. amp -> Numeric amp
Amp.Numeric


{-# INLINE mapLinear #-}
mapLinear :: (Ring.C y, Dim.C u) =>
   y ->
   DN.T u y ->
   Wave.T t y ->
   T t (Sample.Dimensional u y y)
mapLinear :: forall y u t.
(C y, C u) =>
y -> T u y -> T t y -> T t (Dimensional u y y)
mapLinear y
depth T u y
center =
   forall amp t y. amp -> T t y -> T t (Numeric amp y)
amplified T u y
center forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall y z t. (y -> z) -> T t y -> T t z
Wave.distort (\y
x -> forall a. C a => a
oneforall a. C a => a -> a -> a
+y
xforall a. C a => a -> a -> a
*y
depth)

{-# INLINE mapExponential #-}
mapExponential :: (Trans.C y, Dim.C u) =>
   y ->
   DN.T u y ->
   Wave.T t y ->
   T t (Sample.Dimensional u y y)
mapExponential :: forall y u t.
(C y, C u) =>
y -> T u y -> T t y -> T t (Dimensional u y y)
mapExponential y
depth T u y
center =
   -- amplified center . Wave.distort (depth**)
   -- should be faster
   forall amp t y. amp -> T t y -> T t (Numeric amp y)
amplified T u y
center forall b c a. (b -> c) -> (a -> b) -> a -> c
.
      let logDepth :: y
logDepth = forall a. C a => a -> a
log y
depth
      in  forall y z t. (y -> z) -> T t y -> T t z
Wave.distort (forall a. C a => a -> a
exp forall b c a. (b -> c) -> (a -> b) -> a -> c
. (y
logDepthforall a. C a => a -> a -> a
*))