module Csound.Typed.Misc(
    HeadPanSpec(..), headPan, headPan', staticHeadPan
) where

import Data.Default
import Csound.Typed.Types
import Csound.Typed.GlobalState

-- | Static head response based spacialization. It works when you listen in headphones.
-- It works only with sample rate of 44100, 48000 or 96000. It's more efficient than @headPan@.
--
-- > staticHeadPan (azimuth, elevation) asig
--
-- azimuth and elevation are measured in ratios (0, 1),
staticHeadPan :: (D, D) -> Sig -> Sig2
staticHeadPan :: (D, D) -> Sig -> Sig2
staticHeadPan (D
az, D
elev) Sig
asrc = GE [E] -> Sig2
forall a. Tuple a => GE [E] -> a
toTuple (GE [E] -> Sig2) -> GE [E] -> Sig2
forall a b. (a -> b) -> a -> b
$ do
        E
azExpr   <- D -> GE E
forall a. Val a => a -> GE E
toGE (D -> GE E) -> D -> GE E
forall a b. (a -> b) -> a -> b
$ -D
90 D -> D -> D
forall a. Num a => a -> a -> a
+ D
180 D -> D -> D
forall a. Num a => a -> a -> a
* D
az
        E
elevExpr <- D -> GE E
forall a. Val a => a -> GE E
toGE (D -> GE E) -> D -> GE E
forall a b. (a -> b) -> a -> b
$ -D
40 D -> D -> D
forall a. Num a => a -> a -> a
+ D
130 D -> D -> D
forall a. Num a => a -> a -> a
* D
elev
        E
asrcExpr <- Sig -> GE E
forall a. Val a => a -> GE E
toGE Sig
asrc                
        E
sr       <- D -> GE E
forall a. Val a => a -> GE E
toGE (D -> GE E) -> D -> GE E
forall a b. (a -> b) -> a -> b
$ D
getSampleRate
        (E
a1, E
a2) <- E -> E -> E -> E -> E -> GE (E, E)
simpleHrtfstat E
asrcExpr E
azExpr E
elevExpr E
iradius E
sr
        [E] -> GE [E]
forall (m :: * -> *) a. Monad m => a -> m a
return [E
a1, E
a2]
        where iradius :: E
iradius = E
9.0

-- | Optional arguments for opcode hrtfmove.
--
-- phase is 0 or 1
--
-- fade is 1 to 24.
--
-- See csound docs for hrtfmove for details.
data HeadPanSpec = HeadPanSpec 
    { HeadPanSpec -> D
headPanPhase :: D
    , HeadPanSpec -> D
hradPanFade  :: D
    }

instance Default HeadPanSpec where
    def :: HeadPanSpec
def = D -> D -> HeadPanSpec
HeadPanSpec D
0 D
8

-- | Head response based spacialization. It works when you listen in headphones.
-- It works only with sample rate of 44100, 48000 or 96000.
--
-- > headPan (azimuth, elevation) asig
--
-- azimuth and elevation are measured in ratios (0, 1),
headPan :: (Sig, Sig) -> Sig -> Sig2
headPan :: Sig2 -> Sig -> Sig2
headPan = HeadPanSpec -> Sig2 -> Sig -> Sig2
headPan' HeadPanSpec
forall a. Default a => a
def

-- | HeadPan with optional arguments.
headPan' :: HeadPanSpec -> (Sig, Sig) -> Sig -> Sig2
headPan' :: HeadPanSpec -> Sig2 -> Sig -> Sig2
headPan' HeadPanSpec
spec (Sig
az, Sig
elev) Sig
asrc = GE [E] -> Sig2
forall a. Tuple a => GE [E] -> a
toTuple (GE [E] -> Sig2) -> GE [E] -> Sig2
forall a b. (a -> b) -> a -> b
$ do
        E
azExpr   <- Sig -> GE E
forall a. Val a => a -> GE E
toGE (Sig -> GE E) -> Sig -> GE E
forall a b. (a -> b) -> a -> b
$ -Sig
90 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
180 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
az
        E
elevExpr <- Sig -> GE E
forall a. Val a => a -> GE E
toGE (Sig -> GE E) -> Sig -> GE E
forall a b. (a -> b) -> a -> b
$ -Sig
40 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
+ Sig
130 Sig -> Sig -> Sig
forall a. Num a => a -> a -> a
* Sig
elev
        E
asrcExpr <- Sig -> GE E
forall a. Val a => a -> GE E
toGE Sig
asrc        
        E
phase    <- D -> GE E
forall a. Val a => a -> GE E
toGE (D -> GE E) -> D -> GE E
forall a b. (a -> b) -> a -> b
$ HeadPanSpec -> D
headPanPhase HeadPanSpec
spec
        E
fade     <- D -> GE E
forall a. Val a => a -> GE E
toGE (D -> GE E) -> D -> GE E
forall a b. (a -> b) -> a -> b
$ HeadPanSpec -> D
hradPanFade  HeadPanSpec
spec
        E
sr       <- D -> GE E
forall a. Val a => a -> GE E
toGE (D -> GE E) -> D -> GE E
forall a b. (a -> b) -> a -> b
$ D
getSampleRate
        (E
a1, E
a2) <- E -> E -> E -> E -> E -> E -> GE (E, E)
simpleHrtfmove E
asrcExpr E
azExpr E
elevExpr E
phase E
fade E
sr
        [E] -> GE [E]
forall (m :: * -> *) a. Monad m => a -> m a
return [E
a1, E
a2]