{-# LANGUAGE NoImplicitPrelude #-}{- |
Fast delay based on block lists.
Blocks are arrays. They are part of Haskell 98.
In contrast to ring buffers,
block lists allow infinite look ahead.
-}moduleSynthesizer.Plain.Filter.Delay.BlockwhereimportqualifiedSynthesizer.Plain.InterpolationasInterpolationimportqualifiedSynthesizer.Plain.SignalasSigimportqualifiedAlgebra.RealFieldasRealFieldimportqualifiedAlgebra.AdditiveasAdditiveimportData.Array((!),Array,listArray,elems,bounds,indices,rangeSize)importData.List(tails)importTest.QuickCheck((==>),Property)importqualifiedPreludeasPimportPreludeBaseimportNumericPreludemodulatedCore::(RealField.Ca,Additive.Cv)=>Interpolation.Tav->Int->Sig.Ta->Sig.Tv->Sig.TvmodulatedCoreipsizets=zipWith(\t(offset,bs)->let(ti,tf)=splitFraction(-t)inInterpolation.funciptf(dropBlocksToList(size+offset+ti)bs))ts.suffixIndexes.{- Using 'size' for the block size is a heuristics,
maybe it is not a good choice in many cases. -}listToBlockssizemodulated::(RealField.Ca,Additive.Cv)=>Interpolation.Tav->Int->Sig.Ta->Sig.Tv->Sig.TvmodulatedipmaxDelaytsxs=letsize=maxDelay+Interpolation.numberipinmodulatedCoreip(size-Interpolation.offsetip)ts(replicatesizezero++xs)typeBlockLista=[ArrayInta]listToBlocks::Int->Sig.Ta->BlockListalistToBlocksblockSize=map(listArray(0,blockSize-1)).takeWhile(not.null).iterate(dropblockSize)dropBlocksToList::Int->BlockLista->Sig.TadropBlocksToListnumberblocks=letdropUntilremain(b:bs)=ifremain<=snd(boundsb)then(remain,b,bs)elsedropUntil(remain-rangeSize(boundsb))bsdropUntilremain[]=(remain,listArray(0,-1)[],[])(offset,lead,suffix)=dropUntilnumberblocksinmap(lead!)[offset..(snd$boundslead)]++concatMapelemssuffixpropDrop::Int->Int->[Int]->PropertypropDropsizenxs=letinfXs=cyclexslen=1000insize>0&&n>=0&&not(nullxs)==>takelen(dropninfXs)==takelen(dropBlocksToListn(listToBlockssizeinfXs)){- |
Drop elements from a blocked list.
The offset must lie in the leading block.
-}dropSingleBlocksToList::Int->BlockLista->Sig.TadropSingleBlocksToListnumber(arr:arrs)=map(arr!)[number..(snd$boundsarr)]++concatMapelemsarrsdropSingleBlocksToList_[]=[]suffixIndexes::BlockLista->[(Int,BlockLista)]suffixIndexesxs=doblockSuffix<-init$tailsxsi<-indices$headblockSuffixreturn(i,blockSuffix)