{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE Rank2Types #-}
module Synthesizer.ALSA.Dimensional.Play where

import qualified Synthesizer.ALSA.Storable.Play as Play

import qualified Synthesizer.Dimensional.Rate as Rate
import qualified Synthesizer.Dimensional.Amplitude as Amp

import qualified Synthesizer.Dimensional.Process as Proc
import qualified Synthesizer.Dimensional.Signal.Private as SigA

import qualified Synthesizer.Frame.Stereo as Stereo

import qualified Synthesizer.Storable.Signal as SigSt

import qualified Sound.ALSA.PCM as ALSA

import qualified Algebra.DimensionTerm as Dim
import qualified Number.DimensionTerm  as DN

-- import qualified Algebra.ToInteger      as ToInteger
import qualified Algebra.Module         as Module
import qualified Algebra.RealRing      as RealRing
-- import qualified Algebra.Field          as Field
-- import qualified Algebra.Ring           as Ring

import Foreign.Storable (Storable, )

-- import NumericPrelude.Numeric
import NumericPrelude.Base


type Device = String

type RenderedStorableSignal u t v y yv =
   SigA.T (Rate.Dimensional u t) (Amp.Dimensional v y) (SigSt.T yv)

type StorableSignal s v y yv =
   SigA.T (Rate.Phantom s) (Amp.Dimensional v y) (SigSt.T yv)


makeSink ::
   (ALSA.SampleFmt y, RealRing.C t) =>
   Device {- ^ ALSA output device -} ->
   DN.Time t {- ^ period (buffer) size expressed in seconds -} ->
   DN.Frequency t {- ^ sample rate -} ->
   ALSA.SoundSink ALSA.Pcm y
makeSink :: Device -> Time t -> Frequency t -> SoundSink Pcm y
makeSink Device
device Time t
periodTime Frequency t
rate =
   Device -> t -> SampleFreq -> SoundSink Pcm y
forall y t.
(SampleFmt y, C t) =>
Device -> t -> SampleFreq -> SoundSink Pcm y
Play.makeSink Device
device
      (Time -> Time t -> t
forall u a. C u => u -> T u a -> a
DN.toNumberWithDimension Time
Dim.time Time t
periodTime)
      (t -> SampleFreq
forall a b. (C a, C b) => a -> b
RealRing.round (Frequency -> Frequency t -> t
forall u a. C u => u -> T u a -> a
DN.toNumberWithDimension Frequency
Dim.frequency Frequency t
rate))


{-# INLINE timeVoltageStorable #-}
timeVoltageStorable ::
   (Module.C y yv, ALSA.SampleFmt yv, RealRing.C t) =>
   Device ->
   DN.Time t->
   RenderedStorableSignal Dim.Time t Dim.Voltage y yv ->
   IO ()
timeVoltageStorable :: Device
-> Time t -> RenderedStorableSignal Time t Voltage y yv -> IO ()
timeVoltageStorable Device
device Time t
period RenderedStorableSignal Time t Voltage y yv
sig =
   SoundSink Pcm yv -> T yv -> IO ()
forall y (handle :: * -> *).
SampleFmt y =>
SoundSink handle y -> T y -> IO ()
Play.auto (Device -> Time t -> Frequency t -> SoundSink Pcm yv
forall y t.
(SampleFmt y, C t) =>
Device -> Time t -> Frequency t -> SoundSink Pcm y
makeSink Device
device Time t
period (RenderedStorableSignal Time t Voltage y yv -> Frequency t
forall rate amp sig. T (Actual rate) amp sig -> rate
SigA.actualSampleRate RenderedStorableSignal Time t Voltage y yv
sig))
      ((T Voltage y -> y)
-> RenderedStorableSignal Time t Voltage y yv -> T yv
forall y yv (sig :: * -> *) amp rate.
(C y yv, Transform sig yv) =>
(amp -> y) -> T rate (Numeric amp) (sig yv) -> sig yv
SigA.vectorSamples (Voltage -> T Voltage y -> y
forall u a. C u => u -> T u a -> a
DN.toNumberWithDimension Voltage
Dim.voltage) RenderedStorableSignal Time t Voltage y yv
sig)

{-# INLINE timeVoltageMonoStorableToInt16 #-}
timeVoltageMonoStorableToInt16 ::
   (Storable y, RealRing.C y, RealRing.C t) =>
   Device ->
   DN.Time t->
   RenderedStorableSignal Dim.Time t Dim.Voltage y y ->
   IO ()
timeVoltageMonoStorableToInt16 :: Device
-> Time t -> RenderedStorableSignal Time t Voltage y y -> IO ()
timeVoltageMonoStorableToInt16 Device
device Time t
period RenderedStorableSignal Time t Voltage y y
sig =
   SoundSink Pcm Int16 -> T y -> IO ()
forall y (handle :: * -> *).
(Storable y, C y) =>
SoundSink handle Int16 -> T y -> IO ()
Play.monoToInt16 (Device -> Time t -> Frequency t -> SoundSink Pcm Int16
forall y t.
(SampleFmt y, C t) =>
Device -> Time t -> Frequency t -> SoundSink Pcm y
makeSink Device
device Time t
period (RenderedStorableSignal Time t Voltage y y -> Frequency t
forall rate amp sig. T (Actual rate) amp sig -> rate
SigA.actualSampleRate RenderedStorableSignal Time t Voltage y y
sig))
      ((T Voltage y -> y)
-> RenderedStorableSignal Time t Voltage y y -> T y
forall y (sig :: * -> *) amp rate.
(C y, Transform sig y) =>
(amp -> y) -> T rate (Numeric amp) (sig y) -> sig y
SigA.scalarSamples (Voltage -> T Voltage y -> y
forall u a. C u => u -> T u a -> a
DN.toNumberWithDimension Voltage
Dim.voltage) RenderedStorableSignal Time t Voltage y y
sig)

{-# INLINE timeVoltageStereoStorableToInt16 #-}
timeVoltageStereoStorableToInt16 ::
   (Storable y, Module.C y y, RealRing.C y, RealRing.C t) =>
   Device ->
   DN.Time t->
   RenderedStorableSignal Dim.Time t Dim.Voltage y (Stereo.T y) ->
   IO ()
timeVoltageStereoStorableToInt16 :: Device
-> Time t -> RenderedStorableSignal Time t Voltage y (T y) -> IO ()
timeVoltageStereoStorableToInt16 Device
device Time t
period RenderedStorableSignal Time t Voltage y (T y)
sig =
   SoundSink Pcm (T Int16) -> T (T y) -> IO ()
forall y (handle :: * -> *).
(Storable y, C y) =>
SoundSink handle (T Int16) -> T (T y) -> IO ()
Play.stereoToInt16 (Device -> Time t -> Frequency t -> SoundSink Pcm (T Int16)
forall y t.
(SampleFmt y, C t) =>
Device -> Time t -> Frequency t -> SoundSink Pcm y
makeSink Device
device Time t
period (RenderedStorableSignal Time t Voltage y (T y) -> Frequency t
forall rate amp sig. T (Actual rate) amp sig -> rate
SigA.actualSampleRate RenderedStorableSignal Time t Voltage y (T y)
sig))
      ((T Voltage y -> y)
-> RenderedStorableSignal Time t Voltage y (T y) -> T (T y)
forall y yv (sig :: * -> *) amp rate.
(C y yv, Transform sig yv) =>
(amp -> y) -> T rate (Numeric amp) (sig yv) -> sig yv
SigA.vectorSamples (Voltage -> T Voltage y -> y
forall u a. C u => u -> T u a -> a
DN.toNumberWithDimension Voltage
Dim.voltage) RenderedStorableSignal Time t Voltage y (T y)
sig)


{-# INLINE renderTimeVoltageStorable #-}
renderTimeVoltageStorable ::
   (Module.C y yv, ALSA.SampleFmt yv, RealRing.C t) =>
   Device ->
   DN.Time t->
   DN.T Dim.Frequency t ->
   (forall s. Proc.T s Dim.Time t
      (StorableSignal s Dim.Voltage y yv)) ->
   IO ()
renderTimeVoltageStorable :: Device
-> Time t
-> T Frequency t
-> (forall s. T s Time t (StorableSignal s Voltage y yv))
-> IO ()
renderTimeVoltageStorable Device
device Time t
period T Frequency t
rate forall s. T s Time t (StorableSignal s Voltage y yv)
sig =
   Device
-> Time t -> RenderedStorableSignal Time t Voltage y yv -> IO ()
forall y yv t.
(C y yv, SampleFmt yv, C t) =>
Device
-> Time t -> RenderedStorableSignal Time t Voltage y yv -> IO ()
timeVoltageStorable Device
device Time t
period (T Frequency t
-> (forall s. T s Time t (StorableSignal s Voltage y yv))
-> RenderedStorableSignal Time t Voltage y yv
forall u t amp sig.
C u =>
T (Recip u) t
-> (forall s. T s u t (T (Phantom s) amp sig))
-> T (Dimensional u t) amp sig
SigA.render T Frequency t
rate forall s. T s Time t (StorableSignal s Voltage y yv)
sig)

{-# INLINE renderTimeVoltageMonoStorableToInt16 #-}
renderTimeVoltageMonoStorableToInt16 ::
   (Storable y, RealRing.C y, RealRing.C t) =>
   Device ->
   DN.Time t->
   DN.T Dim.Frequency t ->
   (forall s. Proc.T s Dim.Time t
      (StorableSignal s Dim.Voltage y y)) ->
   IO ()
renderTimeVoltageMonoStorableToInt16 :: Device
-> Time t
-> T Frequency t
-> (forall s. T s Time t (StorableSignal s Voltage y y))
-> IO ()
renderTimeVoltageMonoStorableToInt16 Device
device Time t
period T Frequency t
rate forall s. T s Time t (StorableSignal s Voltage y y)
sig =
   Device
-> Time t -> RenderedStorableSignal Time t Voltage y y -> IO ()
forall y t.
(Storable y, C y, C t) =>
Device
-> Time t -> RenderedStorableSignal Time t Voltage y y -> IO ()
timeVoltageMonoStorableToInt16 Device
device Time t
period (T Frequency t
-> (forall s. T s Time t (StorableSignal s Voltage y y))
-> RenderedStorableSignal Time t Voltage y y
forall u t amp sig.
C u =>
T (Recip u) t
-> (forall s. T s u t (T (Phantom s) amp sig))
-> T (Dimensional u t) amp sig
SigA.render T Frequency t
rate forall s. T s Time t (StorableSignal s Voltage y y)
sig)

{-# INLINE renderTimeVoltageStereoStorableToInt16 #-}
renderTimeVoltageStereoStorableToInt16 ::
   (Storable y, Module.C y y, RealRing.C y, RealRing.C t) =>
   Device ->
   DN.Time t->
   DN.T Dim.Frequency t ->
   (forall s. Proc.T s Dim.Time t
      (StorableSignal s Dim.Voltage y (Stereo.T y))) ->
   IO ()
renderTimeVoltageStereoStorableToInt16 :: Device
-> Time t
-> T Frequency t
-> (forall s. T s Time t (StorableSignal s Voltage y (T y)))
-> IO ()
renderTimeVoltageStereoStorableToInt16 Device
device Time t
period T Frequency t
rate forall s. T s Time t (StorableSignal s Voltage y (T y))
sig =
   Device
-> Time t -> RenderedStorableSignal Time t Voltage y (T y) -> IO ()
forall y t.
(Storable y, C y y, C y, C t) =>
Device
-> Time t -> RenderedStorableSignal Time t Voltage y (T y) -> IO ()
timeVoltageStereoStorableToInt16 Device
device Time t
period (T Frequency t
-> (forall s. T s Time t (StorableSignal s Voltage y (T y)))
-> RenderedStorableSignal Time t Voltage y (T y)
forall u t amp sig.
C u =>
T (Recip u) t
-> (forall s. T s u t (T (Phantom s) amp sig))
-> T (Dimensional u t) amp sig
SigA.render T Frequency t
rate forall s. T s Time t (StorableSignal s Voltage y (T y))
sig)