synthesizer-0.2: src/Synthesizer/Storable/Oscillator.hs
{-# LANGUAGE NoImplicitPrelude #-}
{- |
Copyright : (c) Henning Thielemann 2006
License : GPL
Maintainer : synthesizer@henning-thielemann.de
Stability : provisional
Portability : requires multi-parameter type classes
Tone generators
-}
module Synthesizer.Storable.Oscillator where
import qualified Synthesizer.Basic.Wave as Wave
import qualified Synthesizer.Basic.Phase as Phase
import qualified Synthesizer.Storable.Signal as Signal
import Synthesizer.Storable.Signal (ChunkSize)
import Foreign.Storable (Storable)
-- import qualified Synthesizer.Plain.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, Storable a) =>
Phase.T a -> Signal.T a -> Signal.T (Phase.T a)
freqToPhase phase freq = Signal.scanL (flip Phase.increment) phase freq
{-# INLINE static #-}
{-# SPECULATE static :: Storable b => ChunkSize -> (Double -> b) -> (Double -> Double -> Signal.T b) #-}
{- | oscillator with constant frequency -}
static :: (RealField.C a, Storable a, Storable b) =>
ChunkSize -> Wave.T a b -> (Phase.T a -> a -> Signal.T b)
static size wave phase freq =
Signal.map (Wave.apply wave) (Signal.iterate size (Phase.increment freq) phase)
{- | oscillator with modulated phase -}
phaseMod :: (RealField.C a, Storable a, Storable b) =>
ChunkSize -> Wave.T a b -> a -> Signal.T a -> Signal.T b
phaseMod size wave = shapeMod size (Wave.phaseOffset wave) zero
{-# ONLINE shapeMod #-}
{- | oscillator with modulated shape -}
shapeMod :: (RealField.C a, Storable a, Storable b, Storable c) =>
ChunkSize -> (c -> Wave.T a b) -> Phase.T a -> a -> Signal.T c -> Signal.T b
shapeMod size wave phase freq parameters =
Signal.zipWith (Wave.apply . wave) parameters
(Signal.iterate size (Phase.increment freq) phase)
{- | oscillator with modulated frequency -}
freqMod :: (RealField.C a, Storable a, Storable b) =>
ChunkSize -> Wave.T a b -> Phase.T a -> Signal.T a -> Signal.T b
freqMod _size wave phase freqs =
Signal.map (Wave.apply wave) (freqToPhase phase freqs)
{- | oscillator with both phase and frequency modulation -}
phaseFreqMod :: (RealField.C a, Storable a, Storable b) =>
ChunkSize -> Wave.T a b -> Signal.T a -> Signal.T a -> Signal.T b
phaseFreqMod size wave =
shapeFreqMod size (Wave.phaseOffset wave) zero
{- | oscillator with both shape and frequency modulation -}
shapeFreqMod :: (RealField.C a, Storable a, Storable b, Storable c) =>
ChunkSize -> (c -> Wave.T a b) ->
Phase.T a -> Signal.T c -> Signal.T a -> Signal.T b
shapeFreqMod _size wave phase parameters freqs =
Signal.zipWith (Wave.apply . wave) parameters (freqToPhase phase freqs)
{-
{- | oscillator with a sampled waveform with constant frequency
This essentially an interpolation with cyclic padding. -}
staticSample :: RealField.C a => Interpolation.T a b -> Signal.T b -> a -> a -> Signal.T b
staticSample ip wave phase freq =
freqModSample ip wave phase (repeat freq)
{- | oscillator with a sampled waveform with modulated frequency
Should behave homogenously for different types of interpolation. -}
freqModSample :: RealField.C a => Interpolation.T a b -> Signal.T b -> a -> Signal.T a -> Signal.T b
freqModSample ip wave phase freqs =
let len = fromIntegral (length wave)
in Interpolation.multiRelativeCyclicPad
ip (phase*len) (Signal.map (*len) freqs) wave
-}
{- * Oscillators with specific waveforms -}
{-# INLINE staticSine #-}
{-# SPECULATE staticSine :: ChunkSize -> Double -> Double -> Signal.T Double #-}
{- | sine oscillator with static frequency -}
staticSine :: (Trans.C a, RealField.C a, Storable a) =>
ChunkSize -> Phase.T a -> a -> Signal.T a
staticSine size = static size Wave.sine
{-# INLINE freqModSine #-}
{-# SPECULATE freqModSine :: ChunkSize -> Double -> Signal.T Double -> Signal.T Double #-}
{- | sine oscillator with modulated frequency -}
freqModSine :: (Trans.C a, RealField.C a, Storable a) =>
ChunkSize -> Phase.T a -> Signal.T a -> Signal.T a
freqModSine size = freqMod size Wave.sine
{-# INLINE phaseModSine #-}
{-# SPECULATE phaseModSine :: ChunkSize -> Double -> Signal.T Double -> Signal.T Double #-}
{- | sine oscillator with modulated phase, useful for FM synthesis -}
phaseModSine :: (Trans.C a, RealField.C a, Storable a) =>
ChunkSize -> a -> Signal.T a -> Signal.T a
phaseModSine size = phaseMod size Wave.sine
{-# INLINE staticSaw #-}
{-# SPECULATE staticSaw :: ChunkSize -> Double -> Double -> Signal.T Double #-}
{- | saw tooth oscillator with modulated frequency -}
staticSaw :: (RealField.C a, Storable a) =>
ChunkSize -> Phase.T a -> a -> Signal.T a
staticSaw size = static size Wave.saw
{-# INLINE freqModSaw #-}
{-# SPECULATE freqModSaw :: ChunkSize -> Double -> Signal.T Double -> Signal.T Double #-}
{- | saw tooth oscillator with modulated frequency -}
freqModSaw :: (RealField.C a, Storable a) =>
ChunkSize -> Phase.T a -> Signal.T a -> Signal.T a
freqModSaw size = freqMod size Wave.saw
{- Test whether Fusion takes place.
For the following code the simplifier can't resist!
testLength :: (Storable a, Enum a) => a -> Int
testLength x =
Signal.length (Signal.map succ (Signal.fromList (Signal.ChunkSize 100) [x,x,x]))
-}