Safe Haskell | Safe-Inferred |
---|
Functions for instrument cmds. This is called CUtil because there is also Derive.Instrument.DUtil and they are usually imported together.
I need a better name than "Util" for everything.
Synopsis
- insert_call :: Cmd.M m => Thru -> [(Char, Expr.Symbol)] -> Cmd.Handler m
- strokes_to_calls :: [Drums.Stroke] -> [(Char, Expr.Symbol)]
- data Thru
- insert_expr :: Cmd.M m => Thru -> Cmd.NoteEntryMap DeriveT.Expr -> Cmd.Handler m
- to_keycap :: DeriveT.Expr -> KeycapsT.KeyDoc
- merge_kbd_entry :: a -> Cmd.NoteEntryMap a -> Cmd.NoteEntryMap a
- expr_im_thru :: Cmd.M m => Thru.ThruFunction -> DeriveT.Expr -> m [Cmd.Thru]
- eval_thru_notes :: Cmd.M m => DeriveT.Expr -> m [Thru.Note]
- expr_midi_thru :: Cmd.M m => UiMsg.KbdState -> DeriveT.Expr -> m ()
- expr_to_midi :: Cmd.M m => BlockId -> TrackId -> TrackTime -> DeriveT.Expr -> m [Midi.WriteMessage]
- keyswitches :: Cmd.M m => [(Char, Expr.Symbol, Midi.Key)] -> Cmd.Handler m
- simple_drum :: Thru -> Maybe.Maybe ScoreT.Control -> [(Drums.Stroke, Midi.Key)] -> MidiInst.Patch -> MidiInst.Patch
- drum_code :: Thru -> [(Drums.Stroke, CallConfig)] -> MidiInst.Code
- drum_code_cmd :: [(Char, Expr.Symbol)] -> Thru -> [(Drums.Stroke, CallConfig)] -> MidiInst.Code
- drum_code_ :: Thru -> [Drums.Stroke] -> MidiInst.Code
- drum_cmd :: Cmd.M m => [(Char, Expr.Symbol)] -> Thru -> [Drums.Stroke] -> Cmd.Handler m
- drum_patch :: [(Drums.Stroke, Midi.Key)] -> MidiInst.Patch -> MidiInst.Patch
- im_drum_patch :: [Drums.Stroke] -> ImInst.Patch -> ImInst.Patch
- type PitchedStrokes = [(Drums.Stroke, KeyswitchRange)]
- type KeyswitchRange = ([Patch.Keyswitch], Midi.Key, Midi.Key, Midi.Key)
- make_keymap :: Maybe.Maybe Midi.Key -> Midi.Key -> Midi.Key -> Midi.Key -> [[Attrs.Attributes]] -> Map Attrs.Attributes KeyswitchRange
- make_keymap2 :: Maybe.Maybe Midi.Key -> Midi.Key -> Midi.Key -> Midi.Key -> Midi.Key -> [[Attrs.Attributes]] -> Map Attrs.Attributes KeyswitchRange
- make_cc_keymap :: Midi.Key -> Midi.Key -> Midi.Key -> [[Attrs.Attributes]] -> Map Attrs.Attributes KeyswitchRange
- pitched_drum_patch :: PitchedStrokes -> MidiInst.Patch -> MidiInst.Patch
- make_call_map :: [Drums.Stroke] -> Common.CallMap
- pitched_attribute_map :: PitchedStrokes -> Patch.AttributeMap
- drum_pitched_strokes :: [Drums.Stroke] -> Map Attrs.Attributes KeyswitchRange -> (PitchedStrokes, ([Drums.Stroke], [Attrs.Attributes]))
- drum_calls :: [(Drums.Stroke, CallConfig)] -> [(Expr.Symbol, Generator Note)]
- pitched_strokes :: [Attrs.Attributes] -> Pitch.NoteNumber -> Attrs.Attributes -> CallConfig
- data CallConfig = CallConfig {}
- call_config :: CallConfig
- drum_call :: CallConfig -> Expr.Symbol -> Attrs.Attributes -> Generator Note
- apply_tuning_control :: NoteArgs -> ScoreT.Control -> Deriver a -> Deriver a
- resolve_strokes :: Signal.Y -> Map Attrs.Attributes KeyswitchRange -> [(Char, Expr.Symbol, Attrs.Attributes, Drums.Group)] -> (PitchedStrokes, [Text])
eval call
insert_call :: Cmd.M m => Thru -> [(Char, Expr.Symbol)] -> Cmd.Handler m Source #
strokes_to_calls :: [Drums.Stroke] -> [(Char, Expr.Symbol)] Source #
Select the flavor of thru to use when inserting an expression. This
selects either expr_midi_thru
or expr_im_thru
.
Choosing manually is silly because the valid kind of thru depends on the patch type. It's just that due to history and wanting to avoid duplicated code, the Cmd and Derive code in here doesn't care about MIDI vs. im... except for thru.
:: Cmd.M m | |
=> Thru | Evaluate the expression and emit MIDI thru. |
-> Cmd.NoteEntryMap DeriveT.Expr | |
-> Cmd.Handler m |
Create a custom kbd entry cmd that inserts tracklang expressions at the insertion point. Since this shadows the default note entry cmd, it has to handle thru on its own.
merge_kbd_entry :: a -> Cmd.NoteEntryMap a -> Cmd.NoteEntryMap a Source #
expr_im_thru :: Cmd.M m => Thru.ThruFunction -> DeriveT.Expr -> m [Cmd.Thru] Source #
eval_thru_notes :: Cmd.M m => DeriveT.Expr -> m [Thru.Note] Source #
expr_midi_thru :: Cmd.M m => UiMsg.KbdState -> DeriveT.Expr -> m () Source #
Emit MIDI thru for an arbitrary expresison.
This is more accurate and principled than what the usual kbd entry cmds do, since it reuses the deriver and performer directly, while they recreate the performer in an ad-hoc way, e.g. in Cmd.MidiThru. However, this allows them to play chords and is thus more suitable for pitched instruments. Actually, what MidiThru recreates is the channel allocation part of the performer, ultimately becasue the performer's allocator doesn't work in real time. Still, perhaps it would be possible to integrate them better than I have.
expr_to_midi :: Cmd.M m => BlockId -> TrackId -> TrackTime -> DeriveT.Expr -> m [Midi.WriteMessage] Source #
Call a note call and return the MIDI msgs it produces.
keyswitch
keyswitches :: Cmd.M m => [(Char, Expr.Symbol, Midi.Key)] -> Cmd.Handler m Source #
Create a Cmd to set keyswitches.
This simply sets the note text for subsequent notes, and also configures the instrument to play in the given keyswitch.
TODO this just emits keyswitches for every addr and emits them redundantly. This is simpler but it would be more correct to use WriteDeviceState to emit them only when needed. However, it's more complicated because then I need a current attrs (Map Instrument Attrs) along with current note text, so MidiThru can use the attrs to find the keyswitch.
TODO if I can pull the current or previous note out of the derive then I could use that to play an example note. Wait until I have a "play current line" framework up for that.
drums
simple_drum :: Thru -> Maybe.Maybe ScoreT.Control -> [(Drums.Stroke, Midi.Key)] -> MidiInst.Patch -> MidiInst.Patch Source #
Create an unpitched drum instrument. This is an instrument with an enumeration of symbols and no pitch or duration. Each key maps to its own symbol.
code
drum_code :: Thru -> [(Drums.Stroke, CallConfig)] -> MidiInst.Code Source #
Construct code from drum strokes. This is both the deriver calls to interpret the stroke names, and the cmds to enter them.
drum_code_cmd :: [(Char, Expr.Symbol)] -> Thru -> [(Drums.Stroke, CallConfig)] -> MidiInst.Code Source #
drum_code
, but with the opportunity to insert extra keys for
insert_call
. This is because insert_expr
can't be stacked, since it
consumes kbd entry keys it doesn't map, since it's confusing if it doesn't.
drum_code_ :: Thru -> [Drums.Stroke] -> MidiInst.Code Source #
drum_cmd :: Cmd.M m => [(Char, Expr.Symbol)] -> Thru -> [Drums.Stroke] -> Cmd.Handler m Source #
patch
drum_patch :: [(Drums.Stroke, Midi.Key)] -> MidiInst.Patch -> MidiInst.Patch Source #
Create a MIDI patch for the traditional kind of drum instrument where
each different stroke is mapped to a single MIDI keys. pitched_drum_patch
is the variant where each stroke has a range of keys.
im_drum_patch :: [Drums.Stroke] -> ImInst.Patch -> ImInst.Patch Source #
im is much simpler than MIDI and doesn't need all the keymap garbage.
However, like drum_patch
, this just sets patch config, the cmd and deriver
code has to be added separately, see drum_code
or drum_calls
for that.
type PitchedStrokes = [(Drums.Stroke, KeyswitchRange)] Source #
Used with pitched_attribute_map
for MIDI instruments that do the
strategy of assigning pitch ranges to each drum stroke.
type KeyswitchRange = ([Patch.Keyswitch], Midi.Key, Midi.Key, Midi.Key) Source #
(keyswitch, low, high, root_pitch). The root pitch is the pitch at the
bottom of the key range, and winds up in Patch.PitchedKeymap
.
:: Maybe.Maybe Midi.Key | Keyswitches start here. If not given, this patch doesn't use keyswitches. |
-> Midi.Key | notes start here |
-> Midi.Key | each sound is mapped over this range |
-> Midi.Key | the pitch of the bottom note of each range |
-> [[Attrs.Attributes]] | |
-> Map Attrs.Attributes KeyswitchRange |
Make a KeyswitchRange for each grouped Attributes set. Attributes in the same group get the same range and are differentiated by keyswitch.
make_keymap2 :: Maybe.Maybe Midi.Key -> Midi.Key -> Midi.Key -> Midi.Key -> Midi.Key -> [[Attrs.Attributes]] -> Map Attrs.Attributes KeyswitchRange Source #
This is like make_keymap
, except with the arguments rearranged to more
closely match the sample utils I use.
:: Midi.Key | notes start here |
-> Midi.Key | each sound is mapped over this range |
-> Midi.Key | the pitch of the bottom note of each range |
-> [[Attrs.Attributes]] | |
-> Map Attrs.Attributes KeyswitchRange |
This is like make_keymap
, except that attributes are differentiated by
a Patch.ControlSwitch
. CCs start at 102, and only groups of size >1
get a CC. Since each group is controlled by its own CC number, you can then
select each variation independently. This means any set of variations can
be played simultaneously, which is not true for keyswitches.
pitched_drum_patch :: PitchedStrokes -> MidiInst.Patch -> MidiInst.Patch Source #
Annotate a Patch with an Patch.AttributeMap
from the given
PitchedStrokes.
make_call_map :: [Drums.Stroke] -> Common.CallMap Source #
:: [Drums.Stroke] | |
-> Map Attrs.Attributes KeyswitchRange | |
-> (PitchedStrokes, ([Drums.Stroke], [Attrs.Attributes])) | Also return the strokes with no mapping (so they can't be played), and keymap ranges with no corresponding strokes (so there is no call to play them). |
Make PitchedStrokes by pairing each Drums.Stroke
with its
KeyswitchRange
.
drum_calls :: [(Drums.Stroke, CallConfig)] -> [(Expr.Symbol, Generator Note)] Source #
Create a drum_call
for each Drums.Stroke.
This should probably go in DUtil, but that would make it depend on Cmd.Instrument.Drums.
pitched_strokes :: [Attrs.Attributes] -> Pitch.NoteNumber -> Attrs.Attributes -> CallConfig Source #
For drum_calls
. If Just, only strokes which are a superset of one of
these move with the pitch, otherwise the stay at the given NoteNumber. If
Nothing, all strokes move with the pitch.
data CallConfig Source #
CallConfig | |
|
drum_call :: CallConfig -> Expr.Symbol -> Attrs.Attributes -> Generator Note Source #
This is the common deriver call that all drums and drum-like instruments use at the bottom.
apply_tuning_control :: NoteArgs -> ScoreT.Control -> Deriver a -> Deriver a Source #
util
:: Signal.Y | |
-> Map Attrs.Attributes KeyswitchRange | |
-> [(Char, Expr.Symbol, Attrs.Attributes, Drums.Group)] | (key_binding, emits_text, call_attributes, stop_group) |
-> (PitchedStrokes, [Text]) | also return errors |
Given a map describing how Attributes are mapped to the MIDI key range,
take a key binding to a PitchedStrokes
. The reason these are separate is
that the map describes how a particular patch maps attributes, while the
key binding describes the capabilities of the instrument itself.
If a mapping has Attrs.soft
, it's looked up without the soft, but gets
the given dynamic.