{-# LANGUAGE NoImplicitPrelude #-}
{- |
Copyright   :  (c) Henning Thielemann 2006
License     :  GPL

Maintainer  :  synthesizer@henning-thielemann.de
Stability   :  provisional
Portability :  requires multi-parameter type classes

Tone generators

Frequencies are always specified in ratios of the sample rate,
e.g. the frequency 0.01 for the sample rate 44100 Hz
means a physical frequency of 441 Hz.
-}
module Synthesizer.Generic.Oscillator where

import qualified Synthesizer.State.Oscillator as OsciS
import qualified Synthesizer.Causal.Oscillator as OsciC
import qualified Synthesizer.Causal.Process as Causal

import qualified Synthesizer.Basic.Wave       as Wave
import qualified Synthesizer.Basic.Phase      as Phase

import qualified Synthesizer.Causal.Interpolation as Interpolation

import qualified Synthesizer.Generic.Signal  as SigG

import Control.Arrow ((>>>), )

import qualified Algebra.Transcendental        as Trans
import qualified Algebra.RealField             as RealField

import NumericPrelude.Numeric
import NumericPrelude.Base



{- * Oscillators with arbitrary but constant waveforms -}

{- | oscillator with constant frequency -}
static :: (RealField.C a, SigG.Write sig b) =>
   SigG.LazySize ->
   Wave.T a b -> (Phase.T a -> a -> sig b)
static :: forall a (sig :: * -> *) b.
(C a, Write sig b) =>
LazySize -> T a b -> T a -> a -> sig b
static LazySize
size T a b
wave T a
phase a
freq =
   LazySize -> T b -> sig b
forall (sig :: * -> *) y. Write sig y => LazySize -> T y -> sig y
SigG.fromState LazySize
size (T a b -> T a -> a -> T b
forall a b. C a => T a b -> T a -> a -> T b
OsciS.static T a b
wave T a
phase a
freq)

{- | oscillator with modulated frequency -}
freqMod :: (RealField.C a, SigG.Transform sig a, SigG.Transform sig b) =>
   Wave.T a b -> Phase.T a -> sig a -> sig b
freqMod :: forall a (sig :: * -> *) b.
(C a, Transform sig a, Transform sig b) =>
T a b -> T a -> sig a -> sig b
freqMod T a b
wave T a
phase =
   T a b -> sig a -> sig b
forall (sig :: * -> *) a b.
(Transform sig a, Transform sig b) =>
T a b -> sig a -> sig b
Causal.apply (T a b -> T a -> T a b
forall a b. C a => T a b -> T a -> T a b
OsciC.freqMod T a b
wave T a
phase)

{- | oscillator with modulated phase -}
phaseMod :: (RealField.C a, SigG.Transform sig a, SigG.Transform sig b) =>
   Wave.T a b -> a -> sig a -> sig b
phaseMod :: forall a (sig :: * -> *) b.
(C a, Transform sig a, Transform sig b) =>
T a b -> a -> sig a -> sig b
phaseMod T a b
wave =
   (a -> T a b) -> T a -> a -> sig a -> sig b
forall a (sig :: * -> *) c b.
(C a, Transform sig c, Transform sig b) =>
(c -> T a b) -> T a -> a -> sig c -> sig b
shapeMod (T a b -> a -> T a b
forall a b. C a => T a b -> a -> T a b
Wave.phaseOffset T a b
wave) T a
forall a. C a => a
zero

{- | oscillator with modulated shape -}
shapeMod :: (RealField.C a, SigG.Transform sig c, SigG.Transform sig b) =>
   (c -> Wave.T a b) -> Phase.T a -> a -> sig c -> sig b
shapeMod :: forall a (sig :: * -> *) c b.
(C a, Transform sig c, Transform sig b) =>
(c -> T a b) -> T a -> a -> sig c -> sig b
shapeMod c -> T a b
wave T a
phase a
freq =
   T c b -> sig c -> sig b
forall (sig :: * -> *) a b.
(Transform sig a, Transform sig b) =>
T a b -> sig a -> sig b
Causal.apply ((c -> T a b) -> T a -> a -> T c b
forall a c b. C a => (c -> T a b) -> T a -> a -> T c b
OsciC.shapeMod c -> T a b
wave T a
phase a
freq)

{- | oscillator with both phase and frequency modulation -}
phaseFreqMod :: (RealField.C a, SigG.Transform sig a, SigG.Transform sig b) =>
   Wave.T a b -> sig a -> sig a -> sig b
phaseFreqMod :: forall a (sig :: * -> *) b.
(C a, Transform sig a, Transform sig b) =>
T a b -> sig a -> sig a -> sig b
phaseFreqMod T a b
wave =
   (a -> T a b) -> T a -> sig a -> sig a -> sig b
forall a (sig :: * -> *) c b.
(C a, Read sig c, Transform sig a, Transform sig b) =>
(c -> T a b) -> T a -> sig c -> sig a -> sig b
shapeFreqMod (T a b -> a -> T a b
forall a b. C a => T a b -> a -> T a b
Wave.phaseOffset T a b
wave) T a
forall a. C a => a
zero

{- | oscillator with both shape and frequency modulation -}
shapeFreqMod ::
   (RealField.C a,
    SigG.Read sig c, SigG.Transform sig a, SigG.Transform sig b) =>
   (c -> Wave.T a b) -> Phase.T a -> sig c -> sig a -> sig b
shapeFreqMod :: forall a (sig :: * -> *) c b.
(C a, Read sig c, Transform sig a, Transform sig b) =>
(c -> T a b) -> T a -> sig c -> sig a -> sig b
shapeFreqMod c -> T a b
wave T a
phase sig c
parameters =
   T a b -> sig a -> sig b
forall (sig :: * -> *) a b.
(Transform sig a, Transform sig b) =>
T a b -> sig a -> sig b
Causal.apply
      (sig c -> T a (c, a)
forall (sig :: * -> *) a b. Read sig a => sig a -> T b (a, b)
Causal.feedGenericFst sig c
parameters T a (c, a) -> T (c, a) b -> T a b
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>>
       (c -> T a b) -> T a -> T (c, a) b
forall a c b. C a => (c -> T a b) -> T a -> T (c, a) b
OsciC.shapeFreqMod c -> T a b
wave T a
phase)


{- | oscillator with a sampled waveform with constant frequency
This is essentially an interpolation with cyclic padding.
-}
staticSample :: (RealField.C a, SigG.Read wave b, SigG.Write sig b) =>
   SigG.LazySize ->
   Interpolation.T a b -> wave b -> Phase.T a -> a -> sig b
staticSample :: forall a (wave :: * -> *) b (sig :: * -> *).
(C a, Read wave b, Write sig b) =>
LazySize -> T a b -> wave b -> T a -> a -> sig b
staticSample LazySize
size T a b
ip wave b
wave T a
phase a
freq =
   let len :: a
len = Int -> a
forall a b. (C a, C b) => a -> b
fromIntegral (Int -> a) -> Int -> a
forall a b. (a -> b) -> a -> b
$ wave b -> Int
forall sig. Read sig => sig -> Int
SigG.length wave b
wave
   in  LazySize -> T b -> sig b
forall (sig :: * -> *) y. Write sig y => LazySize -> T y -> sig y
SigG.fromState LazySize
size (T b -> sig b) -> T b -> sig b
forall a b. (a -> b) -> a -> b
$
       T a b -> a -> T b -> T a b
forall t y. C t => T t y -> t -> T y -> T t y
Interpolation.relativeCyclicPad
          T a b
ip (a
len a -> a -> a
forall a. C a => a -> a -> a
* T a -> a
forall a. T a -> a
Phase.toRepresentative T a
phase)
          (wave b -> T b
forall y. Storage (wave y) => wave y -> T y
forall (sig :: * -> *) y.
(Read0 sig, Storage (sig y)) =>
sig y -> T y
SigG.toState wave b
wave)
       T a b -> a -> T b
forall a b. T a b -> a -> T b
`Causal.applyConst`
       (a
freq a -> a -> a
forall a. C a => a -> a -> a
* a
len)

{- | oscillator with a sampled waveform with modulated frequency
Should behave homogenously for different types of interpolation.
-}
freqModSample ::
   (RealField.C a,
    SigG.Read wave b, SigG.Transform sig a, SigG.Transform sig b) =>
   Interpolation.T a b -> wave b -> Phase.T a -> sig a -> sig b
freqModSample :: forall a (wave :: * -> *) b (sig :: * -> *).
(C a, Read wave b, Transform sig a, Transform sig b) =>
T a b -> wave b -> T a -> sig a -> sig b
freqModSample T a b
ip wave b
wave T a
phase sig a
freqs =
   let len :: a
len = Int -> a
forall a b. (C a, C b) => a -> b
fromIntegral (Int -> a) -> Int -> a
forall a b. (a -> b) -> a -> b
$ wave b -> Int
forall sig. Read sig => sig -> Int
SigG.length wave b
wave
   in  T a b -> a -> T b -> T a b
forall t y. C t => T t y -> t -> T y -> T t y
Interpolation.relativeCyclicPad
          T a b
ip (a
len a -> a -> a
forall a. C a => a -> a -> a
* T a -> a
forall a. T a -> a
Phase.toRepresentative T a
phase)
          (wave b -> T b
forall y. Storage (wave y) => wave y -> T y
forall (sig :: * -> *) y.
(Read0 sig, Storage (sig y)) =>
sig y -> T y
SigG.toState wave b
wave)
       T a b -> sig a -> sig b
forall (sig :: * -> *) a b.
(Transform sig a, Transform sig b) =>
T a b -> sig a -> sig b
`Causal.apply`
       (a -> a) -> sig a -> sig a
forall y0 y1.
(Storage (sig y0), Storage (sig y1)) =>
(y0 -> y1) -> sig y0 -> sig y1
forall (sig :: * -> *) y0 y1.
(Transform0 sig, Storage (sig y0), Storage (sig y1)) =>
(y0 -> y1) -> sig y0 -> sig y1
SigG.map (a -> a -> a
forall a. C a => a -> a -> a
* a
len) sig a
freqs


{-
Shape+phase modulating oscillators can be found in Causal.Oscillator.
-}

{- * Oscillators with specific waveforms -}

{- | sine oscillator with static frequency -}
staticSine :: (Trans.C a, RealField.C a, SigG.Write sig a) =>
   SigG.LazySize ->
   Phase.T a -> a -> sig a
staticSine :: forall a (sig :: * -> *).
(C a, C a, Write sig a) =>
LazySize -> T a -> a -> sig a
staticSine LazySize
size =
   LazySize -> T a a -> T a -> a -> sig a
forall a (sig :: * -> *) b.
(C a, Write sig b) =>
LazySize -> T a b -> T a -> a -> sig b
static LazySize
size T a a
forall a. C a => T a a
Wave.sine

{- | sine oscillator with modulated frequency -}
freqModSine :: (Trans.C a, RealField.C a, SigG.Transform sig a) =>
   Phase.T a -> sig a -> sig a
freqModSine :: forall a (sig :: * -> *).
(C a, C a, Transform sig a) =>
T a -> sig a -> sig a
freqModSine T a
phase =
   T a a -> sig a -> sig a
forall (sig :: * -> *) a.
Transform sig a =>
T a a -> sig a -> sig a
Causal.applySameType (T a a -> T a -> T a a
forall a b. C a => T a b -> T a -> T a b
OsciC.freqMod T a a
forall a. C a => T a a
Wave.sine T a
phase)

{- | sine oscillator with modulated phase, useful for FM synthesis -}
phaseModSine :: (Trans.C a, RealField.C a, SigG.Transform sig a) =>
   a -> sig a -> sig a
phaseModSine :: forall a (sig :: * -> *).
(C a, C a, Transform sig a) =>
a -> sig a -> sig a
phaseModSine a
freq =
   T a a -> sig a -> sig a
forall (sig :: * -> *) a.
Transform sig a =>
T a a -> sig a -> sig a
Causal.applySameType (T a a -> a -> T a a
forall a b. C a => T a b -> a -> T a b
OsciC.phaseMod T a a
forall a. C a => T a a
Wave.sine a
freq)

{- | saw tooth oscillator with modulated frequency -}
staticSaw :: (RealField.C a, SigG.Write sig a) =>
   SigG.LazySize ->
   Phase.T a -> a -> sig a
staticSaw :: forall a (sig :: * -> *).
(C a, Write sig a) =>
LazySize -> T a -> a -> sig a
staticSaw LazySize
size =
   LazySize -> T a a -> T a -> a -> sig a
forall a (sig :: * -> *) b.
(C a, Write sig b) =>
LazySize -> T a b -> T a -> a -> sig b
static LazySize
size T a a
forall a. C a => T a a
Wave.saw

{- | saw tooth oscillator with modulated frequency -}
freqModSaw :: (RealField.C a, SigG.Transform sig a) =>
   Phase.T a -> sig a -> sig a
freqModSaw :: forall a (sig :: * -> *).
(C a, Transform sig a) =>
T a -> sig a -> sig a
freqModSaw T a
phase =
   T a a -> sig a -> sig a
forall (sig :: * -> *) a.
Transform sig a =>
T a a -> sig a -> sig a
Causal.applySameType (T a a -> T a -> T a a
forall a b. C a => T a b -> T a -> T a b
OsciC.freqMod T a a
forall a. C a => T a a
Wave.saw T a
phase)