packages feed

synthesizer-inference-0.2: src/Synthesizer/Inference/Monad/Signal/Oscillator.hs

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

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

-}
module Synthesizer.Inference.Monad.Signal.Oscillator (
   {- * Oscillators with constant waveforms -}
   static,
   freqMod,
   phaseMod,
   phaseFreqMod,
) where


import qualified UniqueLogicNP.Explicit.Process    as Process
import qualified UniqueLogicNP.Explicit.Expression as Expr
import qualified UniqueLogicNP.Explicit.System     as IS
import qualified Synthesizer.Inference.Monad.Signal     as SigI

import Synthesizer.Inference.Monad.Signal (toFrequencyScalar)

import qualified Synthesizer.Physical.Signal as SigP
import qualified Synthesizer.Plain.Oscillator as Osci
import qualified Synthesizer.Basic.Wave       as Wave

import qualified Algebra.OccasionallyScalar as OccScalar
import qualified Algebra.RealField          as RealField
import qualified Algebra.Field              as Field

import Control.Monad.Fix (mfix)

-- import NumericPrelude
import PreludeBase as P


{- * Oscillators with constant waveforms -}

{- | oscillator with a functional waveform with constant frequency -}
static :: (RealField.C a, Field.C q, OccScalar.C a q) =>
      Wave.T a v  {- ^ waveform -}
   -> q           {- ^ amplitude -}
   -> a           {- ^ start phase from the range [0,1] -}
   -> q           {- ^ frequency -}
   -> SigI.Process a q v
static wave amplitude phase freq =
   mfix (\z ->
      do sampleRate <- Process.newVariable
         f <- toFrequencyScalar z (Expr.constant freq)
         SigI.returnCons sampleRate (IS.constant amplitude)
            (Osci.static wave phase f))

{- | oscillator with a functional waveform with modulated frequency -}
freqMod :: (RealField.C a, Field.C q, OccScalar.C a q) =>
      Wave.T a v   {- ^ waveform -}
   -> q            {- ^ amplitude -}
   -> a            {- ^ start phase from the range [0,1] -}
   -> SigI.T a q a {- ^ frequency control -}
   -> SigI.Process a q v
freqMod wave amplitude phase xs =
   do freqs <- SigI.scalarSamples (toFrequencyScalar xs) xs
      SigI.returnCons
         (SigP.sampleRate xs) (IS.constant amplitude)
         (Osci.freqMod wave phase freqs)

{- | oscillator with modulated phase -}
phaseMod :: (RealField.C a, Field.C q, OccScalar.C a q) =>
      Wave.T a v   {- ^ waveform -}
   -> q            {- ^ amplitude -}
   -> q            {- ^ frequency control -}
   -> SigI.T a q a {- ^ phase modulation, phases must have no unit and
                        are from range [0,1] -}
   -> SigI.Process a q v
phaseMod wave amplitude freq xs =
   do freqFac <- toFrequencyScalar xs (Expr.constant freq)
      phases  <- SigI.scalarSamples (Process.exprToScalar) xs
      SigI.returnCons
         (SigP.sampleRate xs) (IS.constant amplitude)
         (Osci.phaseMod wave freqFac phases)

{- | oscillator with a functional waveform with modulated phase and frequency -}
phaseFreqMod :: (RealField.C a, Field.C q, Eq q, OccScalar.C a q) =>
      Wave.T a v   {- ^ waveform -}
   -> q            {- ^ amplitude -}
   -> SigI.T a q a {- ^ phase control -}
   -> SigI.T a q a {- ^ frequency control -}
   -> SigI.Process a q v
phaseFreqMod wave amplitude xs ys =
   do phases <- SigI.scalarSamples (Process.exprToScalar) xs
      freqs  <- SigI.scalarSamples (toFrequencyScalar ys) ys
      sampleRate <- Process.equalValues
                       [SigP.sampleRate xs, SigP.sampleRate ys]
      SigI.returnCons
         sampleRate (IS.constant amplitude)
         (Osci.phaseFreqMod wave phases freqs)