I wonder if there's a way to limit events based upon their duration from a previous event. So 'this sound will not sound unless it is more than .5 seconds after the previous one", etc... Like some sort of flow restrictor.
I sometimes setup scenarios with modifying functions and randomness that I like, but there might be clusters of sound events that I would like to limit in density. I only want to limit the density in those clusters however, and ideally the limiting function would be based on time (or 'closeness' in terms of a cycle) rather than something like degrade which is based on randomness
I know this might be an odd one but let me know if anything comes to mind!
ok I have tried some things and this is what I came up with:
densityFilter:: Eq a => Double -> [Event a] -> [Event a]
densityFilter density events = foldl (fi density) events [0..length events -1]
where fi density es n | length es > n = filter (\e -> e == es!!n || abs ((eventPartStart e) - (eventPartStart (es!!n))) >= toRational density ) es
| otherwise = es
lessDense :: Eq a => Double -> Pattern a -> Pattern a
lessDense density p = p {query = (densityFilter density) . query p}
you can call it like
d1 $ lessDense 0.01 $ s "hh*16"
The example above produces something kind of unexpected, so I'm not entierly sure what is happening here, but I think it should kind of do what you said. Just try it out a bit and tell me what you think. Maybe we can come up with something better
Thanks for this!! Amazing.
It seems to be working! From looking at the code it seems like the parameter is based on time (and not proximity in a cycle) right?
No, it is actually based on proximity: the parameter gives a threshold of how near two events are allowed to be, if they are to near, one of them gets removed. Here is an example:
("t t t [t*4]::Pattern Bool)
In the forth beat there are four events, so each event in that beat is a 16th, so the distance between them is 1/16. So the following wont do any filtering because there are no notes that are closer than 1/16 apart.
lessDense (1/16) ("t t t [t*4]::Pattern Bool)
But if we now consider
lessDense (1/8) ("t t t [t*4]::Pattern Bool)
It will filter out the second and fourth value of the fourth beat, since they are closer to other events than 1/8.
So the best way to read lessDense x is :filter out any events that are closer than x (a bigger x value will filter more)
sometimes it might be the case that the events aren't ordered by their start time, so it's better to sort them like this:
import Data.List(sortOn)
densityFilter:: Eq a => Double -> [Event a] -> [Event a]
densityFilter density events = foldl (fi density) events [0..length events -1]
where fi density es n | length es > n = filter (\e -> e == es!!n || abs ((eventPartStart e) - (eventPartStart (es!!n))) >= toRational density ) es
| otherwise = es
lessDense :: Eq a => Double -> Pattern a -> Pattern a
lessDense density p = p {query = (densityFilter density). sortOn whole . query p}