{-# OPTIONS_GHC -fno-warn-orphans #-}
{-# Language
        TypeFamilies,
        MultiParamTypeClasses,
        FlexibleInstances,
        FlexibleContexts #-}
module Csound.SigSpace(
    SigSpace(..), BindSig(..), mul, mul', on, uon, At(..), MixAt(..), bat, bmixAt,
    cfd, cfd4, cfds, cfdSpec, cfdSpec4, cfdsSpec, wsum,

    -- * Stereo sig space
    SigSpace2(..), BindSig2(..), mul2, mul2'
) where

import Csound.Typed
import Csound.Typed.Opcode(pvscross, pvscale, pvsmix, balance)

-- | Spectral crossfade.
cfdSpec :: Sig -> Spec -> Spec -> Spec
cfdSpec :: Sig -> Spec -> Spec -> Spec
cfdSpec Sig
coeff Spec
a Spec
b = Spec -> Spec -> Sig -> Sig -> Spec
pvscross Spec
a Spec
b (Sig
1 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
- Sig
coeff) Sig
coeff

-- | Spectral bilinear crossfade (see @cfd4@).
cfdSpec4 :: Sig -> Sig -> Spec -> Spec -> Spec -> Spec -> Spec
cfdSpec4 :: Sig -> Sig -> Spec -> Spec -> Spec -> Spec -> Spec
cfdSpec4 Sig
x Sig
y Spec
a Spec
b Spec
c Spec
d = (Spec -> Spec -> Spec) -> [Spec] -> Spec
forall a. (a -> a -> a) -> [a] -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldl1 Spec -> Spec -> Spec
pvsmix
    [ Spec -> Sig -> Spec
pvscale Spec
a ((Sig
1 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
- Sig
x) Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* (Sig
1 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
- Sig
y))
    , Spec -> Sig -> Spec
pvscale Spec
b (Sig
x Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* (Sig
1 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
- Sig
y))
    , Spec -> Sig -> Spec
pvscale Spec
c (Sig
x Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
y)
    , Spec -> Sig -> Spec
pvscale Spec
d ((Sig
1 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
- Sig
x) Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
y)
    ]

-- | Generic spectral crossfade.
cfdsSpec :: [Sig] -> [Spec] -> Spec
cfdsSpec :: [Sig] -> [Spec] -> Spec
cfdsSpec = Spec -> (Sig -> Spec -> Spec -> Spec) -> [Sig] -> [Spec] -> Spec
forall a. a -> (Sig -> a -> a -> a) -> [Sig] -> [a] -> a
genCfds Spec
forall a. HasCallStack => a
undefined Sig -> Spec -> Spec -> Spec
cfdSpec

-- | Weighted sum.
wsum :: (Num a, SigSpace a) => [(Sig, a)] -> a
wsum :: forall a. (Num a, SigSpace a) => [(Sig, a)] -> a
wsum = [a] -> a
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([a] -> a) -> ([(Sig, a)] -> [a]) -> [(Sig, a)] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Sig, a) -> a) -> [(Sig, a)] -> [a]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Sig -> a -> a) -> (Sig, a) -> a
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Sig -> a -> a
forall a. SigSpace a => Sig -> a -> a
mul)

-- | It applies an effect and balances the processed signal by original one.
bat :: At Sig a b => (Sig -> a) -> b -> AtOut Sig a b
bat :: forall a b. At Sig a b => (Sig -> a) -> b -> AtOut Sig a b
bat Sig -> a
f = (Sig -> a) -> b -> AtOut Sig a b
forall a b c. At a b c => (a -> b) -> c -> AtOut a b c
at (\Sig
x -> (Sig -> Sig) -> a -> a
forall a. SigSpace a => (Sig -> Sig) -> a -> a
mapSig ( Sig -> Sig -> Sig
`balance` Sig
x) (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ Sig -> a
f Sig
x)

-- | It applies an effect and balances the processed signal by original one.
-- Also it applies an effect and mixes the processed balanced signal with original one.
bmixAt :: MixAt Sig a b => Sig -> (Sig -> a) -> b -> AtOut Sig a b
bmixAt :: forall a b.
MixAt Sig a b =>
Sig -> (Sig -> a) -> b -> AtOut Sig a b
bmixAt Sig
k Sig -> a
f = Sig -> (Sig -> a) -> b -> AtOut Sig a b
forall a b c. MixAt a b c => Sig -> (a -> b) -> c -> AtOut a b c
mixAt Sig
k (\Sig
x -> (Sig -> Sig) -> a -> a
forall a. SigSpace a => (Sig -> Sig) -> a -> a
mapSig ( Sig -> Sig -> Sig
`balance` Sig
x) (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
$ Sig -> a
f Sig
x)