{-# LANGUAGE TypeApplications #-} import Test.Hspec import Test.Hspec.QuickCheck import Test.QuickCheck import Data.Functor.Identity (Identity, runIdentity) import Data.MonadicStreamFunction import qualified Data.Vector.Storable as V import Vocoder.Dunai shrinkOne :: (a -> [a]) -> [a] -> [[a]] shrinkOne _ [] = [] shrinkOne shr (x:xs) = [ x':xs | x' <- shr x ] ++ [ x:xs' | xs' <- shrinkOne shr xs ] runMSFList :: MSF Identity a b -> [a] -> [b] runMSFList m l = runIdentity $ embed m l --equivToList :: Eq b => ([a] -> [b]) -> MSF Identity a b -> [a] -> Bool --equivToList f c xs = f xs == runMSFList c xs equivToListA :: ([[Int]] -> [[Int]]) -> MSF Identity (V.Vector Int) [V.Vector Int] -> [[Int]] -> Bool equivToListA f c xs = f xs == concat (map (map V.toList) . runMSFList c . map V.fromList $ xs) equivToListB :: ([[Int]] -> [[Int]]) -> MSF Identity [V.Vector Int] (V.Vector Int) -> [[[Int]]] -> Bool equivToListB f c xs = f (concat xs) == (map V.toList . runMSFList c . map (map V.fromList) $ xs) listFramesOf :: Int -> Int -> [[Int]] -> [[Int]] listFramesOf chunkSize hopSize input = map (\i -> take chunkSize $ drop i cInput) [0, hopSize .. length cInput - chunkSize] where cInput = concat input listSumFrames :: Int -> Int -> [[Int]] -> [[Int]] listSumFrames chunkSize hopSize input = map (\i -> take chunkSize $ drop i cOutput) [0, chunkSize .. lastLength] where cOutput = foldl1 (zipWith (+)) $ zipWith (\k l -> replicate k 0 ++ l ++ repeat 0) [0, hopSize..] input lastLength = maximum $ -1 : zipWith (\k l -> k + length l - 1) [0, hopSize..] input genBlocks :: Arbitrary a => Int -> Gen [[a]] genBlocks blockSize = resize (maximum [5, 1000 `div` blockSize]) $ listOf $ vector blockSize shrinkBlocks :: [[Int]] -> [[[Int]]] shrinkBlocks = shrinkList $ shrinkOne shrink genChunks :: Arbitrary a => Int -> Int -> Gen [[[a]]] genChunks blockM chunkSize = resize (maximum [5, 1000 `div` blockM `div` chunkSize]) $ listOf $ vectorOf blockM $ vector chunkSize shrinkChunks :: [[[Int]]] -> [[[[Int]]]] shrinkChunks = shrinkList $ shrinkOne $ shrinkOne shrink main :: IO () main = hspec $ do prop "framesOfS" $ \(Positive (Small chunkM)) (Positive (Small blockM)) (Positive (Small hopSize)) -> let blockSize = blockM * hopSize chunkSize = chunkM * hopSize in forAllShrink (genBlocks blockSize) shrinkBlocks $ equivToListA (listFramesOf chunkSize hopSize . (replicate (chunkSize - hopSize) 0 :)) (framesOfS chunkSize hopSize) prop "sumFramesS" $ \(Positive (Small chunkM)) (Positive (Small blockM)) (Positive (Small hopSize)) -> let blockSize = blockM * hopSize chunkSize = chunkM * hopSize in forAllShrink (genChunks blockM chunkSize) shrinkChunks $ \l -> equivToListB (take (length l) . listSumFrames blockSize hopSize) (sumFramesS blockSize hopSize) l