module Synthesizer.Plain.Builder (
   T, Put, put, run,
   signalToBinary, signalToBinaryMono, signalToBinaryStereo,
   ) where

import qualified Synthesizer.Basic.Binary as BinSmp

import Data.Monoid (Monoid, mempty, mappend, mconcat, Endo(Endo), appEndo, )
import Data.Semigroup (Semigroup, (<>), )

import qualified Algebra.FloatingPoint as Float
import qualified Algebra.ToInteger as ToInteger

import NumericPrelude.Numeric
import NumericPrelude.Base
import Prelude ()



newtype T a = Cons {forall a. T a -> Endo [a]
decons :: Endo [a]}

type Put a = a -> T a


instance Semigroup (T a) where
   T a
x <> :: T a -> T a -> T a
<> T a
y = Endo [a] -> T a
forall a. Endo [a] -> T a
Cons (Endo [a] -> T a) -> Endo [a] -> T a
forall a b. (a -> b) -> a -> b
$ T a -> Endo [a]
forall a. T a -> Endo [a]
decons T a
x Endo [a] -> Endo [a] -> Endo [a]
forall a. Semigroup a => a -> a -> a
<> T a -> Endo [a]
forall a. T a -> Endo [a]
decons T a
y

instance Monoid (T a) where
   mempty :: T a
mempty = Endo [a] -> T a
forall a. Endo [a] -> T a
Cons Endo [a]
forall a. Monoid a => a
mempty
   mappend :: T a -> T a -> T a
mappend = T a -> T a -> T a
forall a. Semigroup a => a -> a -> a
(<>)

put :: Put a
put :: forall a. Put a
put = Endo [a] -> T a
forall a. Endo [a] -> T a
Cons (Endo [a] -> T a) -> (a -> Endo [a]) -> a -> T a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([a] -> [a]) -> Endo [a]
forall a. (a -> a) -> Endo a
Endo (([a] -> [a]) -> Endo [a]) -> (a -> [a] -> [a]) -> a -> Endo [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (:)

run :: T a -> [a]
run :: forall a. T a -> [a]
run = (Endo [a] -> [a] -> [a]) -> [a] -> Endo [a] -> [a]
forall a b c. (a -> b -> c) -> b -> a -> c
flip Endo [a] -> [a] -> [a]
forall a. Endo a -> a -> a
appEndo [] (Endo [a] -> [a]) -> (T a -> Endo [a]) -> T a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. T a -> Endo [a]
forall a. T a -> Endo [a]
decons


{-# INLINE signalToBinary #-}
signalToBinary ::
   (BinSmp.C v, ToInteger.C int, Bounded int) =>
   [v] -> [int]
signalToBinary :: forall v int. (C v, C int, Bounded int) => [v] -> [int]
signalToBinary =
   T int -> [int]
forall a. T a -> [a]
run (T int -> [int]) -> ([v] -> T int) -> [v] -> [int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [T int] -> T int
forall a. Monoid a => [a] -> a
mconcat ([T int] -> T int) -> ([v] -> [T int]) -> [v] -> T int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (v -> T int) -> [v] -> [T int]
forall a b. (a -> b) -> [a] -> [b]
map ((int -> T int) -> v -> T int
forall a int out.
(C a, Bounded int, C int, Monoid out) =>
(int -> out) -> a -> out
forall int out.
(Bounded int, C int, Monoid out) =>
(int -> out) -> v -> out
BinSmp.outputFromCanonical int -> T int
forall a. Put a
put)

{-# INLINE signalToBinaryMono #-}
signalToBinaryMono ::
   (Float.C a, ToInteger.C int, Bounded int) =>
   [a] -> [int]
signalToBinaryMono :: forall a int. (C a, C int, Bounded int) => [a] -> [int]
signalToBinaryMono =
   (a -> int) -> [a] -> [int]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> int) -> a -> int
forall real int.
(C real, Bounded int, C int) =>
(real -> int) -> real -> int
BinSmp.fromCanonicalWith a -> int
forall b. C b => a -> b
forall a b. (C a, C b) => a -> b
round)

{-# INLINE signalToBinaryStereo #-}
signalToBinaryStereo ::
   (Float.C a, ToInteger.C int, Bounded int) =>
   [(a,a)] -> [int]
signalToBinaryStereo :: forall a int. (C a, C int, Bounded int) => [(a, a)] -> [int]
signalToBinaryStereo =
   ((a, a) -> [int]) -> [(a, a)] -> [int]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\(a
l,a
r) ->
      [(a -> int) -> a -> int
forall real int.
(C real, Bounded int, C int) =>
(real -> int) -> real -> int
BinSmp.fromCanonicalWith a -> int
forall b. C b => a -> b
forall a b. (C a, C b) => a -> b
round a
l,
       (a -> int) -> a -> int
forall real int.
(C real, Bounded int, C int) =>
(real -> int) -> real -> int
BinSmp.fromCanonicalWith a -> int
forall b. C b => a -> b
forall a b. (C a, C b) => a -> b
round a
r])