{-# LANGUAGE FlexibleInstances #-}

module Nes.APU.State.Filter.Sampled (SampledFilter (..), newSampledFilter) where

import Control.Monad.IO.Class
import Nes.APU.State.Filter.Class
import Nes.APU.State.Filter.Constants
import Nes.APU.State.Filter.Fir
import Nes.APU.State.Filter.Iir
import Prelude hiding (filter)

data SampledFilter = MkSF
    { SampledFilter -> Either IirFilter FirFilter
filter :: Either IirFilter FirFilter
    , SampledFilter -> SampleRate
samplePeriod :: {-# UNPACK #-} !Float
    , SampledFilter -> SampleRate
periodCounter :: {-# UNPACK #-} !Float
    }

newSampledFilter :: Either IirFilter FirFilter -> SampleRate -> SampledFilter
newSampledFilter :: Either IirFilter FirFilter -> SampleRate -> SampledFilter
newSampledFilter Either IirFilter FirFilter
filter SampleRate
sampleRate = MkSF{SampleRate
Either IirFilter FirFilter
filter :: Either IirFilter FirFilter
samplePeriod :: SampleRate
periodCounter :: SampleRate
filter :: Either IirFilter FirFilter
periodCounter :: SampleRate
samplePeriod :: SampleRate
..}
  where
    periodCounter :: SampleRate
periodCounter = SampleRate
1
    samplePeriod :: SampleRate
samplePeriod = SampleRate
1 SampleRate -> SampleRate -> SampleRate
forall a. Fractional a => a -> a -> a
/ SampleRate
sampleRate

instance (MonadIO m) => Filter m SampledFilter where
    consume :: SampleRate -> SampledFilter -> m SampledFilter
consume = SampleRate -> SampledFilter -> m SampledFilter
forall (m :: * -> *).
MonadIO m =>
SampleRate -> SampledFilter -> m SampledFilter
sampledFilterConsumeSample
    output :: SampledFilter -> m SampleRate
output SampledFilter
sf = Either IirFilter FirFilter -> m SampleRate
forall (m :: * -> *) a. Filter m a => a -> m SampleRate
output (Either IirFilter FirFilter -> m SampleRate)
-> Either IirFilter FirFilter -> m SampleRate
forall a b. (a -> b) -> a -> b
$ SampledFilter -> Either IirFilter FirFilter
filter SampledFilter
sf

{-# INLINE sampledFilterConsumeSample #-}
sampledFilterConsumeSample :: (MonadIO m) => Sample -> SampledFilter -> m SampledFilter
sampledFilterConsumeSample :: forall (m :: * -> *).
MonadIO m =>
SampleRate -> SampledFilter -> m SampledFilter
sampledFilterConsumeSample SampleRate
sample SampledFilter
sf = do
    Either IirFilter FirFilter
filter' <- SampleRate
-> Either IirFilter FirFilter -> m (Either IirFilter FirFilter)
forall (m :: * -> *) a. Filter m a => SampleRate -> a -> m a
consume SampleRate
sample (Either IirFilter FirFilter -> m (Either IirFilter FirFilter))
-> Either IirFilter FirFilter -> m (Either IirFilter FirFilter)
forall a b. (a -> b) -> a -> b
$ SampledFilter -> Either IirFilter FirFilter
filter SampledFilter
sf
    SampledFilter -> m SampledFilter
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return
        SampledFilter
sf
            { filter = filter'
            }