Multiple instances of degradeBy

I've noticed that when trying to use degradeBy to randomly remove notes from a pattern, across multiple tracks, it removes the same random notes from each pattern. I have a feeling this might be due to Tidalcycle's single continuous random stream.

d1 $ degradeBy 0.8 $ s "cp*8"

d2 $ degradeBy 0.8 $ s "bd*8"

I would like to use degradeBy to randomly remove different notes from each pattern. Any suggestions would be very much appreciated. Thank you.

1 Like

degradeBy is defined with a more general function _degradyByUsing.

(from: source)

-- Useful for manipulating random stream, e.g. to change 'seed'
_degradeByUsing :: Pattern Double -> Double -> Pattern a -> Pattern a
_degradeByUsing prand x p = fmap fst $ filterValues ((> x) . snd) $ (,) <$> p <* prand

You can define another degradeBy function, using a different random "seed", by doing (for example):

myDegBy = _degradeByUsing (slow 1.1 rand)

With a little more work, you can define a more general version of myDegBy that accepts an offset for a sort of random seed effect. I'll leave that as an exercise to the readers :wink:

1 Like

Thanks very much Paul, there's no chance I could have worked this out by myself.

1 Like

another common practice is to do something like

d1 $ degradeBy 0.8 $ s "cp*8"

d2 $ (128 <~) $ degradeBy 0.8 $ s "bd*8"

that could be any big number really, the bad thing about this approach is that if you do something like

d1 $ s "<bd sd cp>"
d2 $ degradeBy 0.8 $ s "arpy*16" # note "<0 2 3>"
d3 $ (151 <~) $ degradeBy 0.8 $ s "arpy*16" # note "<0 2 3>" |- note 12

the amount of cycles you shift the pattern should be a multiple of the amount of variations you have in order to be in synch with your other variations

2 Likes

Hello,
thank you for these informations.
Is it a good way to do that ?

degOffsetBy n = _degradeByUsing (slow n rand)

d1 $ degOffsetBy 2 0.5 $ s "bd*2 ~ bd"

d2 $ degOffsetBy 7 0.5 $ s "sn*2 ~ sn"

cause it seems to work like an offset but I have an error (copied below) when I try to change the value of the percentage of degradation with a midi controller like this:

d2 $ degOffsetBy 7 (cF 0 "16") $ s "sn*2 ~ sn"

the error:

Couldn't match expected type ‘Double’
with actual type ‘Pattern Double’
• In the second argument of ‘degOffsetBy’, namely ‘(cF 0 "16")’
In the expression: degOffsetBy 7 (cF 0 "16")
In the second argument of ‘($)’, namely
‘degOffsetBy 7 (cF 0 "16") $ s "sn*2 ~ sn"

I used to control the percentage of degradeBy with a midi controler without any error:

d2 $ degradeBy (cF 0 "16") $ s "sn*2 ~ sn"

What I'm missing here ?

Nice work!

Notice the definition of degradeBy uses the (mostly internal) function tParam:

degradeBy :: Pattern Double -> Pattern a -> Pattern a
degradeBy = tParam _degradeBy

_degradeBy :: Double -> Pattern a -> Pattern a
_degradeBy = _degradeByUsing rand

-- Useful for manipulating random stream, e.g. to change 'seed'
_degradeByUsing :: Pattern Double -> Double -> Pattern a -> Pattern a
_degradeByUsing prand x p = fmap fst $ filterValues ((> x) . snd) $ (,) <$> p <* prand

You'll want to use that in your definition of degOffsetBy to (basically) cast the type from Double to Pattern Double:

degOffsetBy :: Pattern Time -> Pattern Double -> Pattern a -> Pattern a
degOffsetBy n = tParam (_degradeByUsing (fast n rand))

Let me know if this doesn't work! I don't have a way to test nearby, so this is really just off the top of my head.

1 Like

Waow,
thank you very much, the cast of the type from Double to Pattern Double works when adding tParam.
I find it more efficient like this

degOffsetBy :: Pattern Time -> Pattern Double -> Pattern a -> Pattern a
degOffsetBy n = tParam (_degradeByUsing ((n ~>) rand))

Thank you @paulchannelstrip

2 Likes