I'm trying to write an implementation for a chopBy function
that would be similar to striateBy, that accepts a second parameter like striateBy
for sample length, but playing bits sequentially like chop
.
But I can't quite get the right behaviour ..
The first version I wrote:
_chopBy :: Int -> Double -> ControlPattern -> ControlPattern
_chopBy n f pat = squeezeJoin $ fmap (chopPart n f) pat
chopPart :: Int -> Double -> ValueMap -> ControlPattern
chopPart n f v = fastcat $ map (pure . rangemap v) slices
where
rangemap v (b, e) = Map.union (fromMaybe (makeMap (b,e)) $ merge v (b,e)) v
merge :: ValueMap -> (Double, Double) -> Maybe ValueMap
merge v (b, e) = do
b' <- Map.lookup "begin" v >>= getF
e' <- Map.lookup "end" v >>= getF
let d = e' - b'
return $ makeMap (b' + b*d, b' + e*d)
makeMap (b,e) = Map.fromList [("begin", VF b), ("end", VF e)]
slices = map (\i -> (slot * fromIntegral i, slot * fromIntegral i + f)) [0 .. n-1]
slot = (1 - f) / fromIntegral n
Distributes the events amongst the cycle like so:
(0>⅛)|begin: 0.0f, end: 0.16666666666666666f, s: "a"
(⅛>¼)|begin: 0.4166666666666667f, end: 0.5833333333333334f, s: "a"
(¼>⅜)|begin: 0.0f, end: 0.16666666666666666f, s: "b"
(⅜>½)|begin: 0.4166666666666667f, end: 0.5833333333333334f, s: "b"
(½>⅝)|begin: 0.0f, end: 0.16666666666666666f, s: "c"
(⅝>¾)|begin: 0.4166666666666667f, end: 0.5833333333333334f, s: "c"
(¾>⅞)|begin: 0.0f, end: 0.16666666666666666f, s: "d"
(⅞>1)|begin: 0.4166666666666667f, end: 0.5833333333333334f, s: "d"
But the expected output should evenly divide each part by the specified length, but it looks like the calculation for b
and e
in rangemap
is not handling the positions correctly
I rewrote to try and correct the slicing logic so that each part starts where the previous one ended
chopPart :: Int -> Double -> ValueMap -> ControlPattern
chopPart n f v = fastcat $ map (pure . rangemap v) slices
where
rangemap v (b, e) = Map.union (fromMaybe (makeMap (b, e)) $ merge v (b, e)) v
merge :: ValueMap -> (Double, Double) -> Maybe ValueMap
merge v (b, e) = do
b' <- Map.lookup "begin" v >>= getF
e' <- Map.lookup "end" v >>= getF
let d = e' - b'
return $ makeMap (b' + b * d, b' + e * d)
makeMap (b, e) = Map.fromList [("begin", VF b), ("end", VF e)]
slices = map (\i -> (i * slot, i * slot + f)) [0 .. fromIntegral (n - 1)]
slot = f
which is outputting:
(0>⅛)|begin: 0.0f, end: 0.16666666666666666f, s: "a"
(⅛>¼)|begin: 0.16666666666666666f, end: 0.3333333333333333f, s: "a"
(¼>⅜)|begin: 0.0f, end: 0.16666666666666666f, s: "b"
(⅜>½)|begin: 0.16666666666666666f, end: 0.3333333333333333f, s: "b"
(½>⅝)|begin: 0.0f, end: 0.16666666666666666f, s: "c"
(⅝>¾)|begin: 0.16666666666666666f, end: 0.3333333333333333f, s: "c"
(¾>⅞)|begin: 0.0f, end: 0.16666666666666666f, s: "d"
(⅞>1)|begin: 0.16666666666666666f, end: 0.3333333333333333f, s: "d"
still not quite the expected behaviour.. and not quite sure where to go next?