{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE Rank2Types #-} module Synthesizer.Dimensional.RateAmplitude.File ( write, writeTimeVoltage, writeTimeVoltageMonoDoubleToInt16, writeTimeVoltageStereoDoubleToInt16, renderTimeVoltageMonoDoubleToInt16, renderTimeVoltageStereoDoubleToInt16, ) where import qualified Sound.Sox.Write as Write import qualified Sound.Sox.Option.Format as SoxOpt import qualified Sound.Sox.Frame as Frame import qualified Synthesizer.Basic.Binary as BinSmp import qualified Data.StorableVector.Lazy.Builder as Builder import Foreign.Storable (Storable, ) import qualified Synthesizer.Dimensional.Process as Proc import qualified Synthesizer.Dimensional.Amplitude.Signal as SigA import qualified Synthesizer.Dimensional.RateAmplitude.Signal as SigRA import qualified Synthesizer.Dimensional.RateWrapper as SigP import qualified Synthesizer.Frame.Stereo as Stereo import qualified Synthesizer.Storable.Signal as SigSt -- import qualified Synthesizer.Dimensional.Straight.Signal as SigS import qualified Synthesizer.State.Signal as Sig import qualified Algebra.ToInteger as ToInteger -- import qualified Algebra.Transcendental as Trans import qualified Algebra.Module as Module import qualified Algebra.RealField as RealField import qualified Algebra.Field as Field -- import qualified Algebra.Ring as Ring import qualified Algebra.DimensionTerm as Dim import qualified Number.DimensionTerm as DN import System.Exit(ExitCode) import NumericPrelude import PreludeBase {- | The output format is determined by SoX by the file name extension. The sample precision is determined by the provided 'Builder.Builder' function. Example: > import qualified Data.StorableVector.Lazy.Builder as Builder > > write (DN.frequency one) (DN.voltage one) (\i -> Builder.put (i::Int16)) "test.aiff" sound -} {-# INLINE write #-} write :: (Bounded int, ToInteger.C int, Storable int, Frame.C int, BinSmp.C yv, Dim.C u, RealField.C t, Dim.C v, Module.C y yv, Field.C y) => DN.T (Dim.Recip u) t -> DN.T v y -> (int -> Builder.Builder int) -> FilePath -> SigP.T u t (SigA.S v y) yv -> -- SigP.T u t (SigA.D v y SigS.S) yv -> IO ExitCode write freqUnit amp put name sig = let opts = SoxOpt.numberOfChannels (BinSmp.numberOfSignalChannels sig) sampleRate = DN.divToScalar (SigP.sampleRate sig) freqUnit in Write.extended SigSt.hPut opts SoxOpt.none name (round sampleRate) (Builder.toLazyStorableVector SigSt.defaultChunkSize $ Sig.monoidConcatMap (BinSmp.outputFromCanonical put) $ SigA.vectorSamples (flip DN.divToScalar amp) sig) {-# INLINE writeTimeVoltage #-} writeTimeVoltage :: (Bounded int, ToInteger.C int, Storable int, Frame.C int, BinSmp.C yv, RealField.C t, Module.C y yv, Field.C y) => (int -> Builder.Builder int) -> FilePath -> SigP.T Dim.Time t (SigA.S Dim.Voltage y) yv -> -- SigP.T Dim.Time t (SigA.D Dim.Voltage y SigS.S) yv -> IO ExitCode writeTimeVoltage = write (DN.frequency one) (DN.voltage one) {-# INLINE writeTimeVoltageMonoDoubleToInt16 #-} writeTimeVoltageMonoDoubleToInt16 :: FilePath -> SigP.T Dim.Time Double (SigA.S Dim.Voltage Double) Double -> -- SigP.T Dim.Time t (SigA.D Dim.Voltage y SigS.S) yv -> IO ExitCode writeTimeVoltageMonoDoubleToInt16 name sig = let rate = DN.toNumberWithDimension Dim.frequency (SigP.sampleRate sig) in Write.simple SigSt.hPut SoxOpt.none name (round rate) (SigP.signal (SigRA.toStorableInt16Mono sig)) {-# INLINE writeTimeVoltageStereoDoubleToInt16 #-} writeTimeVoltageStereoDoubleToInt16 :: FilePath -> SigP.T Dim.Time Double (SigA.S Dim.Voltage Double) (Stereo.T Double) -> -- SigP.T Dim.Time t (SigA.D Dim.Voltage y SigS.S) yv -> IO ExitCode writeTimeVoltageStereoDoubleToInt16 name sig = let rate = DN.toNumberWithDimension Dim.frequency (SigP.sampleRate sig) in Write.simple SigSt.hPut SoxOpt.none name (round rate) (SigP.signal (SigRA.toStorableInt16Stereo sig)) {-# INLINE renderTimeVoltageMonoDoubleToInt16 #-} renderTimeVoltageMonoDoubleToInt16 :: DN.T Dim.Frequency Double -> FilePath -> (forall s. Proc.T s Dim.Time Double (SigA.R s Dim.Voltage Double Double)) -> IO ExitCode renderTimeVoltageMonoDoubleToInt16 rate name sig = writeTimeVoltageMonoDoubleToInt16 name (SigP.runProcess rate sig) {-# INLINE renderTimeVoltageStereoDoubleToInt16 #-} renderTimeVoltageStereoDoubleToInt16 :: DN.T Dim.Frequency Double -> FilePath -> (forall s. Proc.T s Dim.Time Double (SigA.R s Dim.Voltage Double (Stereo.T Double))) -> IO ExitCode renderTimeVoltageStereoDoubleToInt16 rate name sig = writeTimeVoltageStereoDoubleToInt16 name (SigP.runProcess rate sig)