{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TypeSynonymInstances #-} {- | Copyright : (c) Henning Thielemann 2009 License : GPL Maintainer : synthesizer@henning-thielemann.de Stability : provisional Portability : requires multi-parameter type classes Class similar to "Synthesizer.Dimensional.Abstraction.Homogeneous" but it can be used for different storage types. -} module Synthesizer.Dimensional.Abstraction.HomogeneousGen where import Synthesizer.Dimensional.Amplitude (Flat(Flat)) import qualified Synthesizer.Dimensional.Amplitude as Amp import qualified Synthesizer.State.Signal as Sig import qualified Synthesizer.Storable.Signal as SigSt import qualified Synthesizer.Basic.WaveSmoothed as WaveSmooth import qualified Synthesizer.Basic.Wave as Wave import qualified Synthesizer.Dimensional.RatePhantom as RP import qualified Synthesizer.Dimensional.Straight.Signal as SigS import qualified Synthesizer.Dimensional.Amplitude.Signal as SigA {- import qualified Number.DimensionTerm as DN import qualified Algebra.DimensionTerm as Dim import qualified Algebra.Module as Module import qualified Algebra.Field as Field import qualified Algebra.Ring as Ring -} -- import Number.DimensionTerm ((&/&)) import Data.Tuple.HT (mapSnd, ) -- import NumericPrelude -- import PreludeBase -- import Prelude () {-# INLINE processSamples #-} processSamples :: (C amp storage0 signal0, C amp storage1 signal1) => (storage0 y0 -> storage1 y1) -> RP.T s signal0 y0 -> RP.T s signal1 y1 processSamples f = RP.fromSignal . plainProcessSamples f . RP.toSignal plainProcessSamples :: (C amp storage0 signal0, C amp storage1 signal1) => (storage0 y0 -> storage1 y1) -> (signal0 y0 -> signal1 y1) plainProcessSamples f = plainWrap . mapSnd f . plainUnwrap wrap :: (C amp storage signal) => (amp, storage y) -> RP.T s signal y wrap = RP.fromSignal . plainWrap unwrap :: (C amp storage signal) => RP.T s signal y -> (amp, storage y) unwrap = plainUnwrap . RP.toSignal {- | Functions using this class might define their own class with functional dependencies, that allow to infer automatically, say, that an amplitude input signal requires an amplitude output signal. -} class C amp storage signal | signal -> amp storage where plainWrap :: (amp, storage y) -> signal y plainUnwrap :: signal y -> (amp, storage y) instance C Flat Sig.T Sig.T where plainWrap = snd plainUnwrap = (,) Flat instance C Flat SigSt.T SigSt.T where plainWrap = snd plainUnwrap = (,) Flat instance C Flat sig (SigS.T sig) where plainWrap = SigS.Cons . snd plainUnwrap = (,) Flat . SigS.samples instance (Amp.C amp) => C amp sig (SigA.T amp (SigS.T sig)) where plainWrap = uncurry SigA.Cons . mapSnd SigS.Cons plainUnwrap (SigA.Cons amp sig) = (amp, SigS.samples sig) {- | These instances are used in oscillator where we even do not need homogenity, since values from the waveform go untouched to the output signal. -} instance C Flat (Wave.T t) (Wave.T t) where plainWrap = snd plainUnwrap = (,) Flat instance C Flat (WaveSmooth.T t) (WaveSmooth.T t) where plainWrap = snd plainUnwrap = (,) Flat instance (Amp.C amp) => C amp (Wave.T t) (SigA.T amp (Wave.T t)) where plainWrap = uncurry SigA.Cons plainUnwrap (SigA.Cons amp sig) = (amp, sig) instance (Amp.C amp) => C amp (WaveSmooth.T t) (SigA.T amp (WaveSmooth.T t)) where plainWrap = uncurry SigA.Cons plainUnwrap (SigA.Cons amp sig) = (amp, sig)