{-# OPTIONS_GHC -O2 -fno-implicit-prelude #-} {- | Copyright : (c) Henning Thielemann 2006 License : GPL Maintainer : synthesizer@henning-thielemann.de Stability : provisional Portability : requires multi-parameter type classes Tone generators -} module Synthesizer.FusionList.Oscillator where import qualified Synthesizer.Basic.Wave as Wave import qualified Synthesizer.Basic.Phase as Phase import qualified Synthesizer.FusionList.Signal as Sig -- import qualified Synthesizer.FusionList.Interpolation as Interpolation {- import qualified Algebra.RealTranscendental as RealTrans import qualified Algebra.Module as Module import qualified Algebra.VectorSpace as VectorSpace import Algebra.Module((*>)) -} import qualified Algebra.Transcendental as Trans import qualified Algebra.RealField as RealField -- import qualified Algebra.Field as Field -- import qualified Algebra.Ring as Ring import qualified Algebra.Additive as Additive import NumericPrelude import qualified Prelude as P import PreludeBase {- * Oscillators with arbitrary but constant waveforms -} {-# INLINE freqToPhase #-} {- | Convert a list of phase steps into a list of momentum phases phase is a number in the interval [0,1) freq contains the phase steps -} freqToPhase :: RealField.C a => Phase.T a -> Sig.T a -> Sig.T (Phase.T a) freqToPhase phase freq = Sig.scanL (flip Phase.increment) phase freq {- Inlining blocks fusion of map and iterate - on the other hand it enables fusion in the main program -} {-# INLINE static #-} {- | oscillator with constant frequency -} static :: (RealField.C a) => Wave.T a b -> (Phase.T a -> a -> Sig.T b) static wave phase freq = Sig.map (Wave.apply wave) (Sig.iterate (Phase.increment freq) phase) {-# INLINE phaseMod #-} {- | oscillator with modulated phase -} phaseMod :: (RealField.C a) => Wave.T a b -> a -> Sig.T a -> Sig.T b phaseMod wave = shapeMod (Wave.phaseOffset wave) zero {-# INLINE shapeMod #-} {- | oscillator with modulated shape -} shapeMod :: (RealField.C a) => (c -> Wave.T a b) -> Phase.T a -> a -> Sig.T c -> Sig.T b shapeMod wave phase freq parameters = Sig.zipWith (Wave.apply . wave) parameters (Sig.iterate (Phase.increment freq) phase) {-# INLINE freqMod #-} {- | oscillator with modulated frequency -} freqMod :: (RealField.C a) => Wave.T a b -> Phase.T a -> Sig.T a -> Sig.T b freqMod wave phase freqs = Sig.map (Wave.apply wave) (freqToPhase phase freqs) {-# INLINE phaseFreqMod #-} {- | oscillator with both phase and frequency modulation -} phaseFreqMod :: (RealField.C a) => Wave.T a b -> Sig.T a -> Sig.T a -> Sig.T b phaseFreqMod wave = shapeFreqMod (Wave.phaseOffset wave) zero {-# INLINE shapeFreqMod #-} {- | oscillator with both shape and frequency modulation -} shapeFreqMod :: (RealField.C a) => (c -> Wave.T a b) -> Phase.T a -> Sig.T c -> Sig.T a -> Sig.T b shapeFreqMod wave phase parameters freqs = Sig.zipWith (Wave.apply . wave) parameters (freqToPhase phase freqs) {- {- | oscillator with a sampled waveform with constant frequency This essentially an interpolation with cyclic padding. -} {-# INLINE staticSample #-} staticSample :: RealField.C a => Interpolation.T a b -> Sig.T b -> Phase.T a -> a -> Sig.T b staticSample ip wave phase freq = freqModSample ip wave phase (Sig.repeat freq) {- | oscillator with a sampled waveform with modulated frequency Should behave homogenously for different types of interpolation. -} {-# INLINE freqModSample #-} freqModSample :: RealField.C a => Interpolation.T a b -> Sig.T b -> Phase.T a -> Sig.T a -> Sig.T b freqModSample ip wave phase freqs = let len = Sig.length wave in Interpolation.multiRelativeCyclicPad ip (Phase.toRepresentative $ Phase.multiply len phase) (Sig.map (* fromIntegral len) freqs) wave -} {- * Oscillators with specific waveforms -} {-# INLINE staticSine #-} {- | sine oscillator with static frequency -} staticSine :: (Trans.C a, RealField.C a) => Phase.T a -> a -> Sig.T a staticSine = static Wave.sine {-# INLINE freqModSine #-} {- | sine oscillator with modulated frequency -} freqModSine :: (Trans.C a, RealField.C a) => Phase.T a -> Sig.T a -> Sig.T a freqModSine = freqMod Wave.sine {-# INLINE phaseModSine #-} {- | sine oscillator with modulated phase, useful for FM synthesis -} phaseModSine :: (Trans.C a, RealField.C a) => a -> Sig.T a -> Sig.T a phaseModSine = phaseMod Wave.sine {-# INLINE staticSaw #-} {- | saw tooth oscillator with modulated frequency -} staticSaw :: RealField.C a => Phase.T a -> a -> Sig.T a staticSaw = static Wave.saw {-# INLINE freqModSaw #-} {- | saw tooth oscillator with modulated frequency -} freqModSaw :: RealField.C a => Phase.T a -> Sig.T a -> Sig.T a freqModSaw = freqMod Wave.saw