packages feed

synthesizer-core-0.7.0.1: test/Test/Sound/Synthesizer/Plain/Interpolation.hs

module Test.Sound.Synthesizer.Plain.Interpolation (
   T, ip,
   LinePreserving, lpIp,
   tests,
   use, useLP, use2,
   -- only for debugging
   frequencyModulationBackCompare,
   frequencyModulationForth0Compare,
   frequencyModulationStorableChunkSizeCompare,
   frequencyModulationStorableCompare,
   ) where

import qualified Synthesizer.Plain.Interpolation as Interpolation
import qualified Synthesizer.Interpolation.Class as Interpol
import qualified Synthesizer.Interpolation.Custom as ExampleCustom
import qualified Synthesizer.Interpolation.Module as ExampleModule
import qualified Synthesizer.Interpolation as InterpolationCore

import qualified Synthesizer.Causal.Interpolation as InterpolC
import qualified Synthesizer.Causal.Process as Causal
import qualified Synthesizer.Generic.Filter.NonRecursive as FiltG
import qualified Synthesizer.Generic.Signal as SigG
import qualified Synthesizer.State.Filter.NonRecursive as FiltS
import qualified Synthesizer.State.Signal as SigS

import qualified Synthesizer.Storable.Filter.NonRecursive as FiltSt
import qualified Synthesizer.Storable.Signal as SigSt

import Test.QuickCheck (quickCheck, Arbitrary(arbitrary), elements, {- Property, (==>), -} Testable, )
-- import Test.Utility

import Foreign.Storable (Storable, )

import qualified Algebra.VectorSpace           as VectorSpace
import qualified Algebra.Module                as Module
import qualified Algebra.RealField             as RealField
import qualified Algebra.Field                 as Field
import qualified Algebra.RealRing                  as RealRing
-- import qualified Algebra.Ring                  as Ring
-- import qualified Algebra.Additive              as Additive

import qualified Test.Sound.Synthesizer.Plain.NonEmpty as NonEmpty
import qualified Data.List.Match as Match
import Control.Monad (liftM2, )

import Test.Utility (equalList, ArbChar, unpackArbString, )


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



instance Arbitrary InterpolationCore.Margin where
   arbitrary =
      liftM2 InterpolationCore.Margin
         (fmap abs arbitrary)
         (fmap abs arbitrary)


use ::
   (Interpolation.T a v -> x) ->
   (T a v -> x)
use f ipt =
   f (ip ipt)

useLP ::
   (Interpolation.T a v -> x) ->
   (LinePreserving a v -> x)
useLP f ipt =
   f (lpIp ipt)

use2 ::
   (Interpolation.T a v ->
    Interpolation.T a v -> x) ->
   (T a v ->
    T a v -> x)
use2 f =
   use $ \ ipLeap ->
   use $ \ ipStep ->
      f ipLeap ipStep



data T a v = Cons {name :: String, ip :: Interpolation.T a v}

instance Show (T a v) where
   show x = name x

instance (Field.C a, Interpol.C a v) => Arbitrary (T a v) where
   arbitrary = elements $
      Cons "constant" ExampleCustom.constant :
      Cons "linear"   ExampleCustom.linear :
      Cons "cubic"    ExampleCustom.cubic :
      []



data LinePreserving a v =
   LPCons {lpName :: String, lpIp :: Interpolation.T a v}

instance Show (LinePreserving a v) where
   show x = lpName x

instance (Field.C a, Interpol.C a v) => Arbitrary (LinePreserving a v) where
   arbitrary = elements $
      LPCons "linear"   ExampleCustom.linear :
      LPCons "cubic"    ExampleCustom.cubic :
      []



constant ::
   (Interpol.C a v, Module.C a v, Eq v) =>
   a -> v -> [v] -> Bool
constant t x0 xs =
   equalList $ map ($(x0:xs)) $ map ($t) $
      Interpolation.func ExampleCustom.constant :
      Interpolation.func ExampleCustom.piecewiseConstant :
      Interpolation.func ExampleModule.constant :
      Interpolation.func ExampleModule.piecewiseConstant :
      []

linear ::
   (Interpol.C a v, Module.C a v, Eq v) =>
   a -> v -> v -> [v] -> Bool
linear t x0 x1 xs =
   equalList $ map ($(x0:x1:xs)) $ map ($t) $
      Interpolation.func ExampleCustom.linear :
      Interpolation.func ExampleCustom.piecewiseLinear :
      Interpolation.func ExampleModule.linear :
      Interpolation.func ExampleModule.piecewiseLinear :
      []

cubic ::
   (Interpol.C a v, VectorSpace.C a v, Eq v) =>
   a -> v -> v -> v -> v -> [v] -> Bool
cubic t x0 x1 x2 x3 xs =
   equalList $ map ($(x0:x1:x2:x3:xs)) $ map ($t) $
      Interpolation.func ExampleCustom.cubic :
      Interpolation.func ExampleCustom.piecewiseCubic :
      Interpolation.func ExampleModule.cubic :
      Interpolation.func ExampleModule.cubicAlt :
      Interpolation.func ExampleModule.piecewiseCubic :
      []


controlAboveOne :: (RealRing.C t) => [t] -> [t]
controlAboveOne =
   map ((one+) . abs)

frequencyModulationForth0 ::
   (RealField.C t, Eq v) =>
   [t] -> [v] -> Bool
frequencyModulationForth0 cs0 xs =
   let cs = controlAboveOne cs0
   in  Causal.apply
          (InterpolC.relative ExampleModule.constant zero
             (FiltS.inverseFrequencyModulationFloor
                (SigS.fromList cs) (SigS.fromList xs)))
          (Match.take xs cs)
        == Match.take cs xs

frequencyModulationForth0Compare ::
   (RealField.C t, Eq v) =>
   [t] -> [v] -> ([v], [v], [v])
frequencyModulationForth0Compare cs0 xs =
   let cs = controlAboveOne cs0
   in  (Match.take cs
          (Causal.apply
             (InterpolC.relative ExampleModule.constant zero
                (FiltS.inverseFrequencyModulationFloor
                   (SigS.fromList cs) (SigS.fromList xs)))
             (Match.take xs cs)),
        SigS.toList
           (FiltS.inverseFrequencyModulationFloor
              (SigS.fromList cs) (SigS.fromList xs)),
        Match.take cs xs)


frequencyModulationForth1 ::
   (RealField.C t, Eq v) =>
   [t] -> [v] -> Bool
frequencyModulationForth1 cs0 xs =
   case controlAboveOne cs0 of
      [] -> True
      (c:cs) ->
         Causal.apply
            (InterpolC.relative ExampleModule.constant c
               (FiltS.inverseFrequencyModulationFloor
                  (SigS.fromList ((c+one):cs)) (SigS.fromList xs)))
            (Match.take xs cs)
          == Match.take cs xs



controlBelowOne :: (RealField.C t) => [t] -> [t]
controlBelowOne =
   map fraction


frequencyModulationBack ::
   (RealField.C t, Eq v) =>
   [t] -> NonEmpty.T v -> Bool
frequencyModulationBack cs0 xs0 =
   let cs = controlBelowOne cs0
       xs = NonEmpty.toInfiniteList xs0
   in  take (floor (sum cs)) xs ==
          (SigS.toList $
           FiltS.inverseFrequencyModulationFloor
             (SigS.fromList cs)
             (SigS.fromList $
              Causal.apply
                 (InterpolC.relative ExampleModule.constant zero
                    (SigS.fromList xs))
                 cs))


frequencyModulationBackCompare ::
   (RealField.C t, Eq v) =>
   [t] -> [v] -> (SigS.T v, SigS.T v)
frequencyModulationBackCompare cs0 xs =
   let cs = controlBelowOne cs0
   in  (FiltS.inverseFrequencyModulationFloor
          (SigS.fromList cs)
          (SigS.fromList $
           Causal.apply
              (InterpolC.relative ExampleModule.constant zero
                 (SigS.fromList (cycle xs)))
              cs),
        SigS.fromList $
        Causal.apply
           (InterpolC.relative ExampleModule.constant zero
              (SigS.fromList (cycle xs)))
           cs)

frequencyModulationGeneric ::
   (RealField.C t, Eq v) =>
   [t] -> [v] -> Bool
frequencyModulationGeneric cs xs =
   SigS.toList
      (FiltS.inverseFrequencyModulationFloor
         (SigS.fromList cs) (SigS.fromList xs))
    == FiltG.inverseFrequencyModulationFloor
          SigG.defaultLazySize cs xs


makeChunkSize :: Int -> SigSt.ChunkSize
makeChunkSize size =
   SigSt.chunkSize (1 + abs size)

{-
makeExactFraction :: (Int,Int) -> Double
makeExactFraction (n,d) =
   fromIntegral n * 2 ^- (- mod (fromIntegral d) 4)
-}

frequencyModulationStorableChunkSize ::
   (Storable v, RealField.C t, Eq v) =>
   Int -> Int ->
   Int -> Int ->
   [t] -> [v] ->
   Bool
frequencyModulationStorableChunkSize size0 size1 xsize0 xsize1 cs xs =
   FiltSt.inverseFrequencyModulationFloor
     (makeChunkSize size0) cs
     (SigSt.fromList (makeChunkSize xsize0) xs)
    ==
   FiltSt.inverseFrequencyModulationFloor
     (makeChunkSize size1) cs
     (SigSt.fromList (makeChunkSize xsize1) xs)


frequencyModulationStorableChunkSizeCompare ::
   (Storable v, RealField.C t, Eq v) =>
   Int -> Int ->
   Int -> Int ->
   [t] -> [v] ->
   (SigSt.T v, SigSt.T v)
frequencyModulationStorableChunkSizeCompare size0 size1 xsize0 xsize1 cs xs =
   (FiltSt.inverseFrequencyModulationFloor
      (makeChunkSize size0) cs
      (SigSt.fromList (makeChunkSize xsize0) xs),
    FiltSt.inverseFrequencyModulationFloor
      (makeChunkSize size1) cs
      (SigSt.fromList (makeChunkSize xsize1) xs))


frequencyModulationStorable ::
   (Storable v, RealField.C t, Eq v) =>
   Int -> Int ->
   [t] -> [v] ->
   Bool
frequencyModulationStorable size xsize cs xs =
   SigSt.toList
      (FiltSt.inverseFrequencyModulationFloor (makeChunkSize size) cs
         (SigSt.fromList (makeChunkSize xsize) xs))
    == FiltG.inverseFrequencyModulationFloor
          SigG.defaultLazySize cs xs


frequencyModulationStorableCompare ::
   (Storable v, RealField.C t, Eq v) =>
   Int -> Int ->
   [t] -> [v] ->
   ([v], SigSt.T v)
frequencyModulationStorableCompare size xsize cs xs =
   (FiltG.inverseFrequencyModulationFloor
       SigG.defaultLazySize cs xs,
    FiltSt.inverseFrequencyModulationFloor (makeChunkSize size) cs
       (SigSt.fromList (makeChunkSize xsize) xs))



testRational ::
   (Testable t) =>
   (Rational -> Rational -> t) -> IO ()
testRational = quickCheck

testFM ::
   (Testable t, Arbitrary (sigX ArbChar), Show (sigX ArbChar)) =>
   ([Rational] -> sigX ArbChar -> t) -> IO ()
testFM = quickCheck

tests :: [(String, IO ())]
tests =
   ("constant", testRational constant) :
   ("linear",   testRational linear  ) :
   ("cubic",    testRational cubic   ) :
   ("frequencyModulationForth0",  testFM frequencyModulationForth0) :
   ("frequencyModulationForth1",  testFM frequencyModulationForth1) :
   ("frequencyModulationBack",    testFM frequencyModulationBack) :
   ("frequencyModulationGeneric", testFM frequencyModulationGeneric) :
   ("frequencyModulationStorableChunkSize",
      quickCheck (\size0 size1 xsize0 xsize1 cs xs ->
         frequencyModulationStorableChunkSize size0 size1 xsize0 xsize1
            (cs::[Rational]) (unpackArbString xs))) :
   ("frequencyModulationStorable",
      quickCheck (\size xsize cs xs ->
         frequencyModulationStorable size xsize
            (cs::[Rational]) (unpackArbString xs))) :
   []