{-# LANGUAGE NoImplicitPrelude #-}
module Synthesizer.State.Displacement where

import qualified Synthesizer.State.Signal as Sig

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

import NumericPrelude.Numeric
import NumericPrelude.Base


-- * Mixing

{-|
Mix two signals.
In opposition to 'zipWith' the result has the length of the longer signal.
-}
{-# INLINE mix #-}
mix :: (Additive.C v) => Sig.T v -> Sig.T v -> Sig.T v
mix :: forall v. C v => T v -> T v -> T v
mix = T v -> T v -> T v
forall v. C v => T v -> T v -> T v
Sig.mix

{-| Mix an arbitrary number of signals. -}
{-# INLINE mixMulti #-}
mixMulti :: (Additive.C v) => [Sig.T v] -> Sig.T v
mixMulti :: forall v. C v => [T v] -> T v
mixMulti = (T v -> T v -> T v) -> T v -> [T v] -> T v
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl T v -> T v -> T v
forall v. C v => T v -> T v -> T v
mix T v
forall a. T a
Sig.empty


{-|
Add a number to all of the signal values.
This is useful for adjusting the center of a modulation.
-}
{-# INLINE raise #-}
raise :: (Additive.C v) => v -> Sig.T v -> Sig.T v
raise :: forall v. C v => v -> T v -> T v
raise v
x = (v -> v) -> T v -> T v
forall a b. (a -> b) -> T a -> T b
Sig.map (v -> v -> v
forall a. C a => a -> a -> a
(+) v
x)


-- * Distortion

{-|
In "Synthesizer.Basic.Distortion" you find a collection
of appropriate distortion functions.
-}
{-# INLINE distort #-}
distort :: (c -> a -> a) -> Sig.T c -> Sig.T a -> Sig.T a
distort :: forall c a. (c -> a -> a) -> T c -> T a -> T a
distort = (c -> a -> a) -> T c -> T a -> T a
forall a b c. (a -> b -> c) -> T a -> T b -> T c
Sig.zipWith


-- * Preprocessing of control curves

{-# INLINE mapLinear #-}
mapLinear :: (Ring.C a) =>
   a ->
   a ->
   Sig.T a ->
   Sig.T a
mapLinear :: forall a. C a => a -> a -> T a -> T a
mapLinear a
depth a
center =
   (a -> a) -> T a -> T a
forall a b. (a -> b) -> T a -> T b
Sig.map (\a
x -> a
centera -> a -> a
forall a. C a => a -> a -> a
*(a
forall a. C a => a
onea -> a -> a
forall a. C a => a -> a -> a
+a
xa -> a -> a
forall a. C a => a -> a -> a
*a
depth))

{-# INLINE mapExponential #-}
mapExponential :: (Trans.C a) =>
   a ->
   a ->
   Sig.T a ->
   Sig.T a
mapExponential :: forall a. C a => a -> a -> T a -> T a
mapExponential a
depth a
center =
   -- Sig.map ((center*) . (depth**))
   -- should be faster
   let logDepth :: a
logDepth = a -> a
forall a. C a => a -> a
log a
depth
   in  (a -> a) -> T a -> T a
forall a b. (a -> b) -> T a -> T b
Sig.map ((a
centera -> a -> a
forall a. C a => a -> a -> a
*) (a -> a) -> (a -> a) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> a
forall a. C a => a -> a
exp (a -> a) -> (a -> a) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a
logDeptha -> a -> a
forall a. C a => a -> a -> a
*))