-- | Pure (read-only) arrays
module Csound.Typed.Types.PureArray
  ( PureArr
  , PureArrD
  , newPureArr
  , newPureArrD
  , readPureArr
  , readPureArrD
  ) where

import Data.List qualified as List
import Data.Proxy

import Csound.Dynamic (E, IfRate (..))
import Csound.Dynamic qualified as D
import Csound.Typed.Types.Prim
import Csound.Typed.Types.Tuple
import Csound.Typed.GlobalState.GE

-- | Pure (read-only) array.
-- We can initialise it and it's a pure value.
-- After initialisation we can read values with lookupPureArr
--
-- This version works on initialisation rate
newtype PureArrD a = PureArrD (GE [E])

-- | Pure (read-only) array.
-- We can initialise it and it's a pure value.
-- After initialisation we can read values with lookupPureArr
--
-- This version works on control rate
newtype PureArr a = PureArr (GE [E])

-----------------------------------------------------------------------------
-- initialization

-- | Inits pure array that can be read at control rate
newPureArr :: Tuple a => [a] -> PureArr a
newPureArr :: forall a. Tuple a => [a] -> PureArr a
newPureArr = GE [E] -> PureArr a
forall a. GE [E] -> PureArr a
PureArr (GE [E] -> PureArr a) -> ([a] -> GE [E]) -> [a] -> PureArr a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IfRate -> [a] -> GE [E]
forall a. Tuple a => IfRate -> [a] -> GE [E]
newPureArrBy IfRate
IfKr

-- | Inits pure array that can be read at initialisation rate
newPureArrD :: Arg a => [a] -> PureArrD a
newPureArrD :: forall a. Arg a => [a] -> PureArrD a
newPureArrD = GE [E] -> PureArrD a
forall a. GE [E] -> PureArrD a
PureArrD (GE [E] -> PureArrD a) -> ([a] -> GE [E]) -> [a] -> PureArrD a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IfRate -> [a] -> GE [E]
forall a. Tuple a => IfRate -> [a] -> GE [E]
newPureArrBy IfRate
IfKr

newPureArrBy :: forall a . Tuple a => IfRate -> [a] -> GE [E]
newPureArrBy :: forall a. Tuple a => IfRate -> [a] -> GE [E]
newPureArrBy IfRate
procRate [a]
initVals = do
  [[E]]
initPrimVals <- [[E]] -> [[E]]
forall a. [[a]] -> [[a]]
List.transpose ([[E]] -> [[E]]) -> GE [[E]] -> GE [[E]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a -> GE [E]) -> [a] -> GE [[E]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM a -> GE [E]
forall a. Tuple a => a -> GE [E]
fromTuple [a]
initVals
  [E] -> GE [E]
forall a. a -> GE a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([E] -> GE [E]) -> [E] -> GE [E]
forall a b. (a -> b) -> a -> b
$ (Rate -> [E] -> E) -> [Rate] -> [[E]] -> [E]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Rate
outRate [E]
initPrims -> Rate -> IfRate -> [E] -> E
D.initPureArr Rate
outRate IfRate
procRate [E]
initPrims) [Rate]
outRates [[E]]
initPrimVals
  where
    outRates :: [Rate]
outRates = Proxy a -> [Rate]
forall a. Tuple a => Proxy a -> [Rate]
tupleRates (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @a)

-----------------------------------------------------------------------------
-- read values

readPureArr :: Tuple a => PureArr a -> Sig -> a
readPureArr :: forall a. Tuple a => PureArr a -> Sig -> a
readPureArr (PureArr GE [E]
vals) Sig
index =
  IfRate -> GE [E] -> GE E -> a
forall a. Tuple a => IfRate -> GE [E] -> GE E -> a
readPureArrBy IfRate
IfKr GE [E]
vals (Sig -> GE E
forall a. Val a => a -> GE E
toGE Sig
index)

readPureArrD :: Arg a => PureArrD a -> D -> a
readPureArrD :: forall a. Arg a => PureArrD a -> D -> a
readPureArrD (PureArrD GE [E]
vals) D
index =
  IfRate -> GE [E] -> GE E -> a
forall a. Tuple a => IfRate -> GE [E] -> GE E -> a
readPureArrBy IfRate
IfIr GE [E]
vals (D -> GE E
forall a. Val a => a -> GE E
toGE D
index)

readPureArrBy :: forall a . Tuple a => IfRate -> GE [E] -> GE E -> a
readPureArrBy :: forall a. Tuple a => IfRate -> GE [E] -> GE E -> a
readPureArrBy IfRate
procRate GE [E]
vals GE E
index = GE [E] -> a
forall a. Tuple a => GE [E] -> a
toTuple (GE [E] -> a) -> GE [E] -> a
forall a b. (a -> b) -> a -> b
$ do
  E
indexE <- GE E
index
  [E]
valsE  <- GE [E]
vals
  [E] -> GE [E]
forall a. a -> GE a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([E] -> GE [E]) -> [E] -> GE [E]
forall a b. (a -> b) -> a -> b
$ (Rate -> E -> E) -> [Rate] -> [E] -> [E]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Rate
outRate E
arr -> Rate -> IfRate -> E -> E -> E
D.readPureArr Rate
outRate IfRate
procRate E
arr (Rate -> E -> E
D.setRate Rate
indexRate E
indexE)) [Rate]
outRates [E]
valsE
  where
    indexRate :: Rate
indexRate = IfRate -> Rate
D.fromIfRate IfRate
procRate
    outRates :: [Rate]
outRates = Proxy a -> [Rate]
forall a. Tuple a => Proxy a -> [Rate]
tupleRates (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @a)