{- | ToDo: How to handle dimensional values as control parameters? How to combine control parameters with antialiasing waveforms? Actually, a waveform is like a Map where one parameter is of type Phase.T. A waveform with dimensional control parameter should be treated like a dimensional Map. If we do not use the Map type for waveforms we must at least provide a function for applying a Map to a Wave. I think the oscillators should always provide the frequency to the apply method of a wave. Then the waveform can decide whether it wants to use it or not. We could make a type class for simple and bandlimited waveforms. However, there is a fundamental problem: Distortion of a waveform (wave shaping) can turn bandlimited waveforms into ones without band limits. -} module Synthesizer.Dimensional.Wave.Controlled where import qualified Synthesizer.Basic.Wave as Wave import qualified Synthesizer.Generic.Wave as WaveG import qualified Synthesizer.Generic.Signal as SigG import qualified Synthesizer.Interpolation as Interpolation import qualified Synthesizer.Dimensional.Signal.Private as SigA import qualified Synthesizer.Dimensional.Amplitude as Amp import qualified Synthesizer.Dimensional.Rate as Rate import qualified Algebra.Transcendental as Trans import qualified Algebra.RealField as RealField import qualified Algebra.Ring as Ring import qualified Number.DimensionTerm as DN import qualified Algebra.DimensionTerm as Dim import NumericPrelude import PreludeBase import Prelude () data T amp c t y = Cons { amplitude :: amp, body :: c -> Wave.T t y } {- data T amp body = Cons { amplitude :: amp, body :: body } -} {- | Interpolate first within waves and then across waves, which is simpler but maybe less efficient for lists. However for types with fast indexing/drop like StorableVector this is optimal. -} sampledTone :: (RealField.C t, SigG.Transform sig y, Dim.C u) => Interpolation.T t y -> Interpolation.T t y -> DN.T u t -> SigA.T (Rate.Dimensional u t) amp (sig y) -> T amp t t y sampledTone ipLeap ipStep period tone = Cons (SigA.amplitude tone) $ WaveG.sampledTone ipLeap ipStep (DN.mulToScalar period (SigA.actualSampleRate tone)) (SigA.body tone) {-# INLINE flat #-} flat :: (Ring.C y) => (c -> Wave.T t y) -> T (Amp.Flat y) c t y flat = Cons Amp.Flat {-# INLINE abstract #-} abstract :: (c -> Wave.T t y) -> T Amp.Abstract c t y abstract = Cons Amp.Abstract {-# INLINE amplified #-} amplified :: (Ring.C y, Dim.C u) => DN.T u y -> (c -> Wave.T t y) -> T (Amp.Dimensional u y) c t y amplified = Cons . Amp.Numeric {-# INLINE mapLinear #-} mapLinear :: (Ring.C y, Dim.C u) => y -> DN.T u y -> (c -> Wave.T t y) -> T (Amp.Dimensional u y) c t y mapLinear depth center = amplified center . (Wave.distort (\x -> one+x*depth) .) {-# INLINE mapExponential #-} mapExponential :: (Trans.C y, Dim.C u) => y -> DN.T u y -> (c -> Wave.T t y) -> T (Amp.Dimensional u y) c t y mapExponential depth center = -- amplified center . Wave.distort (depth**) -- should be faster amplified center . let logDepth = log depth in (Wave.distort (exp . (logDepth*)) .)