{-# LANGUAGE NoImplicitPrelude #-} module Synthesizer.Plain.Play where import qualified Synthesizer.Plain.Builder as Builder import qualified Synthesizer.Basic.Binary as BinSmp import qualified Sound.Sox.Frame as Frame import qualified Sound.Sox.Frame.Stereo as Stereo import qualified Sound.Sox.Option.Format as SoxOpt import qualified Sound.Sox.Play as Play import qualified Sound.Sox.Signal.List as SoxList import Foreign.Storable (Storable, ) import Data.Int (Int16, ) import Data.Monoid (mconcat, ) import System.Exit (ExitCode, ) import qualified Algebra.ToInteger as ToInteger import qualified Algebra.RealRing as RealRing import NumericPrelude.Numeric import NumericPrelude.Base {- | See 'Synthesizer.Plain.File.write'. -} render :: (Storable int, Frame.C int, ToInteger.C int, Bounded int, RealRing.C a, BinSmp.C v) => Builder.Put int -> a -> (a -> [v]) -> IO ExitCode render put sampleRate renderer = auto put sampleRate (renderer sampleRate) renderToInt16 :: (RealRing.C a, BinSmp.C v) => a -> (a -> [v]) -> IO ExitCode renderToInt16 sampleRate renderer = toInt16 sampleRate (renderer sampleRate) renderMonoToInt16 :: (RealRing.C a) => a -> (a -> [a]) -> IO ExitCode renderMonoToInt16 sampleRate renderer = monoToInt16 sampleRate (renderer sampleRate) renderStereoToInt16 :: (RealRing.C a) => a -> (a -> [(a,a)]) -> IO ExitCode renderStereoToInt16 sampleRate renderer = stereoToInt16 sampleRate (renderer sampleRate) {- | See 'Synthesizer.Plain.File.write'. -} auto :: (Storable int, Frame.C int, ToInteger.C int, Bounded int, RealRing.C a, BinSmp.C v) => Builder.Put int -> a -> [v] -> IO ExitCode auto put sampleRate signal = raw (SoxOpt.numberOfChannels (BinSmp.numberOfSignalChannels signal)) sampleRate (Builder.run . mconcat . map (BinSmp.outputFromCanonical put) $ signal) toInt16 :: (RealRing.C a, BinSmp.C v) => a -> [v] -> IO ExitCode toInt16 = auto (Builder.put :: Builder.Put Int16) monoToInt16 :: (RealRing.C a) => a -> [a] -> IO ExitCode monoToInt16 sampleRate signal = raw SoxOpt.none sampleRate (map BinSmp.int16FromCanonical signal) stereoToInt16 :: (RealRing.C a) => a -> [(a,a)] -> IO ExitCode stereoToInt16 sampleRate signal = raw SoxOpt.none sampleRate (map (fmap BinSmp.int16FromCanonical . uncurry Stereo.cons) signal) raw :: (RealRing.C a, Frame.C v, Storable v) => SoxOpt.T -> a -> [v] -> IO ExitCode raw opts sampleRate signal = Play.extended SoxList.put opts SoxOpt.none (round sampleRate) signal exampleMono :: IO ExitCode exampleMono = monoToInt16 (11025::Double) (map sin [0::Double,0.2..]) exampleStereo :: IO ExitCode exampleStereo = stereoToInt16 (11025::Double) $ zip (map sin [0::Double,0.199..]) (map sin [0::Double,0.201..])