Karya, built on 2018-02-23T20:23:55 (patch cf8565b7ac832266878af99a942555d139065f12)

Derive.Cache

Contents

Synopsis

# Documentation

class Cacheable d where Source #

Minimal complete definition

Methods

Instances

 # Methods # Methods # Methods

block :: (PassedArgs d -> NoteDeriver) -> PassedArgs d -> NoteDeriver Source #

If the given generator has a cache entry, relevant derivation context is the same as the cache entry's, and there is no damage under the generator, I can reuse the cached values for it. This is effectively a kind of memoization. If the generator is called, the results will be put in the cache before being returned.

Arguments

 :: Cacheable d => TrackTree.Track -> Set TrackId Children, as documented in Track. -> Deriver (Stream.Stream d) -> Deriver (Stream.Stream d)

Cache a track, but only if it's not sliced and has a TrackId.

Arguments

 :: BlockId -> TrackId -> (ScoreTime, ScoreTime) track_range must be passed explicitly because the event may have been sliced and shifted, but ControlDamage should be relative to the start of the track at ScoreTime 0. -> Deriver ControlDamage

ScoreDamage on the current track is converted into ControlDamage, and expanded to the neighbor events. This is because control calls emit samples between their previous or next events. Then this is merged with any ControlDamage inherited from callers.

If a block call is touched by control damage, the the control damage expands to cover the entire block.

Previously, this inherited damage would also be expanded to its neighbor events, under the rationale that controls can modify other controls. While this is true, it causes an annoying situation where a control track with a single call under (say) a tempo track will cause any edits to the tempo track to invalidate the entire score. This happens a lot in practice, and I've forgotten about this wrinkle a number of times

The downside, of course, is that control damage will not cause a control call that lies before its previous event to rederive, even if it should have. I'll have to see how annoying this is in practice.

Since the warp is the integral of the tempo track, damage on the tempo track will affect all events after it. Actually, the damage extends from the previous event to the end of the track, since interpolating calls extend from the previous event.

It would be simpler to have any edit invalidate the whole track, but it seems like editing a score at the end is a common case, and it would be a shame to rederive the entire score on each edit when only the very end has changed.

Get the number of cached events from a cache_hit_msg.

Get the reason from a cache_miss_msg.

# debugging

Format the cache in a hopefully readable way.

find_generator_cache :: Cacheable d => Type -> CacheKey -> Ranges -> ScoreDamage -> ControlDamage -> Cache -> Either (Bool, Text) (Collect, Stream.Stream d) Source #

Find the cached value, or a reason why there is no cache entry. This is the function that determines whether you hit the cache or not.