Karya, built on Mon Jul 24 11:39:07 PDT 2017 (patch 33511aca01257b76b88de7c7a2763b7a965c084e)

Safe HaskellNone

Derive.Call.Post

Contents

Description

Post-processing utils. These are transformers that directly modify the output of a deriver, as opposed to simply modifying the Dynamic.

Unfortunately things are complicated by the presence of LEvent.Logs in the output stream. I haven't been able to figure out how to cleanly abstract that away, so I wind up with a collection of functions to handle specific kinds of maps.

There are variants for each axis:

  • monadic vs. pure
  • state vs. stateless

Synopsis

map events

non-monadic

emap1_ :: (a -> b) -> Stream.Stream a -> Stream.Stream b Source #

1:1 non-monadic map without state.

TODO this is expected to not destroy the order, but that isn't checked. That means either the event doesn't move, or it doesn't move past its neighbors.

emap1_ord_ :: (a -> Score.Event) -> Stream.Stream a -> Stream.Stream Score.Event Source #

Map on Score.Events. The function is allowed to move the events, since it sorts them afterwards.

emap1 :: (state -> a -> (state, b)) -> state -> Stream.Stream a -> (state, Stream.Stream b) Source #

1:1 non-monadic map with state.

emap :: (state -> a -> (state, [Score.Event])) -> state -> Stream.Stream a -> (state, Stream.Stream Score.Event) Source #

1:n non-monadic map with state.

emap_asc :: (state -> a -> (state, [Score.Event])) -> state -> Stream.Stream a -> (state, Stream.Stream Score.Event) Source #

monadic

apply :: ([a] -> [b]) -> Stream.Stream a -> Stream.Stream b Source #

Apply a function to the non-log events. TODO assumes the function doesn't destroy the order.

apply_m :: Functor f => ([a] -> f [b]) -> Stream.Stream a -> f (Stream.Stream b) Source #

emap_m Source #

Arguments

:: (a -> Score.Event) 
-> (state -> a -> Deriver (state, [b]))

Process an event. Exceptions are caught and logged.

-> state 
-> Stream.Stream a 
-> Deriver (state, Stream.Stream b) 

Monadic map with state. The event type is polymorphic, so you can use LEvent.zip and co. to zip up unthreaded state, constructed with control and nexts and such.

emap_asc_m Source #

Arguments

:: (a -> Score.Event) 
-> (state -> a -> Deriver (state, [Score.Event]))

Process an event. Exceptions are caught and logged.

-> state 
-> Stream.Stream a 
-> Deriver (state, Stream.Stream Score.Event) 

emap_m_ :: (a -> Score.Event) -> (a -> Deriver [b]) -> Stream.Stream a -> Deriver (Stream.Stream b) Source #

emap_m without the state.

unthreaded state

neighbors :: Stream.Stream a -> Stream.Stream ([a], a, [a]) Source #

Zip each event up with its neighbors.

neighbors_by :: Eq key => (event -> key) -> (a -> event) -> Stream.Stream a -> Stream.Stream (Maybe a, a, Maybe a) Source #

Zip each event with its nearest neighbor with the same key. A key might be Score.event_instrument, hand_key, or voice_key.

TODO it's awkward how calls that are not instrument-specific still have to choose between hand or voice when they want the next "relevant" note. Perhaps hand and voice should be merged into a single concept. They have to be distinct for the lilypond backend though.

nexts_by :: Eq key => (event -> key) -> (a -> event) -> Stream.Stream a -> Stream.Stream (a, [a]) Source #

next_by :: Eq key => (event -> key) -> (a -> event) -> Stream.Stream a -> Stream.Stream (a, Maybe a) Source #

Like neighbors_by, but only the next neighbor.

prev_by :: Eq key => (event -> key) -> (a -> event) -> Stream.Stream a -> Stream.Stream (Maybe a, a) Source #

nexts :: [a] -> [[a]] Source #

Extract subsequent events.

prevs :: [a] -> [[a]] Source #

Extract previous events.

uncurry3 :: (a -> b -> c -> d) -> (a, b, c) -> d Source #

uncurry4 :: (a -> b -> c -> d -> e) -> (a, b, c, d) -> e Source #

misc maps

map_first :: (a -> Deriver a) -> Stream.Stream a -> Deriver (Stream.Stream a) Source #

Apply a function on the first Event of an LEvent stream. TODO this shouldn't destroy the order, but it isn't checkded.

event_head :: Stream.Stream a -> (a -> Stream.Stream a -> Deriver (Stream.Stream a)) -> Deriver (Stream.Stream a) Source #

Transform the first event and the rest of the events. TODO weird function with crummy name.

signal

signal :: Monoid sig => (sig -> sig) -> Deriver (Stream.Stream sig) -> Deriver (Stream.Stream sig) Source #

Transform a pitch or control signal.

delayed events

make_delayed :: PassedArgs a -> RealTime.RealTime -> [BaseTypes.Val] -> NoteDeriver Source #

Make a delayed event.

A delayed event should be realized by an accompanying postproc call. It has an EnvKey.args, which are the arguments to the postproc call, and so it's a little bit like a closure or a delayed thunk.

It's awkward because you have to manually call the postproc, which then has to extract the args and re-typecheck them. I considered storing actual thunks as functions, and running a generic postproc which forces them, but I think each one is likely to require a different context. E.g. previous and next events for the same instrument, or with the same hand, or map over groups of events, etc. TODO wait until I have more experience.

TODO this stuff is now unused, but maybe I'll find a use for it again some day.

delayed_args :: Expr.Symbol -> Score.Event -> Maybe [BaseTypes.Val] Source #

Return the args if this is a delayed event created by the given call.

modify events

set_instrument Source #

Arguments

:: (Instrument, Instrument)

unaliased instrument name, from get_instrument

-> Score.Event 
-> Score.Event 

misc

add_event_stack :: Score.Event -> Log.Msg -> Log.Msg Source #

Like with_event_stack, but directly add the event's innermost stack to a log msg. TODO unused