module Csound.Typed.Plugins.ZeroDelayConvolution(
   ZConvSpec(..), zconv, zconv'
) where

import Data.Default

import Csound.Dynamic

import Csound.Typed.Types
import Csound.Typed.GlobalState
import qualified Csound.Typed.GlobalState.Elements as E(zeroDelayConvolutionPlugin)


-- | Zero convolution specification
data ZConvSpec = ZConvSpec
    { ZConvSpec -> D
zconvPartSize :: D -- ^ first partition size in samples
    , ZConvSpec -> D
zconvRatio    :: D -- ^ partition growth ratio
    , ZConvSpec -> D
zconvNp       :: D -- ^ total number of partition sizes
    }

instance Default ZConvSpec where
    def :: ZConvSpec
def = D -> D -> D -> ZConvSpec
ZConvSpec D
64 D
4 D
6

-------------------------------------------------------------------------------

-- | Zero delay convolution with default parameters.
--
-- > zconv tabIR  ain = ...
zconv :: Tab -> Sig -> Sig
zconv :: Tab -> Sig -> Sig
zconv = ZConvSpec -> Tab -> Sig -> Sig
zconv' ZConvSpec
forall a. Default a => a
def

-- | zero delay convolution.
--
-- > zconv' (ZConvSpec ipart irat inp) ifn ain
--
-- Original UDO code by Victor Lazzarini.
--
-- /**************************************************
-- asig ZConv ain,ipart,irat,inp,ifn
-- ain - input signal
-- ipart - first partition size in samples
-- irat - partition growth ratio
-- inp - total number of partition sizes
-- ifn - function table number containing the IR
-- **************************************************/
zconv' :: ZConvSpec -> Tab -> Sig -> Sig
zconv' :: ZConvSpec -> Tab -> Sig -> Sig
zconv' (ZConvSpec D
ipart D
irat D
inp) Tab
ifn Sig
ain = GE E -> Sig
forall a. Val a => GE E -> a
fromGE (GE E -> Sig) -> GE E -> Sig
forall a b. (a -> b) -> a -> b
$ do
    UdoPlugin -> GE ()
addUdoPlugin UdoPlugin
E.zeroDelayConvolutionPlugin
    E -> E -> E -> E -> E -> E
f (E -> E -> E -> E -> E -> E) -> GE E -> GE (E -> E -> E -> E -> E)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Sig -> GE E
forall a. Val a => a -> GE E
toGE Sig
ain GE (E -> E -> E -> E -> E) -> GE E -> GE (E -> E -> E -> E)
forall a b. GE (a -> b) -> GE a -> GE b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> D -> GE E
forall a. Val a => a -> GE E
toGE D
ipart GE (E -> E -> E -> E) -> GE E -> GE (E -> E -> E)
forall a b. GE (a -> b) -> GE a -> GE b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> D -> GE E
forall a. Val a => a -> GE E
toGE D
irat GE (E -> E -> E) -> GE E -> GE (E -> E)
forall a b. GE (a -> b) -> GE a -> GE b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> D -> GE E
forall a. Val a => a -> GE E
toGE D
inp GE (E -> E) -> GE E -> GE E
forall a b. GE (a -> b) -> GE a -> GE b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Tab -> GE E
forall a. Val a => a -> GE E
toGE Tab
ifn
    where f :: E -> E -> E -> E -> E -> E
f E
ain' E
ipart' E
irat' E
inp' E
ifn' = Name -> Spec1 -> [E] -> E
opcs Name
"ZConv" [(Rate
Ar, [Rate
Ar, Rate
Ir, Rate
Ir, Rate
Ir, Rate
Ir])] [E
ain', E
ipart', E
irat', E
inp', E
ifn']