module Synthesizer.Generic.Wave where

import qualified Synthesizer.State.ToneModulation as ToneMod
import qualified Synthesizer.Basic.Wave as Wave

import qualified Synthesizer.Generic.Signal as SigG

import qualified Synthesizer.Interpolation as Interpolation

import qualified Algebra.RealField            as RealField
import qualified Algebra.RealRing             as RealRing

import NumericPrelude.Numeric
import NumericPrelude.Base
import Prelude ()


sample ::
   (RealRing.C a, SigG.Transform sig v) =>
   Interpolation.T a v -> sig v -> Wave.T a v
sample ip wave =
   let len = SigG.length wave
       cycleWave = SigG.cycle wave
   in  Wave.fromFunction $ \ phase ->
           let (n,q) = RealRing.splitFraction (phase * fromIntegral len)
           in  Interpolation.func ip q $
               SigG.toState $
               SigG.drop n cycleWave


{- |
Interpolate first within waves and then across waves,
which is simpler but maybe less efficient for lists.
However for types with fast indexing/drop like StorableVector this is optimal.
-}
sampledTone ::
   (RealField.C a, SigG.Transform sig v) =>
   Interpolation.T a v ->
   Interpolation.T a v ->
   a -> sig v -> a -> Wave.T a v
sampledTone ipLeap ipStep period tone shape = Wave.Cons $ \phase ->
--   uncurry (ToneMod.interpolateCell ipStep ipLeap . swap) $
   uncurry (ToneMod.interpolateCell ipLeap ipStep) $
   ToneMod.sampledToneCell
      (ToneMod.makePrototype
          (Interpolation.margin ipLeap) (Interpolation.margin ipStep)
          period tone)
      shape phase