{-# LANGUAGE NoImplicitPrelude #-}
module Synthesizer.Storable.Play where

import qualified Synthesizer.Basic.Binary as BinSmp

import qualified Sound.Sox.Option.Format as SoxOpt
import qualified Sound.Sox.Play as Play

import Foreign.Storable (Storable, )

import qualified Synthesizer.Storable.Signal as SigSt
import qualified Synthesizer.Frame.Stereo as Stereo

import System.Exit (ExitCode, )

import qualified Algebra.RealRing as RealRing

import NumericPrelude.Numeric
import NumericPrelude.Base


{- |
Latency is high using Sox -
We can achieve better results using ALSA's sound output!
See synthesizer-alsa package.
-}
monoToInt16 ::
   (Storable a, RealRing.C a) =>
   a -> SigSt.T a -> IO ExitCode
monoToInt16 :: forall a. (Storable a, C a) => a -> T a -> IO ExitCode
monoToInt16 a
rate =
   (Handle -> Vector Int16 -> IO ())
-> T -> Int -> Vector Int16 -> IO ExitCode
forall y (sig :: * -> *).
C y =>
(Handle -> sig y -> IO ()) -> T -> Int -> sig y -> IO ExitCode
Play.simple Handle -> Vector Int16 -> IO ()
forall a. Storable a => Handle -> Vector a -> IO ()
SigSt.hPut T
SoxOpt.none (a -> Int
forall b. C b => a -> b
forall a b. (C a, C b) => a -> b
round a
rate) (Vector Int16 -> IO ExitCode)
-> (T a -> Vector Int16) -> T a -> IO ExitCode
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   (a -> Int16) -> T a -> Vector Int16
forall x y.
(Storable x, Storable y) =>
(x -> y) -> Vector x -> Vector y
SigSt.map a -> Int16
forall a. C a => a -> Int16
BinSmp.int16FromCanonical

stereoToInt16 ::
   (Storable a, RealRing.C a) =>
   a -> SigSt.T (Stereo.T a) -> IO ExitCode
stereoToInt16 :: forall a. (Storable a, C a) => a -> T (T a) -> IO ExitCode
stereoToInt16 a
rate =
   (Handle -> Vector (T Int16) -> IO ())
-> T -> Int -> Vector (T Int16) -> IO ExitCode
forall y (sig :: * -> *).
C y =>
(Handle -> sig y -> IO ()) -> T -> Int -> sig y -> IO ExitCode
Play.simple Handle -> Vector (T Int16) -> IO ()
forall a. Storable a => Handle -> Vector a -> IO ()
SigSt.hPut T
SoxOpt.none (a -> Int
forall b. C b => a -> b
forall a b. (C a, C b) => a -> b
round a
rate) (Vector (T Int16) -> IO ExitCode)
-> (T (T a) -> Vector (T Int16)) -> T (T a) -> IO ExitCode
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   (T a -> T Int16) -> T (T a) -> Vector (T Int16)
forall x y.
(Storable x, Storable y) =>
(x -> y) -> Vector x -> Vector y
SigSt.map (\T a
y -> Int16 -> Int16 -> T Int16
forall a. a -> a -> T a
Stereo.cons
                       (a -> Int16
forall a. C a => a -> Int16
BinSmp.int16FromCanonical (a -> Int16) -> a -> Int16
forall a b. (a -> b) -> a -> b
$ T a -> a
forall a. T a -> a
Stereo.left T a
y)
                       (a -> Int16
forall a. C a => a -> Int16
BinSmp.int16FromCanonical (a -> Int16) -> a -> Int16
forall a b. (a -> b) -> a -> b
$ T a -> a
forall a. T a -> a
Stereo.right T a
y))