{- |
Maps that handle pairs of amplitudes and sampled values.
They are a special form of arrows.
module Synthesizer.Dimensional.Map where

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

import qualified Data.Tuple as Tuple
import Data.Tuple.HT as TupleHT (swap, )

import Prelude hiding (map, id, fst, snd, )

{- |
This type shall ensure, that you do not accidentally
bring amplitudes and the corresponding low-level signal values out of sync.
We also use it for generation of internal control parameters
in "Synthesizer.Dimensional.Causal.ControlledProcess".
In principle this could also be 'Causal.T',
but maps are not bound to a sampling rate,
and thus do not need the @s@ type parameter.
newtype T amp0 amp1 yv0 yv1 =
   Cons (amp0 -> (amp1, yv0 -> yv1))

independent ::
   (amp0 -> amp1) -> (yv0 -> yv1) ->
   T amp0 amp1 yv0 yv1
independent f g =
   Cons (\amp -> (f amp, g))

double ::
   T amp (amp, amp)
     y (y, y)
double =
   let aux = \x -> (x, x)
   in  independent aux aux

fst ::
   T (amp0,amp1) amp0
     (y0,y1) y0
fst =
   let aux = Tuple.fst
   in  independent aux aux

snd ::
   T (amp0,amp1) amp1
     (y0,y1) y1
snd =
   let aux = Tuple.snd
   in  independent aux aux

swap ::
   T (amp0,amp1) (amp1,amp0)
     (y0,y1) (y1,y0)
swap =
   let aux = TupleHT.swap
   in  independent aux aux

balanceRight ::
   T ((amp0,amp1), amp2) (amp0, (amp1,amp2))
     ((y0,y1), y2) (y0, (y1,y2))
balanceRight =
   let aux = \((a,b), c) -> (a, (b,c))
   in  independent aux aux

balanceLeft ::
   T (amp0, (amp1,amp2)) ((amp0,amp1), amp2)
     (y0, (y1,y2)) ((y0,y1), y2)
balanceLeft =
   let aux = \(a, (b,c)) -> ((a,b), c)
   in  independent aux aux

packTriple ::
   T (amp0,(amp1,amp2)) (amp0,amp1,amp2)
     (y0,(y1,y2)) (y0,y1,y2)
packTriple =
   let aux = \(a,(b,c)) -> (a,b,c)
   in  independent aux aux

unpackTriple ::
   T (amp0,amp1,amp2) (amp0,(amp1,amp2))
     (y0,y1,y2) (y0,(y1,y2))
unpackTriple =
   let aux = \(a,b,c) -> (a,(b,c))
   in  independent aux aux