synthesizer-0.0.3: src/Synthesizer/Dimensional/Rate/Oscillator.hs
{-# OPTIONS -fno-implicit-prelude #-}
{- |
Copyright : (c) Henning Thielemann 2008
License : GPL
Maintainer : synthesizer@henning-thielemann.de
Stability : provisional
Portability : requires multi-parameter type classes
-}
module Synthesizer.Dimensional.Rate.Oscillator (
{- * Oscillators with constant waveforms -}
static,
staticAntiAlias,
freqMod,
freqModAntiAlias,
phaseMod,
phaseFreqMod,
shapeMod,
shapeFreqMod,
staticSample,
freqModSample,
) where
import qualified Synthesizer.Dimensional.Abstraction.Flat as Flat
import qualified Synthesizer.Dimensional.RatePhantom as RP
import qualified Synthesizer.State.Oscillator as Osci
import qualified Synthesizer.State.Signal as Sig
import qualified Synthesizer.Basic.WaveSmoothed as WaveSmooth
import qualified Synthesizer.Basic.Wave as Wave
import qualified Synthesizer.Basic.Phase as Phase
import qualified Synthesizer.Dimensional.Straight.Signal as SigS
import qualified Synthesizer.Dimensional.Cyclic.Signal as SigC
import qualified Synthesizer.Dimensional.Amplitude.Signal as SigA
import qualified Synthesizer.Dimensional.Process as Proc
import Synthesizer.Dimensional.Process (toFrequencyScalar, )
import qualified Synthesizer.State.Interpolation as Interpolation
import qualified Number.DimensionTerm as DN
import qualified Algebra.DimensionTerm as Dim
-- import Number.DimensionTerm ((&*&))
import qualified Algebra.RealField as RealField
import qualified Algebra.Field as Field
-- import NumericPrelude
import PreludeBase as P
{- * Oscillators with constant waveforms -}
{- | oscillator with a functional waveform with constant frequency -}
{-# INLINE static #-}
static :: (RealField.C t, Dim.C u) =>
Wave.T t y {- ^ waveform -}
-> Phase.T t {- ^ start phase from the range [0,1] -}
-> DN.T (Dim.Recip u) t
{- ^ frequency -}
-> Proc.T s u t (SigS.R s y)
static wave phase =
staticAux (SigS.fromSamples . Osci.static wave phase)
{- | oscillator with a functional waveform with constant frequency -}
{-# INLINE staticAntiAlias #-}
staticAntiAlias :: (RealField.C t, Dim.C u) =>
WaveSmooth.T t y
{- ^ waveform -}
-> Phase.T t {- ^ start phase from the range [0,1] -}
-> DN.T (Dim.Recip u) t
{- ^ frequency -}
-> Proc.T s u t (SigS.R s y)
staticAntiAlias wave phase =
staticAux (SigS.fromSamples . Osci.staticAntiAlias wave phase)
{- | oscillator with a functional waveform with modulated frequency -}
{-# INLINE freqMod #-}
freqMod :: (RealField.C t, Dim.C u) =>
Wave.T t y {- ^ waveform -}
-> Phase.T t {- ^ start phase from the range [0,1] -}
-> Proc.T s u t (
SigA.R s (Dim.Recip u) t t
{- v frequency control -}
-> SigS.R s y)
freqMod wave phase =
freqModAux (SigS.fromSamples . Osci.freqMod wave phase)
{- | oscillator with a functional waveform with modulated frequency -}
{-# INLINE freqModAntiAlias #-}
freqModAntiAlias :: (RealField.C t, Dim.C u) =>
WaveSmooth.T t y
{- ^ waveform -}
-> Phase.T t {- ^ start phase from the range [0,1] -}
-> Proc.T s u t (
SigA.R s (Dim.Recip u) t t
{- v frequency control -}
-> SigS.R s y)
freqModAntiAlias wave phase =
freqModAux (SigS.fromSamples . Osci.freqModAntiAlias wave phase)
{- | oscillator with modulated phase -}
{-# INLINE phaseMod #-}
phaseMod :: (Flat.C flat t, RealField.C t, Dim.C u) =>
Wave.T t y {- ^ waveform -}
-> DN.T (Dim.Recip u) t
{- ^ frequency -}
-> Proc.T s u t (
RP.T s flat t
{- v phase modulation, phases must have no unit and
are from range [0,1] -}
-> SigS.R s y)
phaseMod wave =
staticAux (\freq -> SigS.fromSamples . Osci.phaseMod wave freq . Flat.toSamples)
{- | oscillator with modulated shape -}
{-# INLINE shapeMod #-}
shapeMod :: (Flat.C flat c, RealField.C t, Dim.C u) =>
(c -> Wave.T t y)
{- ^ waveform -}
-> Phase.T t {- ^ phase -}
-> DN.T (Dim.Recip u) t
{- ^ frequency -}
-> Proc.T s u t (
RP.T s flat c {- v shape control -}
-> SigS.R s y)
shapeMod wave phase =
staticAux (\freq -> SigS.fromSamples . Osci.shapeMod wave phase freq . Flat.toSamples)
{- | oscillator with a functional waveform with modulated phase and frequency -}
{-# INLINE phaseFreqMod #-}
phaseFreqMod :: (Flat.C flat t, RealField.C t, Dim.C u) =>
Wave.T t y {- ^ waveform -}
-> Proc.T s u t (
RP.T s flat t
{- v phase control -}
-> SigA.R s (Dim.Recip u) t t
{- v frequency control -}
-> SigS.R s y)
phaseFreqMod wave =
fmap flip $
freqModAux
(\ freqs phases ->
SigS.fromSamples $ Osci.phaseFreqMod wave (Flat.toSamples phases) freqs)
{- | oscillator with both shape and frequency modulation -}
{-# INLINE shapeFreqMod #-}
shapeFreqMod :: (Flat.C flat c, RealField.C t, Dim.C u) =>
(c -> Wave.T t y)
{- ^ waveform -}
-> Phase.T t {- ^ phase -}
-> Proc.T s u t (
RP.T s flat c
{- v shape control -}
-> SigA.R s (Dim.Recip u) t t
{- v frequency control -}
-> SigS.R s y)
shapeFreqMod wave phase =
fmap flip $
freqModAux
(\ freqs parameters ->
SigS.fromSamples $ Osci.shapeFreqMod wave phase (Flat.toSamples parameters) freqs)
{- |
oscillator with a sampled waveform with constant frequency
This is essentially an interpolation with cyclic padding.
-}
{-# INLINE staticSample #-}
staticSample :: (RealField.C t, Dim.C u) =>
Interpolation.T t y
-> SigC.R r y {- ^ waveform -}
-> Phase.T t {- ^ start phase from the range [0,1] -}
-> DN.T (Dim.Recip u) t
{- ^ frequency -}
-> Proc.T s u t (SigS.R s y)
staticSample ip wave phase =
staticAux (SigS.fromSamples . Osci.staticSample ip (SigC.toPeriod wave) phase)
{- |
oscillator with a sampled waveform with modulated frequency
Should behave homogenously for different types of interpolation.
-}
{-# INLINE freqModSample #-}
freqModSample :: (RealField.C t, Dim.C u) =>
Interpolation.T t y
-> SigC.R r y {- ^ waveform -}
-> Phase.T t {- ^ start phase from the range [0,1] -}
-> Proc.T s u t (
SigA.R s (Dim.Recip u) t t
{- v frequency control -}
-> SigS.R s y)
freqModSample ip wave phase =
freqModAux (SigS.fromSamples . Osci.freqModSample ip (SigC.toPeriod wave) phase)
{-# INLINE freqModAux #-}
freqModAux :: (Field.C t, Dim.C u) =>
(Sig.T t -> c)
-> Proc.T s u t (
SigA.R s (Dim.Recip u) t t
-> c)
freqModAux f =
do toFreq <- Proc.withParam toFrequencyScalar
return $ f . SigA.scalarSamples toFreq
{-# INLINE staticAux #-}
staticAux :: (Dim.C u, Field.C t) =>
(t -> c)
-> DN.T (Dim.Recip u) t
-> Proc.T s u t c
staticAux f freq =
fmap f (toFrequencyScalar freq)