{-# LANGUAGE Arrows #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
module FRP.Rhine.Clock.Realtime.Audio
( AudioClock (..)
, AudioRate (..)
, PureAudioClock (..)
, PureAudioClockF
, pureAudioClockF
)
where
import GHC.Float (double2Float)
import GHC.TypeLits (Nat, natVal, KnownNat)
import Data.Time.Clock
import Control.Monad.IO.Class
import Control.Monad.Trans.MSF.Except hiding (step)
import FRP.Rhine.Clock
import FRP.Rhine.Clock.Proxy
data AudioRate
= Hz44100
| Hz48000
| Hz96000
rateToIntegral :: Integral a => AudioRate -> a
rateToIntegral :: AudioRate -> a
rateToIntegral AudioRate
Hz44100 = a
44100
rateToIntegral AudioRate
Hz48000 = a
48000
rateToIntegral AudioRate
Hz96000 = a
96000
data AudioClock (rate :: AudioRate) (bufferSize :: Nat) = AudioClock
class AudioClockRate (rate :: AudioRate) where
theRate :: AudioClock rate bufferSize -> AudioRate
theRateIntegral :: Integral a => AudioClock rate bufferSize -> a
theRateIntegral = AudioRate -> a
forall a. Integral a => AudioRate -> a
rateToIntegral (AudioRate -> a)
-> (AudioClock rate bufferSize -> AudioRate)
-> AudioClock rate bufferSize
-> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AudioClock rate bufferSize -> AudioRate
forall (rate :: AudioRate) (bufferSize :: Nat).
AudioClockRate rate =>
AudioClock rate bufferSize -> AudioRate
theRate
theRateNum :: Num a => AudioClock rate bufferSize -> a
theRateNum = Integer -> a
forall a. Num a => Integer -> a
fromInteger (Integer -> a)
-> (AudioClock rate bufferSize -> Integer)
-> AudioClock rate bufferSize
-> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AudioClock rate bufferSize -> Integer
forall (rate :: AudioRate) a (bufferSize :: Nat).
(AudioClockRate rate, Integral a) =>
AudioClock rate bufferSize -> a
theRateIntegral
instance AudioClockRate Hz44100 where
theRate :: AudioClock 'Hz44100 bufferSize -> AudioRate
theRate AudioClock 'Hz44100 bufferSize
_ = AudioRate
Hz44100
instance AudioClockRate Hz48000 where
theRate :: AudioClock 'Hz48000 bufferSize -> AudioRate
theRate AudioClock 'Hz48000 bufferSize
_ = AudioRate
Hz48000
instance AudioClockRate Hz96000 where
theRate :: AudioClock 'Hz96000 bufferSize -> AudioRate
theRate AudioClock 'Hz96000 bufferSize
_ = AudioRate
Hz96000
theBufferSize
:: (KnownNat bufferSize, Integral a)
=> AudioClock rate bufferSize -> a
theBufferSize :: AudioClock rate bufferSize -> a
theBufferSize = Integer -> a
forall a. Num a => Integer -> a
fromInteger (Integer -> a)
-> (AudioClock rate bufferSize -> Integer)
-> AudioClock rate bufferSize
-> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AudioClock rate bufferSize -> Integer
forall (n :: Nat) (proxy :: Nat -> Type).
KnownNat n =>
proxy n -> Integer
natVal
instance (MonadIO m, KnownNat bufferSize, AudioClockRate rate)
=> Clock m (AudioClock rate bufferSize) where
type Time (AudioClock rate bufferSize) = UTCTime
type Tag (AudioClock rate bufferSize) = Maybe Double
initClock :: AudioClock rate bufferSize
-> RunningClockInit
m
(Time (AudioClock rate bufferSize))
(Tag (AudioClock rate bufferSize))
initClock AudioClock rate bufferSize
audioClock = do
let
step :: DiffTime
step = Integer -> DiffTime
picosecondsToDiffTime
(Integer -> DiffTime) -> Integer -> DiffTime
forall a b. (a -> b) -> a -> b
$ Double -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round (Double
10 Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^ (Integer
12 :: Integer) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ AudioClock rate bufferSize -> Double
forall (rate :: AudioRate) a (bufferSize :: Nat).
(AudioClockRate rate, Num a) =>
AudioClock rate bufferSize -> a
theRateNum AudioClock rate bufferSize
audioClock :: Double)
bufferSize :: Int
bufferSize = AudioClock rate bufferSize -> Int
forall (bufferSize :: Nat) a (rate :: AudioRate).
(KnownNat bufferSize, Integral a) =>
AudioClock rate bufferSize -> a
theBufferSize AudioClock rate bufferSize
audioClock
runningClock :: MonadIO m => UTCTime -> Maybe Double -> MSF m () (UTCTime, Maybe Double)
runningClock :: UTCTime -> Maybe Double -> MSF m () (UTCTime, Maybe Double)
runningClock UTCTime
initialTime Maybe Double
maybeWasLate = MSFExcept m () (UTCTime, Maybe Double) Void
-> MSF m () (UTCTime, Maybe Double)
forall (m :: Type -> Type) a b.
Monad m =>
MSFExcept m a b Void -> MSF m a b
safely (MSFExcept m () (UTCTime, Maybe Double) Void
-> MSF m () (UTCTime, Maybe Double))
-> MSFExcept m () (UTCTime, Maybe Double) Void
-> MSF m () (UTCTime, Maybe Double)
forall a b. (a -> b) -> a -> b
$ do
UTCTime
bufferFullTime <- MSF (ExceptT UTCTime m) () (UTCTime, Maybe Double)
-> MSFExcept m () (UTCTime, Maybe Double) UTCTime
forall e (m :: Type -> Type) a b.
MSF (ExceptT e m) a b -> MSFExcept m a b e
try (MSF (ExceptT UTCTime m) () (UTCTime, Maybe Double)
-> MSFExcept m () (UTCTime, Maybe Double) UTCTime)
-> MSF (ExceptT UTCTime m) () (UTCTime, Maybe Double)
-> MSFExcept m () (UTCTime, Maybe Double) UTCTime
forall a b. (a -> b) -> a -> b
$ proc () -> do
Int
n <- MSF (ExceptT UTCTime m) () Int
forall n (m :: Type -> Type) a. (Num n, Monad m) => MSF m a n
count -< ()
let nextTime :: UTCTime
nextTime = (DiffTime -> NominalDiffTime
forall a b. (Real a, Fractional b) => a -> b
realToFrac DiffTime
step NominalDiffTime -> NominalDiffTime -> NominalDiffTime
forall a. Num a => a -> a -> a
* Int -> NominalDiffTime
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
n :: Int)) NominalDiffTime -> UTCTime -> UTCTime
`addUTCTime` UTCTime
initialTime
()
_ <- MSF (ExceptT UTCTime m) (Bool, UTCTime) ()
forall (m :: Type -> Type) e.
Monad m =>
MSF (ExceptT e m) (Bool, e) ()
throwOn' -< (Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
bufferSize, UTCTime
nextTime)
MSF
(ExceptT UTCTime m) (UTCTime, Maybe Double) (UTCTime, Maybe Double)
forall (a :: Type -> Type -> Type) b. Arrow a => a b b
returnA -< (UTCTime
nextTime, if Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe Double
maybeWasLate else Maybe Double
forall a. Maybe a
Nothing)
UTCTime
currentTime <- m UTCTime -> MSFExcept m () (UTCTime, Maybe Double) UTCTime
forall (m :: Type -> Type) e a b.
Monad m =>
m e -> MSFExcept m a b e
once_ (m UTCTime -> MSFExcept m () (UTCTime, Maybe Double) UTCTime)
-> m UTCTime -> MSFExcept m () (UTCTime, Maybe Double) UTCTime
forall a b. (a -> b) -> a -> b
$ IO UTCTime -> m UTCTime
forall (m :: Type -> Type) a. MonadIO m => IO a -> m a
liftIO IO UTCTime
getCurrentTime
let
lateDiff :: Diff UTCTime
lateDiff = UTCTime
currentTime UTCTime -> UTCTime -> Diff UTCTime
forall time. TimeDomain time => time -> time -> Diff time
`diffTime` UTCTime
bufferFullTime
late :: Maybe Double
late = if Double
Diff UTCTime
lateDiff Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0 then Double -> Maybe Double
forall a. a -> Maybe a
Just Double
Diff UTCTime
lateDiff else Maybe Double
forall a. Maybe a
Nothing
MSF m () (UTCTime, Maybe Double)
-> MSFExcept m () (UTCTime, Maybe Double) Void
forall (m :: Type -> Type) a b e.
Monad m =>
MSF m a b -> MSFExcept m a b e
safe (MSF m () (UTCTime, Maybe Double)
-> MSFExcept m () (UTCTime, Maybe Double) Void)
-> MSF m () (UTCTime, Maybe Double)
-> MSFExcept m () (UTCTime, Maybe Double) Void
forall a b. (a -> b) -> a -> b
$ UTCTime -> Maybe Double -> MSF m () (UTCTime, Maybe Double)
forall (m :: Type -> Type).
MonadIO m =>
UTCTime -> Maybe Double -> MSF m () (UTCTime, Maybe Double)
runningClock UTCTime
bufferFullTime Maybe Double
late
UTCTime
initialTime <- IO UTCTime -> m UTCTime
forall (m :: Type -> Type) a. MonadIO m => IO a -> m a
liftIO IO UTCTime
getCurrentTime
(MSF m () (UTCTime, Maybe Double), UTCTime)
-> m (MSF m () (UTCTime, Maybe Double), UTCTime)
forall (m :: Type -> Type) a. Monad m => a -> m a
return
( UTCTime -> Maybe Double -> MSF m () (UTCTime, Maybe Double)
forall (m :: Type -> Type).
MonadIO m =>
UTCTime -> Maybe Double -> MSF m () (UTCTime, Maybe Double)
runningClock UTCTime
initialTime Maybe Double
forall a. Maybe a
Nothing
, UTCTime
initialTime
)
instance GetClockProxy (AudioClock rate bufferSize)
data PureAudioClock (rate :: AudioRate) = PureAudioClock
class PureAudioClockRate (rate :: AudioRate) where
thePureRate :: PureAudioClock rate -> AudioRate
thePureRateIntegral :: Integral a => PureAudioClock rate -> a
thePureRateIntegral = AudioRate -> a
forall a. Integral a => AudioRate -> a
rateToIntegral (AudioRate -> a)
-> (PureAudioClock rate -> AudioRate) -> PureAudioClock rate -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PureAudioClock rate -> AudioRate
forall (rate :: AudioRate).
PureAudioClockRate rate =>
PureAudioClock rate -> AudioRate
thePureRate
thePureRateNum :: Num a => PureAudioClock rate -> a
thePureRateNum = Integer -> a
forall a. Num a => Integer -> a
fromInteger (Integer -> a)
-> (PureAudioClock rate -> Integer) -> PureAudioClock rate -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PureAudioClock rate -> Integer
forall (rate :: AudioRate) a.
(PureAudioClockRate rate, Integral a) =>
PureAudioClock rate -> a
thePureRateIntegral
instance (Monad m, PureAudioClockRate rate) => Clock m (PureAudioClock rate) where
type Time (PureAudioClock rate) = Double
type Tag (PureAudioClock rate) = ()
initClock :: PureAudioClock rate
-> RunningClockInit
m (Time (PureAudioClock rate)) (Tag (PureAudioClock rate))
initClock PureAudioClock rate
audioClock = (MSF m () (Double, ()), Double)
-> m (MSF m () (Double, ()), Double)
forall (m :: Type -> Type) a. Monad m => a -> m a
return
( (() -> Double) -> MSF m () Double
forall (a :: Type -> Type -> Type) b c.
Arrow a =>
(b -> c) -> a b c
arr (Double -> () -> Double
forall a b. a -> b -> a
const (Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ PureAudioClock rate -> Double
forall (rate :: AudioRate) a.
(PureAudioClockRate rate, Num a) =>
PureAudioClock rate -> a
thePureRateNum PureAudioClock rate
audioClock)) MSF m () Double
-> MSF m Double (Double, ()) -> MSF m () (Double, ())
forall k (cat :: k -> k -> Type) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> MSF m Double Double
forall v s (m :: Type -> Type).
(VectorSpace v s, Monad m) =>
MSF m v v
sumS MSF m Double Double -> MSF m Double () -> MSF m Double (Double, ())
forall (a :: Type -> Type -> Type) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& (Double -> ()) -> MSF m Double ()
forall (a :: Type -> Type -> Type) b c.
Arrow a =>
(b -> c) -> a b c
arr (() -> Double -> ()
forall a b. a -> b -> a
const ())
, Double
0
)
instance GetClockProxy (PureAudioClock rate)
type PureAudioClockF (rate :: AudioRate) = RescaledClock (PureAudioClock rate) Float
pureAudioClockF :: PureAudioClockF rate
pureAudioClockF :: PureAudioClockF rate
pureAudioClockF = RescaledClock :: forall cl time. cl -> Rescaling cl time -> RescaledClock cl time
RescaledClock
{ unscaledClock :: PureAudioClock rate
unscaledClock = PureAudioClock rate
forall (rate :: AudioRate). PureAudioClock rate
PureAudioClock
, rescale :: Rescaling (PureAudioClock rate) Float
rescale = Double -> Float
Rescaling (PureAudioClock rate) Float
double2Float
}