packages feed

synthesizer-core 0.8.0.2 → 0.8.1

raw patch · 23 files changed

+397/−920 lines, 23 filesdep ~directory

Dependency ranges changed: directory

Files

+ Changes.md view
@@ -0,0 +1,11 @@+# Change log for the `synthesizer-core` package++## 8.1++* `Plain.Filter.Recursive.FirstOrder.highpassInit`,+  `Plain.Filter.Recursive.FirstOrder.highpassModifierInit`+  and derived functions change the meaning of the initial parameter.+  The previous meaning was pretty unclear and useless+  such that I consider it a bug.+  We do no longer negate the initial value.+  This is consistent with `lowpassInit`.
private/Synthesizer/Basic/NumberTheory.hs view
@@ -115,6 +115,7 @@    primitiveRootsOfUnityFullOrbitTest,    maximumOrderOfPrimitiveRootsOfUnityNaive,    maximumOrderOfPrimitiveRootsOfUnityInteger,+   divideByMaximumPowerRecursive,    numbers3SmoothCorec,    numbers3SmoothFoldr,    numbers3SmoothSet,@@ -759,11 +760,11 @@    last $    n : unfoldr (\m -> case divMod m b of (q,r) -> toMaybe (isZero r) (q,q)) n -_divideByMaximumPowerRecursive ::+divideByMaximumPowerRecursive ::    (Integral.C a, Eq a, ZeroTestable.C a) => a -> a -> a-_divideByMaximumPowerRecursive b =+divideByMaximumPowerRecursive b =    let recourse n =-          case divMod b n of+          case divMod n b of              (q,0) -> recourse q              _ -> n    in  recourse
speedtest/SpeedTestExp.hs view
@@ -105,6 +105,7 @@    withBinaryFile name WriteMode $ \h ->    newArray_ (0,2*num-1) >>= \arr ->       let k = 0.5**(1/hl)+          loop :: Int -> Double -> IO ()           loop i y =              if i<num                then writeArray (arr :: IOUArray Int Int16)
src/Synthesizer/Basic/Distortion.hs view
@@ -11,12 +11,14 @@    zigZag, sine,    oddChebyshev, {- swing, -}    quantize,+   powerSigned,    ) where  import qualified Algebra.Transcendental        as Trans import qualified Algebra.RealField             as RealField import qualified Algebra.Field                 as Field import qualified Algebra.RealRing              as RealRing+import qualified Algebra.Absolute              as Absolute import qualified Algebra.Ring                  as Ring  import Data.List.HT (mapAdjacent, )@@ -142,3 +144,14 @@  quantize :: (RealField.C a) => a -> a quantize x = fromIntegral (round x :: Int)+++{- * other -}++{- |+Power function.+Roughly the map @\p x -> x**p@ but retains the sign of @x@.+-}+{-# INLINE powerSigned #-}+powerSigned :: (Absolute.C a, Trans.C a) => a -> a -> a+powerSigned p x = signum x * abs x ** p
src/Synthesizer/Basic/Wave.hs view
@@ -51,6 +51,7 @@    truncCosine,    truncTriangle,    powerNormed,+   powerNormed2,    logitSaw,    logitSine,    sineSquare,@@ -78,6 +79,7 @@    ) where  import qualified Synthesizer.Basic.Phase as Phase+import qualified Synthesizer.Basic.Distortion as Distort  import qualified Algebra.RealTranscendental    as RealTrans import qualified Algebra.Transcendental        as Trans@@ -590,19 +592,20 @@ The sign is flipped with respect to 'saw' and 'sine' which is an historical artifact. -}+{-# DEPRECATED powerNormed "Use powerNormed2 instead." #-} {-# INLINE powerNormed #-} powerNormed :: (Absolute.C a, Trans.C a) => a -> T a a-powerNormed p = distort (negate . power01Normed p) saw---- | auxiliary-{-# INLINE power01Normed #-}-power01Normed :: (Absolute.C a, Trans.C a) => a -> a -> a-power01Normed p x = (p+0.5) * powerSigned p x+powerNormed p = amplify (-p-0.5) $ distort (Distort.powerSigned p) saw --- | auxiliary-{-# INLINE powerSigned #-}-powerSigned :: (Absolute.C a, Trans.C a) => a -> a -> a-powerSigned p x = signum x * abs x ** p+{- |+Power function.+Roughly the map @\p x -> x**p@+but retains the sign of @x@ and+normalizes the mapping over @[0,1]@ to an L2 norm of 1.+-}+{-# INLINE powerNormed2 #-}+powerNormed2 :: (Absolute.C a, Trans.C a) => a -> T a a+powerNormed2 p = amplify (sqrt (1+2*p)) $ distort (Distort.powerSigned p) saw   {- |@@ -633,7 +636,7 @@       a {- ^ 0 for 'sine', 1 for 'square' -}    -> T a a sineSquare c =-   distort (powerSigned (1-c)) sine+   distort (Distort.powerSigned (1-c)) sine   
src/Synthesizer/Generic/Filter/NonRecursive.hs view
@@ -392,8 +392,7 @@    (Additive.C v, SigG.Write sig v) =>    Int -> sig v -> ([Int], [sig v]) pyramid height sig =-   let sizes =-          reverse $ take (1+height) $ iterate (2*) 1+   let sizes = reverse $ take (1+height) $ iterate (2*) 1    in  (sizes,         scanl (flip sumsDownsample2) sig (map SigG.LazySize $ tail sizes)) @@ -508,11 +507,8 @@    sig (Int,Int) -> sig v accumulatePosModulatedFromPyramid accumulate (sizes,pyr0) ctrl =    let blockSize = head sizes-       pyrStarts =-          iterate (zipWith SigG.drop sizes) pyr0-       ctrlBlocks =-          SigS.toList $-          SigG.sliceVertical blockSize ctrl+       pyrStarts = iterate (zipWith SigG.drop sizes) pyr0+       ctrlBlocks = SigS.toList $ SigG.sliceVertical blockSize ctrl    in  SigG.concat $        zipWith           (\pyr ->@@ -561,8 +557,7 @@   inverseFrequencyModulationFloor ::-   (Ord t, Ring.C t,-    SigG.Write sig v, SigG.Read sig t) =>+   (Ord t, Ring.C t, SigG.Write sig v, SigG.Read sig t) =>    SigG.LazySize ->    sig t -> sig v -> sig v inverseFrequencyModulationFloor chunkSize ctrl xs =
src/Synthesizer/Generic/Filter/Recursive/MovingAverage.hs view
@@ -155,7 +155,7 @@ -} {-# INLINE sumsModulatedHalf #-} sumsModulatedHalf ::-   (RealField.C a, Module.C a v, SigG.Transform sig a, SigG.Transform sig v, SigG.Write sig v) =>+   (RealField.C a, Module.C a v, SigG.Transform sig a, SigG.Write sig v) =>    Int -> sig a -> sig v -> sig v sumsModulatedHalf maxDInt ds xs =    let maxD  = fromIntegral maxDInt@@ -167,7 +167,7 @@  {-# INLINE modulatedFrac #-} modulatedFrac ::-   (RealField.C a, Module.C a v, SigG.Transform sig a, SigG.Transform sig v, SigG.Write sig v) =>+   (RealField.C a, Module.C a v, SigG.Transform sig a, SigG.Write sig v) =>    Int -> sig a -> sig v -> sig v modulatedFrac maxDInt ds xs =    SigG.zipWith (\d y -> recip (2*d) *> y) ds $
src/Synthesizer/Generic/Fourier.hs view
@@ -681,7 +681,7 @@ -} {- suffers from big inefficiency of repeated 'append'    SigG.takeStateMatch sig $-   SigS.monoidConcat $+   SigS.fold $    SigS.map (SigS.take (fromIntegral n) . powers sig) $    SigS.take (fromIntegral m) $ -- necessary for strict storable vectors    powers sig z@@ -706,7 +706,7 @@        Permutation.apply transposeNM . --       concatRechunk sig .        SigG.zipWith (*) twiddle .-       SigS.monoidConcat .+       SigS.fold .        SigS.map (transformWithCache subCacheN) .        SigG.sliceVertical (fromInteger n) .        Permutation.apply transposeMN $@@ -786,7 +786,7 @@ concatRechunk pattern =    SigG.takeStateMatch pattern .    SigG.toState .-   SigS.monoidConcat+   SigS.fold   data LevelPrime =
src/Synthesizer/Generic/Oscillator.hs view
@@ -71,7 +71,8 @@  {- | oscillator with both shape and frequency modulation -} shapeFreqMod ::-   (RealField.C a, SigG.Read sig c, SigG.Transform sig a, SigG.Transform sig b) =>+   (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 wave phase parameters =    Causal.apply@@ -97,7 +98,9 @@ {- | 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) =>+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 ip wave phase freqs =    let len = fromIntegral $ SigG.length wave
src/Synthesizer/Generic/Signal.hs view
@@ -798,10 +798,15 @@       (foldL (Additive.+)) -} ++{-# INLINE foldMap #-}+foldMap :: (Read sig a, Monoid m) => (a -> m) -> sig a -> m+foldMap f = foldR (mappend . f) mempty++{-# DEPRECATED monoidConcatMap "Use foldMap instead." #-} {-# INLINE monoidConcatMap #-} monoidConcatMap :: (Read sig a, Monoid m) => (a -> m) -> sig a -> m-monoidConcatMap f =-   foldR (mappend . f) mempty+monoidConcatMap = foldMap   {-# INLINE tails #-}
+ src/Synthesizer/PiecewiseConstant/Generic.hs view
@@ -0,0 +1,44 @@+module Synthesizer.PiecewiseConstant.Generic (+   toSignal,+   toSignalInit,+   toSignalInitWith,+   ) where++import qualified Synthesizer.PiecewiseConstant.Private as PC+import Synthesizer.PiecewiseConstant.Private (StrictTime)++import qualified Synthesizer.Generic.Signal as SigG+import qualified Synthesizer.Generic.Cut    as CutG++import qualified Data.EventList.Relative.BodyTime as EventListBT+import qualified Data.EventList.Relative.TimeBody as EventList++import qualified Numeric.NonNegative.Wrapper as NonNegW++++replicateLong ::+   (SigG.Write sig y) =>+   StrictTime -> y -> sig y+replicateLong tl y =+   CutG.concat $+   map (\t ->+      SigG.replicate+--         (SigG.LazySize $ fromIntegral $ maxBound::Int)+         SigG.defaultLazySize+         (NonNegW.toNumber t) y) $+   PC.chopLongTime tl++{-# INLINE toSignal #-}+toSignal :: (SigG.Write sig y) => EventListBT.T StrictTime y -> sig y+toSignal = PC.toSignal replicateLong++{-# INLINE toSignalInit #-}+toSignalInit :: (SigG.Write sig y) => y -> EventList.T StrictTime y -> sig y+toSignalInit = PC.toSignalInit replicateLong++{-# INLINE toSignalInitWith #-}+toSignalInitWith ::+   (SigG.Write sig c) =>+   (y -> c) -> c -> EventList.T StrictTime [y] -> sig c+toSignalInitWith = PC.toSignalInitWith replicateLong
+ src/Synthesizer/PiecewiseConstant/Private.hs view
@@ -0,0 +1,75 @@+module Synthesizer.PiecewiseConstant.Private where++import qualified Synthesizer.Generic.Signal as SigG++import qualified Data.EventList.Relative.BodyTime  as EventListBT+import qualified Data.EventList.Relative.TimeBody  as EventList++import qualified Numeric.NonNegative.Wrapper as NonNegW++import Control.Monad.Trans.State (evalState, get, put, )++import qualified Data.List as List+import Data.Traversable (traverse, )+import Data.Foldable (traverse_, )++++type StrictTime = NonNegW.Integer+type ShortStrictTime = NonNegW.Int+++{-# INLINE toSignal #-}+toSignal ::+   (SigG.Transform sig y) =>+   (StrictTime -> y -> sig y) ->+   EventListBT.T StrictTime y -> sig y+toSignal replicateLong =+   EventListBT.foldrPair+      (\y t -> SigG.append (replicateLong t y))+      SigG.empty++{-# INLINE toSignalInit #-}+toSignalInit ::+   (SigG.Transform sig y) =>+   (StrictTime -> y -> sig y) ->+   y -> EventList.T StrictTime y -> sig y+toSignalInit replicateLong initial =+   (\ ~(t,rest) -> SigG.append (replicateLong t initial) rest)+   .+   EventList.foldr+      (,)+      (\y ~(t,rest) -> SigG.append (replicateLong t y) rest)+      (0, SigG.empty)+{-+   toSignal .+--   EventListBM.switchBodyR const .+--   EventListBM.snocTime NonNeg.zero .+--   EventListMB.consBody initial .+   -- switchBodyR causes a space leak+   EventListTM.switchBodyR EventListBT.empty+      (\xs _ -> EventListMT.consBody initial xs)+-}++{-# INLINE toSignalInitWith #-}+toSignalInitWith ::+   (SigG.Transform sig c) =>+   (StrictTime -> c -> sig c) ->+   (y -> c) -> c -> EventList.T StrictTime [y] -> sig c+toSignalInitWith replicateLong f initial =+   toSignalInit replicateLong initial .+   flip evalState initial .+   traverse (\evs -> traverse_ (put . f) evs >> get)+++{- |+Returns a list of non-zero times.+-}+{-# INLINE chopLongTime #-}+chopLongTime :: StrictTime -> [ShortStrictTime]+chopLongTime n =+   let d = fromIntegral (maxBound :: Int)+       (q,r) = divMod (NonNegW.toNumber n) d+   in  map (NonNegW.fromNumberMsg "chopLongTime" . fromInteger) $+       List.genericReplicate q d +++       if r/=0 then [r] else []
src/Synthesizer/PiecewiseConstant/Signal.hs view
@@ -12,6 +12,9 @@    zipWith,    ) where +import Synthesizer.PiecewiseConstant.Private+         (StrictTime, ShortStrictTime, chopLongTime)+ import qualified Data.EventList.Relative.TimeTime  as EventListTT import qualified Data.EventList.Relative.MixedTime as EventListMT import qualified Data.EventList.Relative.BodyTime  as EventListBT@@ -32,8 +35,6 @@ import qualified Prelude as P  -type StrictTime = NonNegW.Integer-type ShortStrictTime = NonNegW.Int type LazyTime = NonNegChunky.T StrictTime  type T = EventListBT.T StrictTime@@ -67,18 +68,6 @@       (NonNegChunky.fromChunks .        List.concatMap chopLongTime .        NonNegChunky.toChunks)--{- |-Returns a list of non-zero times.--}-{-# INLINE chopLongTime #-}-chopLongTime :: StrictTime -> [ShortStrictTime]-chopLongTime n =-   let d = fromIntegral (maxBound :: Int)-       (q,r) = P.divMod (NonNegW.toNumber n) d-   in  map (NonNegW.fromNumberMsg "chopLongTime" . fromInteger) $-       List.genericReplicate q d ++-       if not $ isZero r then [r] else []  {-# INLINE longFromShortTime #-} longFromShortTime :: ShortStrictTime -> StrictTime
+ src/Synthesizer/PiecewiseConstant/Storable.hs view
@@ -0,0 +1,47 @@+module Synthesizer.PiecewiseConstant.Storable (+   toSignal,+   toSignalInit,+   toSignalInitWith,+   ) where++import qualified Synthesizer.PiecewiseConstant.Private as PC+import Synthesizer.PiecewiseConstant.Private (StrictTime)++import qualified Synthesizer.Storable.Signal     as SigSt+import qualified Data.StorableVector.Lazy.Pattern as SigStV+import qualified Data.StorableVector.Lazy        as SVL++import qualified Data.EventList.Relative.BodyTime  as EventListBT+import qualified Data.EventList.Relative.TimeBody  as EventList++import Foreign.Storable (Storable, )++import qualified Numeric.NonNegative.Wrapper as NonNegW+import qualified Numeric.NonNegative.Chunky as NonNegChunky++++chunkSizesFromStrictTime :: StrictTime -> NonNegChunky.T SigSt.ChunkSize+chunkSizesFromStrictTime =+   NonNegChunky.fromChunks .+   map (SVL.ChunkSize . NonNegW.toNumber) .+   PC.chopLongTime+++replicateLong :: (Storable y) => StrictTime -> y -> SigSt.T y+replicateLong t y =+   SigStV.replicate (chunkSizesFromStrictTime t) y++{-# INLINE toSignal #-}+toSignal :: (Storable y) => EventListBT.T StrictTime y -> SigSt.T y+toSignal = PC.toSignal replicateLong++{-# INLINE toSignalInit #-}+toSignalInit :: (Storable y) => y -> EventList.T StrictTime y -> SigSt.T y+toSignalInit = PC.toSignalInit replicateLong++{-# INLINE toSignalInitWith #-}+toSignalInitWith ::+   (Storable c) =>+   (y -> c) -> c -> EventList.T StrictTime [y] -> SigSt.T c+toSignalInitWith = PC.toSignalInitWith replicateLong
src/Synthesizer/Plain/Filter/Recursive/FirstOrder.hs view
@@ -30,6 +30,8 @@ import qualified Foreign.Storable.Traversable as StoreTrav import Foreign.Storable (Storable(sizeOf, alignment, peek, poke)) +import qualified Test.QuickCheck as QC+ import qualified Algebra.Module                as Module import qualified Algebra.Transcendental        as Trans import qualified Algebra.Ring                  as Ring@@ -41,7 +43,7 @@   newtype Parameter a = Parameter {getParameter :: a}-   deriving Show+   deriving (Eq, Show)   instance Functor Parameter where@@ -74,7 +76,10 @@    peek = Store.peek Parameter    poke = Store.poke getParameter +instance QC.Arbitrary a => QC.Arbitrary (Parameter a) where+   arbitrary = fmap Parameter QC.arbitrary + {-| Convert cut-off frequency to feedback factor. -} {-# INLINE parameter #-} parameter :: Trans.C a => a -> Parameter a@@ -129,7 +134,7 @@ highpassModifierInit :: (Ring.C a, Module.C a v) =>    Modifier.Initialized v v (Parameter a) v v highpassModifierInit =-   Modifier.Initialized negate highpassStep+   Modifier.Initialized id highpassStep  {-# INLINE highpassModifier #-} highpassModifier :: (Ring.C a, Module.C a v) =>@@ -146,7 +151,7 @@ highpassInitAlt :: (Ring.C a, Module.C a v) =>    v -> Sig.T (Parameter a) -> Sig.T v -> Sig.T v highpassInitAlt y0 control x =-   x - lowpassInit (-y0) control x+   zipWith (-) x $ lowpassInit y0 control x  {-# INLINE highpass #-} highpass :: (Ring.C a, Module.C a v) =>@@ -156,6 +161,7 @@   data Result a = Result {highpass_, lowpass_ :: !a}+   deriving (Eq)  instance Functor Result where    {-# INLINE fmap #-}@@ -203,6 +209,9 @@    alignment = StoreTrav.alignment    peek      = StoreTrav.peekApplicative    poke      = StoreTrav.poke++instance QC.Arbitrary a => QC.Arbitrary (Result a) where+   arbitrary = liftA2 Result QC.arbitrary QC.arbitrary   {-# INLINE step #-}
src/Synthesizer/Plain/Instrument.hs view
@@ -254,7 +254,7 @@ osciSharp sampleRate freq =    let --control = iterate (+ (-1/sampleRate)) 4        control = exponential2 (0.01*sampleRate) 10-   in  Osci.shapeMod Wave.powerNormed 0 (freq/sampleRate) control+   in  Osci.shapeMod Wave.powerNormed2 0 (freq/sampleRate) control  {-| Build a saw sound from its harmonics and modulate it.     Different to normal modulation
src/Synthesizer/State/Signal.hs view
@@ -922,11 +922,21 @@ {- | Counterpart to 'Data.Monoid.mconcat'. -}+fold :: Monoid m => T m -> m+fold = foldR mappend mempty++{-# DEPRECATED monoidConcat "Use foldMap instead." #-} monoidConcat :: Monoid m => T m -> m-monoidConcat = foldR mappend mempty+monoidConcat = fold ++foldMap :: Monoid m => (a -> m) -> T a -> m+foldMap f = monoidConcat . map f++{-# DEPRECATED monoidConcatMap "Use foldMap instead." #-} monoidConcatMap :: Monoid m => (a -> m) -> T a -> m-monoidConcatMap f = monoidConcat . map f+monoidConcatMap = foldMap+  instance Monoid (T y) where    mempty = empty
src/Synthesizer/Storable/Filter/NonRecursive.hs view
@@ -9,6 +9,11 @@ Portability :  requires multi-parameter type classes -} module Synthesizer.Storable.Filter.NonRecursive (+   delay,+   delayPad,+   delayPos,+   delayNeg,+    downsample2,    sumsDownsample2,    convolveDownsample2,@@ -57,6 +62,31 @@ import NumericPrelude.Base as NP  ++{-# INLINE delay #-}+delay :: (Additive.C y, Storable y) => Int -> SigSt.T y -> SigSt.T y+delay = delayPad zero++{-# INLINE delayPad #-}+delayPad :: (Storable y) => y -> Int -> SigSt.T y -> SigSt.T y+delayPad z n =+   if n<0+     then delayNeg (Additive.negate n)+     else delayPosPad z n++{-# INLINE delayPos #-}+delayPos :: (Additive.C y, Storable y) => Int -> SigSt.T y -> SigSt.T y+delayPos = delayPosPad zero++{-# INLINE delayPosPad #-}+delayPosPad :: (Storable v) => v -> Int -> SigSt.T v -> SigSt.T v+delayPosPad z n = SigSt.append (SigSt.replicate SigSt.defaultChunkSize n z)++{-# INLINE delayNeg #-}+delayNeg :: (Storable y) => Int -> SigSt.T y -> SigSt.T y+delayNeg = SigSt.drop++ {- | The Maybe type carries an unpaired value from one block to the next one. -}@@ -215,7 +245,7 @@    (Additive.C v, Storable v) =>    Int -> SigSt.T (Int,Int) -> SigSt.T v -> SigSt.T v sumsPosModulatedPyramid height ctrl xs =-   FiltG.accumulatePosModulatedFromPyramid+   accumulatePosModulatedPyramid       FiltG.sumRangeFromPyramid       (addSizes $ pyramid (+) height xs)       ctrl@@ -225,7 +255,7 @@    (v -> v -> v) ->    Int -> SigSt.T (Int,Int) -> SigSt.T v -> SigSt.T v accumulateBinPosModulatedPyramid acc height ctrl xs =-   FiltG.accumulatePosModulatedFromPyramid+   accumulatePosModulatedPyramid       (\pyr ->          fromMaybe (error "accumulateBinPosModulatedPyramid: empty window") .          FiltG.maybeAccumulateRangeFromPyramid acc pyr)@@ -245,11 +275,12 @@ movingAverageModulatedPyramid ::    (Field.C a, Module.C a v, Storable Int, Storable v) =>    a -> Int -> Int -> SigSt.T Int -> SigSt.T v -> SigSt.T v-movingAverageModulatedPyramid amp height maxC ctrl xs =-   SigSt.zipWith (\c x -> (amp / fromIntegral (2*c+1)) *> x) ctrl $-   sumsPosModulatedPyramid height-      (SigSt.map (\c -> (maxC - c, maxC + c + 1)) ctrl)-      (FiltG.delay maxC xs)+movingAverageModulatedPyramid amp height maxC ctrl0 =+   withPaddedInput zero+      (\ctrl xs ->+         SigSt.zipWith (\c x -> (amp / fromIntegral (2*c+1)) *> x) ctrl0 $+         sumsPosModulatedPyramid height ctrl xs)+      maxC ctrl0   movingAccumulateModulatedPyramid ::@@ -257,10 +288,20 @@    (v -> v -> v) ->    v -> Int -> Int -> SigSt.T Int -> SigSt.T v -> SigSt.T v movingAccumulateModulatedPyramid acc pad height =-   FiltG.withPaddedInput pad $+   withPaddedInput pad $    accumulateBinPosModulatedPyramid acc height  +withPaddedInput ::+   (Storable y) =>+   y -> (SigSt.T (Int, Int) -> SigSt.T y -> v) ->+   Int -> SigSt.T Int -> SigSt.T y -> v+withPaddedInput pad proc maxC ctrl xs =+   proc+      (SigSt.map (\c -> (maxC - c, maxC + c + 1)) ctrl)+      (delayPad pad maxC xs)++ {- | The function is like that of 'Synthesizer.State.Filter.NonRecursive.inverseFrequencyModulationFloor',@@ -273,7 +314,8 @@ (Since control and input signal are aligned in time, we might as well use the control chunk structure. Currently I do not know what is better.-For the above example it doesn't matter.)+For the above example it doesn't matter.+We might implement a variant in Causal.Filter.NonRecursive.)  This function cannot be written using generic functions, since we have to inspect the chunks individually.
src/Synthesizer/Storable/Signal.hs view
@@ -89,186 +89,14 @@ import Prelude ()  -{--import NumericPrelude.Numeric-   (sum, (+), (-), divMod, fromIntegral, fromInteger, toInteger, isZero, zero, )--import Prelude hiding-   (length, (++), iterate, foldl, map, repeat, replicate, null,-    zip, zipWith, zipWith3, drop, take, splitAt, takeWhile, reverse)--}--{--import qualified Prelude as P-import Prelude-   (IO, ($), (.), fst, snd, id,-    Int, Double, Float,-    Char, Num, Show, showsPrec, FilePath,-    Bool(True,False), not,-    flip, curry, uncurry,-    Ord, (<), (>), (<=), {- (>=), (==), -} min, max,-    mapM_, fmap, (=<<), return,-    Enum, succ, pred, )--}-- -- this form is needed for Storable signal embed in amplitude signal type T = Vector.Vector--- type T a = Vector.Vector a   defaultChunkSize :: ChunkSize defaultChunkSize = ChunkSize 1024  -{--{- * Helper functions for StorableVector -}--cancelNullVector :: (Vector a, b) -> Maybe (Vector a, b)-cancelNullVector y =-   toMaybe (not (Vector.null (fst y))) y--viewLVector :: Storable a =>-   Vector a -> Maybe (a, Vector a)-viewLVector = Vector.viewL-{--   toMaybe-      (not (Vector.null x))-      (Vector.head x, Vector.tail x)--}--crochetLVector :: (Storable x, Storable y) =>-      (x -> acc -> Maybe (y, acc))-   -> acc-   -> Vector x-   -> (Vector y, Maybe acc)-crochetLVector f acc0 x0 =-   mapSnd (fmap fst) $-   Vector.unfoldrN-      (Vector.length x0)-      (\(acc,xt) ->-         do (x,xs) <- viewLVector xt-            (y,acc') <- f x acc-            return (y, (acc',xs)))-      (acc0, x0)--}--{--reduceLVector :: Storable x =>-   (x -> acc -> Maybe acc) -> acc -> Vector x -> (acc, Bool)-reduceLVector f acc0 x =-   let recourse i acc =-          if i < Vector.length x-            then (acc, True)-            else-               maybe-                  (acc, False)-                  (recourse (succ i))-                  (f (Vector.index x i) acc)-   in  recourse 0 acc0-----{- * Fundamental functions -}--{- |-Sophisticated implementation where chunks always have size bigger than 0.--}-{-# INLINE [0] unfoldr #-}-unfoldr :: (Storable b) =>-      ChunkSize-   -> (a -> Maybe (b,a))-   -> a-   -> T b-unfoldr (ChunkSize size) f =-   Cons .-   List.unfoldr-      (cancelNullVector . Vector.unfoldrN size f =<<) .-   Just--{- |-Simple implementation where chunks can have size 0 in the first run.-Then they are filtered out.-This separation might reduce laziness.--}-unfoldr0 :: (Storable b) =>-      ChunkSize-   -> (a -> Maybe (b,a))-   -> a-   -> T b-unfoldr0 (ChunkSize size) f =-   Cons .-   List.filter (not . Vector.null) .-   List.unfoldr (fmap (Vector.unfoldrN size f)) .-   Just---unfoldr1 :: (Storable b) =>-      ChunkSize-   -> (a -> (b, Maybe a))-   -> Maybe a-   -> T b-unfoldr1 size f = unfoldr size (liftM f)--{-# INLINE [0] crochetL #-}-crochetL :: (Storable x, Storable y) =>-      (x -> acc -> Maybe (y, acc))-   -> acc-   -> T x-   -> T y-crochetL f acc0 =-   Cons . List.unfoldr (\(xt,acc) ->-       do (x,xs) <- ListHT.viewL xt-          acc' <- acc-          return $ mapSnd ((,) xs) $ crochetLVector f acc' x) .-   flip (,) (Just acc0) .-   decons--{--Usage of 'unfoldr' seems to be clumsy but that covers all cases,-like different block sizes in source and destination list.--}-crochetLSize :: (Storable x, Storable y) =>-      ChunkSize-   -> (x -> acc -> Maybe (y, acc))-   -> acc-   -> T x-   -> T y-crochetLSize size f =-   curry (unfoldr size (\(acc,xt) ->-      do (x,xs) <- viewL xt-         (y,acc') <- f x acc-         return (y, (acc',xs))))--viewL :: Storable a => T a -> Maybe (a, T a)-viewL (Cons xs0) =-   -- dropWhile would be unnecessary if we require that all chunks are non-empty-   do (x,xs) <- ListHT.viewL (List.dropWhile Vector.null xs0)-      (y,ys) <- viewLVector x-      return (y, append (fromChunk ys) (Cons xs))--viewR :: Storable a => T a -> Maybe (T a, a)-viewR (Cons xs0) =-   -- dropWhile would be unnecessary if we require that all chunks are non-empty-   do (xs,x) <- ListHT.viewR (dropWhileRev Vector.null xs0)-      (ys,y) <- Vector.viewR x-      return (append (Cons xs) (fromChunk ys), y)--crochetListL :: (Storable y) =>-      ChunkSize-   -> (x -> acc -> Maybe (y, acc))-   -> acc-   -> [x]-   -> T y-crochetListL size f =-   curry (unfoldr size (\(acc,xt) ->-      do (x,xs) <- ListHT.viewL xt-         (y,acc') <- f x acc-         return (y, (acc',xs))))--}-- {-# INLINE fromList #-} fromList :: (Storable a) => ChunkSize -> [a] -> T a fromList = Vector.pack@@ -278,334 +106,12 @@ toList = Vector.unpack  -{---- should start fusion-fromListCrochetL :: (Storable a) => ChunkSize -> [a] -> T a-fromListCrochetL size =-   crochetListL size (\x _ -> Just (x, ())) ()--fromListUnfoldr :: (Storable a) => ChunkSize -> [a] -> T a-fromListUnfoldr size = unfoldr size ListHT.viewL--fromListPack :: (Storable a) => ChunkSize -> [a] -> T a-fromListPack (ChunkSize size) =-   Cons .-   List.map Vector.pack .-   sliceVert size--toList :: (Storable a) => T a -> [a]-toList = List.concatMap Vector.unpack . decons---- if the chunk has length zero, an empty sequence is generated-fromChunk :: (Storable a) => Vector a -> T a-fromChunk x =-   if Vector.null x-     then empty-     else Cons [x]---{-# INLINE [0] reduceL #-}-reduceL :: Storable x =>-   (x -> acc -> Maybe acc) -> acc -> T x -> acc-reduceL f acc0 =-   let recourse acc xt =-          case xt of-             [] -> acc-             (x:xs) ->-                 let (acc',continue) = reduceLVector f acc x-                 in  if continue-                       then recourse acc' xs-                       else acc'-   in  recourse acc0 . decons----{- * Basic functions -}--empty :: Storable a => T a-empty = Cons []--null :: Storable a => T a -> Bool-null = List.null . decons---{-# NOINLINE [0] cons #-}-cons :: Storable a => a -> T a -> T a-cons x = Cons . (Vector.singleton x :) . decons---length :: T a -> Int-length = sum . List.map Vector.length . decons---reverse :: Storable a => T a -> T a-reverse =-   Cons . List.reverse . List.map Vector.reverse . decons---{-# INLINE [0] foldl #-}-foldl :: Storable b => (a -> b -> a) -> a -> T b -> a-foldl f x0 = List.foldl (Vector.foldl f) x0 . decons---{-# INLINE [0] map #-}-map :: (Storable x, Storable y) =>-      (x -> y)-   -> T x-   -> T y-map f = mapInline f -- Cons . List.map (Vector.map f) . decons--{-# INLINE mapInline #-}-mapInline :: (Storable x, Storable y) =>-      (x -> y)-   -> T x-   -> T y-mapInline f =-   let mapVec = Vector.map f-   in  Cons . List.map mapVec . decons----{-# NOINLINE [0] drop #-}-drop :: (Storable a) => Int -> T a -> T a-drop _ (Cons []) = empty-drop n (Cons (x:xs)) =-   let m = Vector.length x-   in  if m<=n-         then drop (n-m) (Cons xs)-         else Cons (Vector.drop n x : xs)--{-# NOINLINE [0] take #-}-take :: (Storable a) => Int -> T a -> T a-take _ (Cons []) = empty-take 0 _ = empty-take n (Cons (x:xs)) =-   let m = Vector.length x-   in  if m<=n-         then Cons $ (x:) $ decons $ take (n-m) $ Cons xs-         else fromChunk (Vector.take n x)----{-# NOINLINE [0] splitAt #-}-splitAt :: (Storable a) => Int -> T a -> (T a, T a)-splitAt n0 =-   let recourse _ [] = ([], [])-       recourse 0 xs = ([], xs)-       recourse n (x:xs) =-          let m = Vector.length x-          in  if m<=n-                then mapFst (x:) $ recourse (n-m) xs-                else mapPair ((:[]), (:xs)) $ Vector.splitAt n x-   in  mapPair (Cons, Cons) . recourse n0 . decons---dropMarginRem :: (Storable a) => Int -> Int -> T a -> (Int, T a)-dropMarginRem n m xs =-   List.foldl'-      (\(mi,xsi) k -> (mi-k, drop k xsi))-      (m,xs)-      (List.map Vector.length $ decons $ take m $ drop n xs)--{--This implementation does only walk once through the dropped prefix.-It is maximally lazy and minimally space consuming.--}-dropMargin :: (Storable a) => Int -> Int -> T a -> T a-dropMargin n m xs =-   List.foldl' (flip drop) xs-      (List.map Vector.length $ decons $ take m $ drop n xs)---{-# NOINLINE [0] dropWhile #-}-dropWhile :: (Storable a) => (a -> Bool) -> T a -> T a-dropWhile _ (Cons []) = empty-dropWhile p (Cons (x:xs)) =-   let y = Vector.dropWhile p x-   in  if Vector.null y-         then dropWhile p (Cons xs)-         else Cons (y:xs)--{-# NOINLINE [0] takeWhile #-}-takeWhile :: (Storable a) => (a -> Bool) -> T a -> T a-takeWhile _ (Cons []) = empty-takeWhile p (Cons (x:xs)) =-   let y = Vector.takeWhile p x-   in  if Vector.length y < Vector.length x-         then fromChunk y-         else Cons (x : decons (takeWhile p (Cons xs)))---{-# NOINLINE [0] span #-}-span :: (Storable a) => (a -> Bool) -> T a -> (T a, T a)-span p =-   let recourse [] = ([],[])-       recourse (x:xs) =-          let (y,z) = Vector.span p x-          in  if Vector.null z-                then mapFst (x:) (recourse xs)-                else (decons $ fromChunk y, (z:xs))-   in  mapPair (Cons, Cons) . recourse . decons-{--span _ (Cons []) = (empty, empty)-span p (Cons (x:xs)) =-   let (y,z) = Vector.span p x-   in  if Vector.length y == 0-         then mapFst (Cons . (x:) . decons) (span p (Cons xs))-         else (Cons [y], Cons (z:xs))--}--concat :: (Storable a) => [T a] -> T a-concat = Cons . List.concat . List.map decons---{- |-Ensure a minimal length of the list by appending pad values.--}-{-# NOINLINE [0] pad #-}-pad :: (Storable a) => ChunkSize -> a -> Int -> T a -> T a-pad size y n0 =-   let recourse n xt =-          if n<=0-            then xt-            else-              case xt of-                 [] -> decons $ replicate size n y-                 x:xs -> x : recourse (n - Vector.length x) xs-   in  Cons . recourse n0 . decons--padAlt :: (Storable a) => ChunkSize -> a -> Int -> T a -> T a-padAlt size x n xs =-   append xs-      (let m = length xs-       in  if n>m-             then replicate size (n-m) x-             else empty)---infixr 5 `append`--{-# NOINLINE [0] append #-}-append :: T a -> T a -> T a-append (Cons xs) (Cons ys)  =  Cons (xs List.++ ys)--{-# INLINE iterate #-}-iterate :: Storable a => ChunkSize -> (a -> a) -> a -> T a-iterate size f = unfoldr size (\x -> Just (x, f x))--repeat :: Storable a => ChunkSize -> a -> T a-repeat (ChunkSize size) =-   Cons . List.repeat . Vector.replicate size--cycle :: Storable a => T a -> T a-cycle =-   Cons . List.cycle . decons--replicate :: Storable a => ChunkSize -> Int -> a -> T a-replicate (ChunkSize size) n x =-   let (numChunks, rest) = divMod n size-   in  append-          (Cons (List.replicate numChunks (Vector.replicate size x)))-          (fromChunk (Vector.replicate rest x))--}- {-# INLINE scanL #-} scanL :: (Storable a, Storable b) =>    (a -> b -> a) -> a -> T b -> T a scanL = Vector.scanl  -{--{-# INLINE [0] mapAccumL #-}-mapAccumL :: (Storable a, Storable b) =>-   (acc -> a -> (acc, b)) -> acc -> T a -> (acc, T b)-mapAccumL f start =-   mapSnd Cons .-   List.mapAccumL (Vector.mapAccumL f) start .-   decons--{-# INLINE [0] mapAccumR #-}-mapAccumR :: (Storable a, Storable b) =>-   (acc -> a -> (acc, b)) -> acc -> T a -> (acc, T b)-mapAccumR f start =-   mapSnd Cons .-   List.mapAccumR (Vector.mapAccumR f) start .-   decons--{- disabled RULES-  "Storable.append/repeat/repeat" forall size x.-      append (repeat size x) (repeat size x) = repeat size x ;--  "Storable.append/repeat/replicate" forall size n x.-      append (repeat size x) (replicate size n x) = repeat size x ;--  "Storable.append/replicate/repeat" forall size n x.-      append (replicate size n x) (repeat size x) = repeat size x ;--  "Storable.append/replicate/replicate" forall size n m x.-      append (replicate size n x) (replicate size m x) =-         replicate size (n+m) x ;--  "Storable.mix/repeat/repeat" forall size x y.-      mix (repeat size x) (repeat size y) = repeat size (x+y) ;--  -}--{- disabled RULES-  "Storable.length/cons" forall x xs.-      length (cons x xs) = 1 + length xs ;--  "Storable.length/map" forall f xs.-      length (map f xs) = length xs ;--  "Storable.map/cons" forall f x xs.-      map f (cons x xs) = cons (f x) (map f xs) ;--  "Storable.map/repeat" forall size f x.-      map f (repeat size x) = repeat size (f x) ;--  "Storable.map/replicate" forall size f x n.-      map f (replicate size n x) = replicate size n (f x) ;--  "Storable.map/repeat" forall size f x.-      map f (repeat size x) = repeat size (f x) ;--  {--  This can make things worse, if 'map' is applied to replicate,-  since this can use of sharing.-  It can also destroy the more important map/unfoldr fusion in-    take n . map f . unfoldr g--  "Storable.take/map" forall n f x.-      take n (map f x) = map f (take n x) ;-  -}--  "Storable.take/repeat" forall size n x.-      take n (repeat size x) = replicate size n x ;--  "Storable.take/take" forall n m xs.-      take n (take m xs) = take (min n m) xs ;--  "Storable.drop/drop" forall n m xs.-      drop n (drop m xs) = drop (n+m) xs ;--  "Storable.drop/take" forall n m xs.-      drop n (take m xs) = take (max 0 (m-n)) (drop n xs) ;--  "Storable.map/mapAccumL/snd" forall g f acc0 xs.-      map g (snd (mapAccumL f acc0 xs)) =-         snd (mapAccumL (\acc a -> mapSnd g (f acc a)) acc0 xs) ;--  -}--{- GHC says this is an orphaned rule-  "Storable.map/mapAccumL/mapSnd" forall g f acc0 xs.-      mapSnd (map g) (mapAccumL f acc0 xs) =-         mapAccumL (\acc a -> mapSnd g (f acc a)) acc0 xs ;--}--}-- {- | This implementation generates laziness breaks whereever one of the original sequences has laziness breaks.@@ -809,367 +315,6 @@   -{--{-# INLINE zip #-}-zip :: (Storable a, Storable b) =>-   ChunkSize -> (T a -> T b -> T (a,b))-zip size  =  zipWith size (,)--{-# INLINE zipWith3 #-}-zipWith3 :: (Storable a, Storable b, Storable c, Storable d) =>-   ChunkSize -> (a -> b -> c -> d) -> (T a -> T b -> T c -> T d)-zipWith3 size f s0 s1 =-   zipWith size (uncurry f) (zip size s0 s1)--{-# INLINE zipWith4 #-}-zipWith4 :: (Storable a, Storable b, Storable c, Storable d, Storable e) =>-   ChunkSize -> (a -> b -> c -> d -> e) -> (T a -> T b -> T c -> T d -> T e)-zipWith4 size f s0 s1 =-   zipWith3 size (uncurry f) (zip size s0 s1)---{- * Fusable functions -}--{-# INLINE [0] zipWith #-}-zipWith :: (Storable x, Storable y, Storable z) =>-      ChunkSize-   -> (x -> y -> z)-   -> T x-   -> T y-   -> T z-zipWith size f =-   curry (unfoldr size (\(xt,yt) ->-      liftM2-         (\(x,xs) (y,ys) -> (f x y, (xs,ys)))-         (viewL xt)-         (viewL yt)))----scanLCrochet :: (Storable a, Storable b) =>-   (a -> b -> a) -> a -> T b -> T a-scanLCrochet f start =-   cons start .-   crochetL (\x acc -> let y = f acc x in Just (y, y)) start--{-# INLINE mapCrochet #-}-mapCrochet :: (Storable a, Storable b) => (a -> b) -> (T a -> T b)-mapCrochet f = crochetL (\x _ -> Just (f x, ())) ()--}- {-# INLINE takeCrochet #-} takeCrochet :: Storable a => Int -> T a -> T a takeCrochet = Vector.crochetL (\x n -> toMaybe (n>0) (x, pred n))--{--{-# INLINE repeatUnfoldr #-}-repeatUnfoldr :: Storable a => ChunkSize -> a -> T a-repeatUnfoldr size = iterate size id--{-# INLINE replicateCrochet #-}-replicateCrochet :: Storable a => ChunkSize -> Int -> a -> T a-replicateCrochet size n = takeCrochet n . repeat size---{--The "fromList/drop" rule is not quite accurate-because the chunk borders are moved.-Maybe 'ChunkSize' better is a list of chunks sizes.--}--{- disabled RULES-  "fromList/zipWith"-    forall size f (as :: Storable a => [a]) (bs :: Storable a => [a]).-     fromList size (List.zipWith f as bs) =-        zipWith size f (fromList size as) (fromList size bs) ;--  "fromList/drop" forall as n size.-     fromList size (List.drop n as) =-        drop n (fromList size as) ;-  -}----{- * Fused functions -}--type Unfoldr s a = (s -> Maybe (a,s), s)--{-# INLINE zipWithUnfoldr2 #-}-zipWithUnfoldr2 :: Storable z =>-      ChunkSize-   -> (x -> y -> z)-   -> Unfoldr a x-   -> Unfoldr b y-   -> T z-zipWithUnfoldr2 size h (f,a) (g,b) =-   unfoldr size-      (\(a0,b0) -> liftM2 (\(x,a1) (y,b1) -> (h x y, (a1,b1))) (f a0) (g b0))---      (uncurry (liftM2 (\(x,a1) (y,b1) -> (h x y, (a1,b1)))) . (f *** g))-      (a,b)--{- done by takeCrochet-{-# INLINE mapUnfoldr #-}-mapUnfoldr :: (Storable x, Storable y) =>-      ChunkSize-   -> (x -> y)-   -> Unfoldr a x-   -> T y-mapUnfoldr size g (f,a) =-   unfoldr size (fmap (mapFst g) . f) a--}--{-# INLINE dropUnfoldr #-}-dropUnfoldr :: Storable x =>-      ChunkSize-   -> Int-   -> Unfoldr a x-   -> T x-dropUnfoldr size n (f,a0) =-   maybe-      empty-      (unfoldr size f)-      (nest n (\a -> fmap snd . f =<< a) (Just a0))---{- done by takeCrochet-{-# INLINE takeUnfoldr #-}-takeUnfoldr :: Storable x =>-      ChunkSize-   -> Int-   -> Unfoldr a x-   -> T x-takeUnfoldr size n0 (f,a0) =-   unfoldr size-      (\(a,n) ->-         do guard (n>0)-            (x,a') <- f a-            return (x, (a', pred n)))-      (a0,n0)--}---lengthUnfoldr :: Storable x =>-      Unfoldr a x-   -> Int-lengthUnfoldr (f,a0) =-   let recourse n a =-          maybe n (recourse (succ n) . snd) (f a)-   in  recourse 0 a0---{-# INLINE zipWithUnfoldr #-}-zipWithUnfoldr ::-   (Storable b, Storable c) =>-      (acc -> Maybe (a, acc))-   -> (a -> b -> c)-   -> acc-   -> T b -> T c-zipWithUnfoldr f h a y =-   crochetL (\y0 a0 ->-       do (x0,a1) <- f a0-          Just (h x0 y0, a1)) a y--{-# INLINE zipWithCrochetL #-}-zipWithCrochetL ::-   (Storable x, Storable b, Storable c) =>-      ChunkSize-   -> (x -> acc -> Maybe (a, acc))-   -> (a -> b -> c)-   -> acc-   -> T x -> T b -> T c-zipWithCrochetL size f h a x y =-   crochetL (\(x0,y0) a0 ->-       do (z0,a1) <- f x0 a0-          Just (h z0 y0, a1))-      a (zip size x y)---{-# INLINE crochetLCons #-}-crochetLCons ::-   (Storable a, Storable b) =>-      (a -> acc -> Maybe (b, acc))-   -> acc-   -> a -> T a -> T b-crochetLCons f a0 x xs =-   maybe-      empty-      (\(y,a1) -> cons y (crochetL f a1 xs))-      (f x a0)--{-# INLINE reduceLCons #-}-reduceLCons ::-   (Storable a) =>-      (a -> acc -> Maybe acc)-   -> acc-   -> a -> T a -> acc-reduceLCons f a0 x xs =-   maybe a0 (flip (reduceL f) xs) (f x a0)------{-# RULES-  "Storable.zipWith/share" forall size (h :: a->a->b) (x :: T a).-     zipWith size h x x = map (\xi -> h xi xi) x ;----  "Storable.map/zipWith" forall size (f::c->d) (g::a->b->c) (x::T a) (y::T b).-  "Storable.map/zipWith" forall size f g x y.-     map f (zipWith size g x y) =-        zipWith size (\xi yi -> f (g xi yi)) x y ;--  -- this rule lets map run on a different block structure-  "Storable.zipWith/map,*" forall size f g x y.-     zipWith size g (map f x) y =-        zipWith size (\xi yi -> g (f xi) yi) x y ;--  "Storable.zipWith/*,map" forall size f g x y.-     zipWith size g x (map f y) =-        zipWith size (\xi yi -> g xi (f yi)) x y ;---  "Storable.drop/unfoldr" forall size f a n.-     drop n (unfoldr size f a) =-        dropUnfoldr size n (f,a) ;--  "Storable.take/unfoldr" forall size f a n.-     take n (unfoldr size f a) =---        takeUnfoldr size n (f,a) ;-        takeCrochet n (unfoldr size f a) ;--  "Storable.length/unfoldr" forall size f a.-     length (unfoldr size f a) = lengthUnfoldr (f,a) ;--  "Storable.map/unfoldr" forall size g f a.-     map g (unfoldr size f a) =---        mapUnfoldr size g (f,a) ;-        mapCrochet g (unfoldr size f a) ;--  "Storable.map/iterate" forall size g f a.-     map g (iterate size f a) =-        mapCrochet g (iterate size f a) ;--{--  "Storable.zipWith/unfoldr,unfoldr" forall sizeA sizeB f g h a b n.-     zipWith n h (unfoldr sizeA f a) (unfoldr sizeB g b) =-        zipWithUnfoldr2 n h (f,a) (g,b) ;--}--  -- block boundaries are changed here, so it changes lazy behaviour-  "Storable.zipWith/unfoldr,*" forall sizeA sizeB f h a y.-     zipWith sizeA h (unfoldr sizeB f a) y =-        zipWithUnfoldr f h a y ;--  -- block boundaries are changed here, so it changes lazy behaviour-  "Storable.zipWith/*,unfoldr" forall sizeA sizeB f h a y.-     zipWith sizeA h y (unfoldr sizeB f a) =-        zipWithUnfoldr f (flip h) a y ;--  "Storable.crochetL/unfoldr" forall size f g a b.-     crochetL g b (unfoldr size f a) =-        unfoldr size (\(a0,b0) ->-            do (y0,a1) <- f a0-               (z0,b1) <- g y0 b0-               Just (z0, (a1,b1))) (a,b) ;--  "Storable.reduceL/unfoldr" forall size f g a b.-     reduceL g b (unfoldr size f a) =-        snd-          (untilNothing (\(a0,b0) ->-              do (y,a1) <- f a0-                 b1 <- g y b0-                 Just (a1, b1)) (a,b)) ;--  "Storable.crochetL/cons" forall g b x xs.-     crochetL g b (cons x xs) =-        crochetLCons g b x xs ;--  "Storable.reduceL/cons" forall g b x xs.-     reduceL g b (cons x xs) =-        reduceLCons g b x xs ;-----  "Storable.take/crochetL" forall f a x n.-     take n (crochetL f a x) =-        takeCrochet n (crochetL f a x) ;--  "Storable.length/crochetL" forall f a x.-     length (crochetL f a x) = length x ;--  "Storable.map/crochetL" forall g f a x.-     map g (crochetL f a x) =-        mapCrochet g (crochetL f a x) ;--  "Storable.zipWith/crochetL,*" forall size f h a x y.-     zipWith size h (crochetL f a x) y =-        zipWithCrochetL size f h a x y ;--  "Storable.zipWith/*,crochetL" forall size f h a x y.-     zipWith size h y (crochetL f a x) =-        zipWithCrochetL size f (flip h) a x y ;--  "Storable.crochetL/crochetL" forall f g a b x.-     crochetL g b (crochetL f a x) =-        crochetL (\x0 (a0,b0) ->-            do (y0,a1) <- f x0 a0-               (z0,b1) <- g y0 b0-               Just (z0, (a1,b1))) (a,b) x ;--  "Storable.reduceL/crochetL" forall f g a b x.-     reduceL g b (crochetL f a x) =-        snd-          (reduceL (\x0 (a0,b0) ->-              do (y,a1) <- f x0 a0-                 b1 <- g y b0-                 Just (a1, b1)) (a,b) x) ;-  #-}----- maybe candidate for Utility, cf. FusionList.Signal.recourse--{-# INLINE untilNothing #-}-untilNothing :: (acc -> Maybe acc) -> acc -> acc-untilNothing f =-   let aux x = maybe x aux (f x)-   in  aux---{- * Fusion tests -}---fromMapList :: (Storable y) => ChunkSize -> (x -> y) -> [x] -> T y-fromMapList size f =-   unfoldr size (fmap (mapFst f) . ListHT.viewL)--{-# RULES-  "Storable.fromList/map" forall size f xs.-     fromList size (List.map f xs) = fromMapList size f xs ;-  #-}---testLength :: (Storable a, Enum a) => a -> Int-testLength x = length (map succ (fromList (ChunkSize 100) [x,x,x]))--testMapZip :: (Storable a, Enum a, Num a) =>-   ChunkSize -> T a -> T a -> T a--- testMapZip size x y = map snd (zipWith size (,) x y)-testMapZip size x y = map succ (zipWith size (P.+) x y)--testMapCons :: (Storable a, Enum a) =>-   a -> T a -> T a-testMapCons x xs = map succ (cons x xs)--{-# INLINE testMapIterate #-}-{-# SPECIALISE testMapIterate ::-   ChunkSize -> Char -> T Char #-}-testMapIterate :: (Storable a, Enum a) =>-   ChunkSize -> a -> T a-testMapIterate size y = map pred $ iterate size succ y--testMapIterateInt ::-   ChunkSize -> Int -> T Int-testMapIterateInt = testMapIterate---}
synthesizer-core.cabal view
@@ -1,5 +1,5 @@ Name:           synthesizer-core-Version:        0.8.0.2+Version:        0.8.1 License:        GPL License-File:   LICENSE Author:         Henning Thielemann <haskell@henning-thielemann.de>@@ -29,6 +29,7 @@ Build-Type:     Simple  Extra-Source-Files:+  Changes.md   Makefile  Flag optimizeAdvanced@@ -37,7 +38,7 @@   Source-Repository this-  Tag:         0.8.0.2+  Tag:         0.8.1   Type:        darcs   Location:    http://code.haskell.org/synthesizer/core/ @@ -205,6 +206,8 @@     Synthesizer.Generic.Signal     Synthesizer.Generic.Wave     Synthesizer.PiecewiseConstant.Signal+    Synthesizer.PiecewiseConstant.Generic+    Synthesizer.PiecewiseConstant.Storable      -- that's only exposed for Haddock     Synthesizer.Plain.Tutorial@@ -219,6 +222,7 @@     Synthesizer.Basic.NumberTheory     Synthesizer.Generic.Permutation     Synthesizer.Generic.LengthSignal+    Synthesizer.PiecewiseConstant.Private   Test-Suite test@@ -252,6 +256,7 @@     Test.Sound.Synthesizer.Plain.Filter     Test.Sound.Synthesizer.Plain.Filter.Allpass     Test.Sound.Synthesizer.Plain.Filter.Hilbert+    Test.Sound.Synthesizer.Plain.Filter.FirstOrder     Test.Sound.Synthesizer.Plain.Interpolation     Test.Sound.Synthesizer.Plain.NonEmpty     Test.Sound.Synthesizer.Plain.Oscillator@@ -298,7 +303,7 @@     synthesizer-core,     numeric-prelude,     old-time >= 1.0 && < 1.2,-    directory >= 1.0 && < 1.3,+    directory >= 1.0 && < 1.4,     binary,     bytestring,     utility-ht,
test/Test/Main.hs view
@@ -3,6 +3,7 @@ import qualified Test.Sound.Synthesizer.Plain.Analysis       as Analysis import qualified Test.Sound.Synthesizer.Plain.Control        as Control import qualified Test.Sound.Synthesizer.Plain.Filter         as Filter+import qualified Test.Sound.Synthesizer.Plain.Filter.FirstOrder as Filt1 import qualified Test.Sound.Synthesizer.Plain.Interpolation  as Interpolation import qualified Test.Sound.Synthesizer.Plain.Oscillator     as Oscillator import qualified Test.Sound.Synthesizer.Plain.Wave           as Wave@@ -31,6 +32,7 @@    concat $       prefix "Plain.Analysis"       Analysis.tests :       prefix "Plain.Control"        Control.tests :+      prefix "Plain.Filter.FirstOrder" Filt1.tests :       prefix "Plain.Filter"         Filter.tests :       prefix "Plain.Interpolation"  Interpolation.tests :       prefix "Plain.Oscillator"     Oscillator.tests :
test/Test/Sound/Synthesizer/Basic/NumberTheory.hs view
@@ -46,7 +46,7 @@  instance Arbitrary Big where    arbitrary = do-      digits <- arbitrary+      digits <- QC.listOf arbitrary       -- negative digits yield numbers close to the maximum       let maxi = 10^50       return $ Big $@@ -152,6 +152,10 @@              (NT.ordersOfPrimitiveRootsOfUnityInteger !! (n-1)))          ==          NT.ordersOfRootsOfUnityInteger !! (n-1) !! (k-1)) :+   ("divideByMaximumPower",+      QC.quickCheck $+         QC.forAll (QC.choose (2,10::Integer)) $ \b (Positive n) ->+         NT.divideByMaximumPower b n == NT.divideByMaximumPowerRecursive b n) :    ("numbers3Smooth",       QC.quickCheckWith singleArgs $ equalList $ map (take 10000) $          [NT.numbers3SmoothCorec, NT.numbers3SmoothFoldr, NT.numbers3SmoothSet]) :
+ test/Test/Sound/Synthesizer/Plain/Filter/FirstOrder.hs view
@@ -0,0 +1,73 @@+module Test.Sound.Synthesizer.Plain.Filter.FirstOrder (tests) where++import qualified Synthesizer.Plain.Filter.Recursive.FirstOrder as Filt1+import qualified Synthesizer.Plain.Signal as Sig+import qualified Synthesizer.Causal.Process as Causal++import Test.QuickCheck (quickCheck, )++import qualified Number.GaloisField2p32m5 as GF++import Control.Applicative ((<$), )++import NumericPrelude.Numeric+import NumericPrelude.Base+import Prelude ()++++addLowHighpass :: Sig.T (Filt1.Parameter GF.T, GF.T) -> Bool+addLowHighpass pxs =+   let (ps, xs) = unzip pxs+   in  Filt1.lowpass ps xs + Filt1.highpass ps xs == xs++combineLowHighpass :: Sig.T (Filt1.Parameter GF.T) -> Sig.T GF.T -> Bool+combineLowHighpass ps xs =+   zipWith Filt1.Result (Filt1.highpass ps xs) (Filt1.lowpass ps xs)+   ==+   Causal.apply Filt1.causal (zip ps xs)+++lowpassId :: Sig.T GF.T -> Bool+lowpassId xs =+   Filt1.lowpass (repeat $ Filt1.Parameter (zero::GF.T)) xs == xs++lowpassZero :: Sig.T GF.T -> Bool+lowpassZero xs =+   Filt1.lowpass (repeat $ Filt1.Parameter (one::GF.T)) xs == (zero <$ xs)+--   isZero $ Filt1.lowpass (repeat $ Filt1.Parameter (one::GF.T)) xs++highpassId :: Sig.T GF.T -> Bool+highpassId xs =+   Filt1.highpass (repeat $ Filt1.Parameter (one::GF.T)) xs == xs++highpassZero :: Sig.T GF.T -> Bool+highpassZero xs =+   Filt1.highpass (repeat $ Filt1.Parameter (zero::GF.T)) xs == (zero <$ xs)+++lowpassConst :: Sig.T GF.T -> GF.T -> Bool+lowpassConst ks x =+   Filt1.lowpassInit x (map Filt1.Parameter ks) (repeat x) == (x <$ ks)++highpassConst :: Sig.T GF.T -> GF.T -> Bool+highpassConst ks x =+   Filt1.highpassInit x (map Filt1.Parameter ks) (repeat x) == (zero <$ ks)++highpassInitAlt :: GF.T -> Sig.T (Filt1.Parameter GF.T) -> Sig.T GF.T -> Bool+highpassInitAlt x0 ps xs =+   Filt1.highpassInit x0 ps xs == Filt1.highpassInitAlt x0 ps xs+++tests :: [(String, IO ())]+tests =+   ("addLowHighpass", quickCheck addLowHighpass) :+   ("combineLowHighpass", quickCheck combineLowHighpass) :+   ("lowpassId", quickCheck lowpassId) :+   ("lowpassZero", quickCheck lowpassZero) :+   ("highpassId", quickCheck highpassId) :+   ("highpassZero", quickCheck highpassZero) :+   ("lowpassConst", quickCheck lowpassConst) :+   ("highpassConst", quickCheck highpassConst) :+   ("highpassInitAlt", quickCheck highpassInitAlt) :+   []