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

Safe HaskellNone

Perform.Midi.Patch

Contents

Description

Description of a midi-specific instrument, as well as the runtime midi device and channel mapping.

Synopsis

Config

data Config Source #

Configuration for one instrument on a score.

Constructors

Config 

Fields

  • config_allocation :: ![(Addr, Maybe Voices)]

    An instrument may have multiple addresses assigned to it, which means that it can be multiplexed across multiple channels. In addition, multiple instruments can be allocated to overlapping addresses, which is how keyswitches work; each one is considered a separate instrument. An instrument wishing to use an address will emit an appropriate message to configure it (probably a keyswitch, possibly a program change).

    Each Addr has a count of how many simultaneous voices the addr can handle. Nothing means there's no limit.

  • config_control_defaults :: !ControlValMap

    Default controls for this instrument, will always be set unless explicitly replaced. This hopefully avoids the problem where a synthesizer starts in an undefined state. This is different from Common.config_controls in that these are meant to provide a default for synthesizer state, so these are only applied during conversion, and thus should only contain controls the MIDI instrument understands.

  • config_initialization :: !(Set Initialization)
     
  • config_settings :: !Settings
     

data Initialization Source #

Document what kinds of initialization this instrument needs. Each instrument is initialized once when the score is loaded.

Constructors

Tuning

Configure tuning with Midi.realtime_tuning.

NrpnTuning

Configure tuning with Midi.nrpn_tuning.

Midi

Send InitializePatch.

Instances

Bounded Initialization # 
Enum Initialization # 
Eq Initialization # 
Ord Initialization # 
Read Initialization # 
Show Initialization # 
Pretty.Pretty Initialization # 

type Addr = (Midi.WriteDevice, Midi.Channel) Source #

MIDI instruments are addressed by a (device, channel) pair, allocated in Config.

type Voices = Int Source #

Number of simultaneous voices a certain Addr supports, aka polyphony.

type PbRange = (Int, Int) Source #

Pitchbend range in tempered semitones below and above unity. The first integer should probably be negative.

Settings

data Settings Source #

This has instrument configuration which has built-in defaults but can also be modified per score. When the instrument is allocated, patch_defaults is copied to config_settings.

Constructors

Settings 

Fields

Patch

data Patch Source #

A Patch has information about one specific instrument. The performance Instrument and MIDI config are derived from it, via its Synth.

Constructors

Patch 

Fields

Instances

patch :: PbRange -> InstTypes.Name -> Patch Source #

Create a Patch with empty vals, to set them as needed.

default_name :: InstTypes.Name Source #

This is a convention for the default instrument of a synth. This is useful for softsynths whose patches all generally have the same config.

type CallMap = Map Attrs.Attributes Expr.Symbol Source #

Map attributes to the names of the calls they should map to. This is used by the integrator to turn score events into UI events.

Scale

data Scale Source #

Describe the tuning of a MIDI patch.

This is used both to describe a patch tuned to something other than 12TET, and to retune a 12TET patch.

The Scale is used during performance to warp played pitches to the patch's tuning. The idea is that they will warp to integral Midi.Keys that won't need any tuning and can thus all go on a single MIDI channel.

Constructors

Scale 

Fields

make_scale :: Text -> [(Midi.Key, Pitch.NoteNumber)] -> Scale Source #

Fill in non-adjacent MIDI keys by interpolating the neighboring NoteNumbers. This is because a 0 between two notes will prevent pitch slides. Another problem is that the MIDI performer has no notion of instruments that don't support certain key numbers. That could be added but it's simpler to just not have patches like that.

convert_scale Source #

Arguments

:: Scale 
-> Pitch.NoteNumber

if you want this pitch

-> Maybe Pitch.NoteNumber

play this key

scale_nns :: Maybe AttributeMap -> Scale -> [(Midi.Key, Pitch.NoteNumber)] Source #

Absolute NoteNumber for each Midi.Key to tune 12TET to this scale.

scale_offsets :: Maybe AttributeMap -> Scale -> [Maybe Pitch.NoteNumber] Source #

Relative NoteNumber offset for each Midi.Key to tune 12TET to this scale.

scale_tuning :: Maybe AttributeMap -> Scale -> [Maybe (Midi.Key, Pitch.NoteNumber)] Source #

Map the mapped keys through the scale.

Flag

data Flag Source #

Various instrument flags. Add new ones at the bottom to avoid messing up serialization.

Constructors

Triggered

Patch doesn't pay attention to duration. E.g., drum samples may not pay attention to note off. The UI can use this to create zero duration events for this patch. TODO this is actually not MIDI-specific, so it should go in Instrument.Common.

Pressure

Patch uses continuous pressure control, assigned to CC 2 (breath), instead of trigger velocity. This is used to support the dyn control. Percussive instruments like pianos map it to MIDI velocity, and continuous instruments like winds always have maximum velocity and map dyn to breath.

ConstantPitch

Notes on this instrument don't change their pitch after they start. This suppresses all pitch bending for each note. It's useful because it can be difficult to prevent pitch leakage. E.g. if a transpose signal starts after the note and the note is moved, it winds up at the end of the note.

It's a hack, but it's useful in practice. It could also go in the note generator, but it's convenient to apply it in convert because that's where the transpose signals are applied.

HoldKeyswitch

If set, a keysitch has to be held while its note is playing. Otherwise, it will just be tapped before the note starts.

ResumePlay

When playing from mid-score, scan backwards for the first overlapping notes with this instrument set and resume that note. This way you can play long notes like tambura from the middle.

UseFinalNoteOff

If there are overlapping notes with the same MIDI key, delay all NoteOffs until the final one. This is for synthesizers which turn the note off on the first one, such as Kontakt.

InitializePatch

AttributeMap

type AttributeMap = Common.AttributeMap ([Keyswitch], Maybe Keymap) Source #

This is a specialization of Common.AttributeMap for MIDI. You should use a constructor like keyswitches, which will call sort_attributes to make sure there are no overlaps.

data Keymap Source #

A Keymap corresponds to a timbre selected by MIDI key range, rather than keyswitches. Unlike a keyswitch, this doesn't change the state of the MIDI channel, so multiple keymapped notes can coexist, and keymap replaces the pitch of the note.

Constructors

UnpitchedKeymap !Midi.Key

This ignores the event's pitch and instead emits the given MIDI key. This is appropriate for drumkit style patches, with a separate unpitched timbre on each key.

PitchedKeymap !Midi.Key !Midi.Key !Midi.Key

The timbre is mapped over the inclusive MIDI key range from low to high, where the pitch of the low end of the range is given by the NoteNumber. So this transposes the event's pitch and clips it to the given range.

data Keyswitch Source #

A Keyswitch changes the timbre of a patch, but does so in a channel-global way. So overlapping notes with different keyswitches will be split into different channels, if possible.

Constructors

Keyswitch !Midi.Key 
ControlSwitch !Midi.Control !Midi.ControlValue

This keyswitch is triggered by a control change.

Aftertouch !Midi.ControlValue

This is like ControlSwitch, except send a poly aftertouch value for the note's pitch. This allows simultaneous different notes with different articulations.

keyswitches :: [(Attrs.Attributes, [Keyswitch])] -> AttributeMap Source #

An AttributeMap with just keyswitches.

single_keyswitches :: [(Attrs.Attributes, Midi.Key)] -> AttributeMap Source #

An AttributeMap with a single Midi.Key keyswitch per Attribute.

unpitched_keymap :: [(Attrs.Attributes, Midi.Key)] -> AttributeMap Source #

An AttributeMap with just unpitched keymaps.

keyswitch_on :: Midi.Key -> Keyswitch -> Midi.ChannelMessage Source #

The MIDI message to activate the given Keyswitch.

Config

data Config Source #

Configuration for one instrument on a score.

Constructors

Config 

Fields

  • config_allocation :: ![(Addr, Maybe Voices)]

    An instrument may have multiple addresses assigned to it, which means that it can be multiplexed across multiple channels. In addition, multiple instruments can be allocated to overlapping addresses, which is how keyswitches work; each one is considered a separate instrument. An instrument wishing to use an address will emit an appropriate message to configure it (probably a keyswitch, possibly a program change).

    Each Addr has a count of how many simultaneous voices the addr can handle. Nothing means there's no limit.

  • config_control_defaults :: !ControlValMap

    Default controls for this instrument, will always be set unless explicitly replaced. This hopefully avoids the problem where a synthesizer starts in an undefined state. This is different from Common.config_controls in that these are meant to provide a default for synthesizer state, so these are only applied during conversion, and thus should only contain controls the MIDI instrument understands.

  • config_initialization :: !(Set Initialization)
     
  • config_settings :: !Settings
     

data Initialization Source #

Document what kinds of initialization this instrument needs. Each instrument is initialized once when the score is loaded.

Constructors

Tuning

Configure tuning with Midi.realtime_tuning.

NrpnTuning

Configure tuning with Midi.nrpn_tuning.

Midi

Send InitializePatch.

Instances

Bounded Initialization # 
Enum Initialization # 
Eq Initialization # 
Ord Initialization # 
Read Initialization # 
Show Initialization # 
Pretty.Pretty Initialization # 

type Addr = (Midi.WriteDevice, Midi.Channel) Source #

MIDI instruments are addressed by a (device, channel) pair, allocated in Config.

type Voices = Int Source #

Number of simultaneous voices a certain Addr supports, aka polyphony.

Settings

data Settings Source #

This has instrument configuration which has built-in defaults but can also be modified per score. When the instrument is allocated, patch_defaults is copied to config_settings.

Constructors

Settings 

Fields

no_pb_range :: PbRange Source #

This is a special magic value to indicate an incomplete Settings, which is what mempty is. Normally Config should be initialized from Settings in patch_defaults, but config is used to create template allocations which are merged with the patch defaults when the allocation is created.

Patch

data Patch Source #

A Patch has information about one specific instrument. The performance Instrument and MIDI config are derived from it, via its Synth.

Constructors

Patch 

Fields

Instances

patch :: PbRange -> InstTypes.Name -> Patch Source #

Create a Patch with empty vals, to set them as needed.

default_name :: InstTypes.Name Source #

This is a convention for the default instrument of a synth. This is useful for softsynths whose patches all generally have the same config.

type CallMap = Map Attrs.Attributes Expr.Symbol Source #

Map attributes to the names of the calls they should map to. This is used by the integrator to turn score events into UI events.

Scale

data Scale Source #

Describe the tuning of a MIDI patch.

This is used both to describe a patch tuned to something other than 12TET, and to retune a 12TET patch.

The Scale is used during performance to warp played pitches to the patch's tuning. The idea is that they will warp to integral Midi.Keys that won't need any tuning and can thus all go on a single MIDI channel.

Constructors

Scale 

Fields

make_scale :: Text -> [(Midi.Key, Pitch.NoteNumber)] -> Scale Source #

Fill in non-adjacent MIDI keys by interpolating the neighboring NoteNumbers. This is because a 0 between two notes will prevent pitch slides. Another problem is that the MIDI performer has no notion of instruments that don't support certain key numbers. That could be added but it's simpler to just not have patches like that.

convert_scale Source #

Arguments

:: Scale 
-> Pitch.NoteNumber

if you want this pitch

-> Maybe Pitch.NoteNumber

play this key

tuning

scale_nns :: Maybe AttributeMap -> Scale -> [(Midi.Key, Pitch.NoteNumber)] Source #

Absolute NoteNumber for each Midi.Key to tune 12TET to this scale.

scale_offsets :: Maybe AttributeMap -> Scale -> [Maybe Pitch.NoteNumber] Source #

Relative NoteNumber offset for each Midi.Key to tune 12TET to this scale.

scale_tuning :: Maybe AttributeMap -> Scale -> [Maybe (Midi.Key, Pitch.NoteNumber)] Source #

Map the mapped keys through the scale.

Flag

data Flag Source #

Various instrument flags. Add new ones at the bottom to avoid messing up serialization.

Constructors

Triggered

Patch doesn't pay attention to duration. E.g., drum samples may not pay attention to note off. The UI can use this to create zero duration events for this patch. TODO this is actually not MIDI-specific, so it should go in Instrument.Common.

Pressure

Patch uses continuous pressure control, assigned to CC 2 (breath), instead of trigger velocity. This is used to support the dyn control. Percussive instruments like pianos map it to MIDI velocity, and continuous instruments like winds always have maximum velocity and map dyn to breath.

ConstantPitch

Notes on this instrument don't change their pitch after they start. This suppresses all pitch bending for each note. It's useful because it can be difficult to prevent pitch leakage. E.g. if a transpose signal starts after the note and the note is moved, it winds up at the end of the note.

It's a hack, but it's useful in practice. It could also go in the note generator, but it's convenient to apply it in convert because that's where the transpose signals are applied.

HoldKeyswitch

If set, a keysitch has to be held while its note is playing. Otherwise, it will just be tapped before the note starts.

ResumePlay

When playing from mid-score, scan backwards for the first overlapping notes with this instrument set and resume that note. This way you can play long notes like tambura from the middle.

UseFinalNoteOff

If there are overlapping notes with the same MIDI key, delay all NoteOffs until the final one. This is for synthesizers which turn the note off on the first one, such as Kontakt.

InitializePatch

AttributeMap

type AttributeMap = Common.AttributeMap ([Keyswitch], Maybe Keymap) Source #

This is a specialization of Common.AttributeMap for MIDI. You should use a constructor like keyswitches, which will call sort_attributes to make sure there are no overlaps.

data Keymap Source #

A Keymap corresponds to a timbre selected by MIDI key range, rather than keyswitches. Unlike a keyswitch, this doesn't change the state of the MIDI channel, so multiple keymapped notes can coexist, and keymap replaces the pitch of the note.

Constructors

UnpitchedKeymap !Midi.Key

This ignores the event's pitch and instead emits the given MIDI key. This is appropriate for drumkit style patches, with a separate unpitched timbre on each key.

PitchedKeymap !Midi.Key !Midi.Key !Midi.Key

The timbre is mapped over the inclusive MIDI key range from low to high, where the pitch of the low end of the range is given by the NoteNumber. So this transposes the event's pitch and clips it to the given range.

data Keyswitch Source #

A Keyswitch changes the timbre of a patch, but does so in a channel-global way. So overlapping notes with different keyswitches will be split into different channels, if possible.

Constructors

Keyswitch !Midi.Key 
ControlSwitch !Midi.Control !Midi.ControlValue

This keyswitch is triggered by a control change.

Aftertouch !Midi.ControlValue

This is like ControlSwitch, except send a poly aftertouch value for the note's pitch. This allows simultaneous different notes with different articulations.

keyswitches :: [(Attrs.Attributes, [Keyswitch])] -> AttributeMap Source #

An AttributeMap with just keyswitches.

single_keyswitches :: [(Attrs.Attributes, Midi.Key)] -> AttributeMap Source #

An AttributeMap with a single Midi.Key keyswitch per Attribute.

unpitched_keymap :: [(Attrs.Attributes, Midi.Key)] -> AttributeMap Source #

An AttributeMap with just unpitched keymaps.

keyswitch_on :: Midi.Key -> Keyswitch -> Midi.ChannelMessage Source #

The MIDI message to activate the given Keyswitch.