scamp.instruments.ScampInstrument

class scamp.instruments.ScampInstrument(name: str = None, ensemble: scamp.instruments.Ensemble = None, default_spelling_policy: scamp.spelling.SpellingPolicy = None, clef_preference='from_name')[source]

Bases: expenvelope.json_serializer.SavesToJSON

Instrument class that does the playing of the notes. Generally this will be created through one of the “new_part” methods of the Session or Ensemble class.

Parameters
Variables
  • name – name of this instrument (e.g. when printed in a score)

  • name_count – when there are multiple instruments of the same name within an Ensemble, this variable assigns each a unique index (starting with 0), to distinguish them

  • ensemble – Ensemble to which this instrument will belong.

  • playback_implementations – list of PlaybackImplementation(s) used to actually playback notes

Methods

add_osc_playback(port[, ip_address, …])

Add an OSCPlaybackImplementation for this instrument.

add_soundfont_playback([preset, soundfont, …])

Add a soundfont playback implementation for this instrument.

add_streaming_midi_playback([…])

Add a streaming MIDI playback implementation for this instrument.

change_note_parameter(note_id, param_name, …)

Changes the value of parameter of note playback over a given time; can also take a sequence of targets and times

change_note_pitch(note_id, …[, …])

Change the pitch of an already started note; can also take a sequence of targets and times.

change_note_volume(note_id, …[, …])

Change the volume of an already started note; can also take a sequence of targets and times

end_all_notes()

Ends all notes currently playing

end_note([note_id])

Ends the note with the given note id.

json_dumps()

Dump this object as a JSON string.

num_notes_playing()

Returns the number of notes currently playing.

play_chord(pitches, volume, length[, …])

Play a chord with the given pitches, volume, and length.

play_note(pitch, volume, length[, …])

Play a note on this instrument, with the given pitch, volume and length.

remove_osc_playback()

Remove the most recent OSCPlaybackImplementation from this instrument.

remove_soundfont_playback()

Remove the most recent SoundfontPlaybackImplementation from this instrument.

remove_streaming_midi_playback()

Remove the most recent MIDIStreamPlaybackImplementation from this instrument.

resolve_clef_preference()

Resolves the clef preference to a sequence of possible clef choices.

save_to_json(file_path)

Save this object to a JSON file using the given path.

send_midi_cc(cc_number, value_from_0_to_1)

Sends a midi cc message to all midi-based playback implementations, affecting all channels this instrument uses.

set_ensemble(ensemble)

Sets the ensemble that this instrument belongs to.

set_max_pitch_bend(semitones)

Set the max pitch bend for all midi playback implementations on this instrument

split_note(note_id)

Adds a split point in a note, causing it later to be rendered as tied pieces.

start_chord(pitches, volume[, properties, …])

Simple utility for starting chords without starting each note individually.

start_note(pitch, volume[, properties, …])

Start a note with the given pitch, volume, and properties

Inherited Methods

duplicate()

Returns a copy of this object by serializing to and from JSON.

json_loads(s)

Load this object from a JSON string.

load_from_json(file_path)

Load this object from a JSON file with the given path.

Attributes

clef_preference

The clef preference for this instrument.

default_spelling_policy

The default spelling policy for notes played back by this instrument.

set_ensemble(ensemble: scamp.instruments.Ensemble) → None[source]

Sets the ensemble that this instrument belongs to. Generally this happens automatically.

Parameters

ensemble – the Ensemble that this instrument should belong to.

play_note(pitch, volume, length, properties: Union[str, dict, scamp.utilities.NoteProperty] = None, blocking: bool = True, clock: clockblocks.clock.Clock = None) → None[source]

Play a note on this instrument, with the given pitch, volume and length.

Parameters
  • pitch – either a number, an Envelope, or a list used to create an Envelope. MIDI pitch values are used, with 60 representing middle C. However, microtones are allowed; for instance, a pitch of 64.7 produces an F4 30 cents flat.

  • volume – either a number, an Envelope, or a list used to create an Envelope. Volume is scaled from 0 to 1, with 0 representing silence and 1 representing max volume.

  • length – either a number (of beats), or a tuple representing a set of tied segments

  • properties

    Catch-all for a wide range of other playback and notation details that we may want to convey about a note. These details can either be given in a dictionary or a string (for greater brevity). Recognized dictionary keys are “articulation(s)”, “notehead(s)”, “notation(s)”, “text(s)”, “playback_adjustment(s)”, “key”/”spelling_policy”, “voice”, and “param_*” (for specifying arbitrary extra parameters). For example:

    properties={
         # add  staccato and tenuto articulations
        "articulations": ["staccato", "tenuto"],
        # change to an "x" notehead
        "notehead": "x",
        # add a 32-note tremolo
        "notation": "tremolo32",
        # add this text to the score by the note
        "text": "Hello there!",
        # play an octave higher (could also use a NotePlaybackAdjustment object)
        "playback_adjustment": "pitch + 12",
        # notate accidentals consistent with the key of Bb major
        "key": "Bb major",
        # place the note in voice two (named voices are also allowed)
        "voice": 2,
        # sets the "vibrato" parameter to an envelope going from 2 to 6 to 1
        # (note that extra parameters only effect playback when used with
        # a playback implementation that recognizes them)
        "param_vibrato": [2, 6, 1]
    }
    

    Since this dictionary format can be quite cumbersome, it is also possible to pass a string containing shorthand, which gets parsed into a dictionary. For example:

    properties="articulations: staccato/tenuto, harmonic, #, volume * 0.7"
    

    The comma separates different properties, and the forward slash separates multiple entries for the same property (with the exception of with the text property, since a slash could be part of the text). Properties can either be given with explicit key/value pairs (separated by colon), or a value can simply be given and the type of property will be inferred. In the above example, it is inferred that “harmonic” is a notehead, that the “#” is a desired spelling, and that “volume * 0.7” is a string to be parsed as a NotePlaybackAdjustment using its from_string() method.

    Finally, it is also possible to directly pass a SpellingPolicy, StaffText, or NotePlaybackAdjustment.

  • blocking – if True, don’t return until the note is done playing; if False, return immediately

  • clock – which clock to use. If None, capture the clock from context.

play_chord(pitches: Sequence, volume, length, properties: Union[str, dict, scamp.utilities.NoteProperty] = None, blocking: bool = True, clock: clockblocks.clock.Clock = None) → None[source]

Play a chord with the given pitches, volume, and length. Essentially, this is a convenience method that bundles together several calls to “play_note” and takes a list of pitches rather than a single pitch

Parameters
  • pitches – a list of pitches for the notes of this chord

  • volume – see play_note()

  • length – see play_note()

  • properties – see play_note(). One extra wrinkle to note with chords: if one value is given for the “notehead” property then all noteheads are set to that value. If multiple values are given, they will be assigned to individual noteheads, and there should be the same number as notes in the chord.

  • blocking – see description for “play_note”

  • clock – see description for “play_note”

start_note(pitch: float, volume: float, properties: Union[str, dict, scamp.utilities.NoteProperty] = None, clock: clockblocks.clock.Clock = None, max_volume: float = 1, flags: Sequence[str] = None)scamp.instruments.NoteHandle[source]

Start a note with the given pitch, volume, and properties

Parameters
  • pitch – the pitch / starting pitch of the note (not an Envelope)

  • volume – the volume / starting volume of the note (not an Envelope)

  • properties – see play_note()

  • clock – the clock on which to run any animation of pitch, volume, etc. If None, captures the clock from context.

  • max_volume – This is a bit of a pain, but since midi playback requires us to set the velocity at the beginning of the note, and thereafter vary volume using expression, and since expression can only make the note quieter, we need to start the note with velocity equal to the max desired volume (using expression to adjust it down to the actual start volume). The default will be 1, meaning as loud as possible, since unless we know in advance what the note is going to do, we need to be prepared to go up to full volume. Using play_note, we do actually know in advance how loud the note is going to get, so we can set max volume to the peak of the Envelope. Honestly, I wish I could separate this implementation detail from the ScampInstrument class, but I don’t see how this would be possible.

  • flags – list of strings that act as flags for how the note should be processed. Should probably be ignored by a normal user.

Returns

a NoteHandle with which to later manipulate the note

start_chord(pitches: Sequence[float], volume: float, properties: Union[str, dict, scamp.utilities.NoteProperty] = None, clock: clockblocks.clock.Clock = None, max_volume: float = 1, flags: Sequence[str] = None)scamp.instruments.ChordHandle[source]

Simple utility for starting chords without starting each note individually.

Parameters
  • pitches – a list of pitches (not Envelopes)

  • volume – see start_note()

  • properties – see play_note(). In general, properties are cloned to all members of the chord. However, noteheads can be separately defined using this syntax: “noteheads: diamond / normal / cross”

  • clock – see start_note

  • max_volume – see start_note

  • flags – see start_note

Returns

a ChordHandle, which is used to manipulate the chord thereafter. Pitch change calls on the ChordHandle are based on the first note of the chord; all other notes are shifted in parallel

change_note_parameter(note_id: Union[int, NoteHandle], param_name: str, target_value_or_values: Union[float, Sequence], transition_length_or_lengths: Union[float, Sequence] = 0, transition_curve_shape_or_shapes: Union[float, Sequence] = 0, clock: clockblocks.clock.Clock = None) → None[source]

Changes the value of parameter of note playback over a given time; can also take a sequence of targets and times

Parameters
  • note_id – which note to affect (an id or a NoteHandle)

  • param_name – name of the parameter to affect. “pitch” and “volume” are special cases

  • target_value_or_values – target value (or list of values) for the parameter

  • transition_length_or_lengths – transition time(s) in beats to the target value(s)

  • transition_curve_shape_or_shapes – curve shape(s) for the transition(s)

  • clock – which clock all of this happens on; by default, reuses the clock that the note started on.

change_note_pitch(note_id: Union[int, NoteHandle], target_value_or_values: Union[float, Sequence], transition_length_or_lengths: Union[float, Sequence] = 0, transition_curve_shape_or_shapes: Union[float, Sequence] = 0, clock: clockblocks.clock.Clock = None) → None[source]

Change the pitch of an already started note; can also take a sequence of targets and times.

Parameters
  • note_id – which note to affect (an id or a NoteHandle)

  • target_value_or_values – target value (or list of values) for the parameter

  • transition_length_or_lengths – transition time(s) in beats to the target value(s)

  • transition_curve_shape_or_shapes – curve shape(s) for the transition(s)

  • clock – which clock all of this happens on; by default, reuses the clock that the note started on.

change_note_volume(note_id: Union[int, NoteHandle], target_value_or_values: Union[float, Sequence], transition_length_or_lengths: Union[float, Sequence] = 0, transition_curve_shape_or_shapes: Union[float, Sequence] = 0, clock: clockblocks.clock.Clock = None) → None[source]

Change the volume of an already started note; can also take a sequence of targets and times

Parameters
  • note_id – which note to affect (an id or a NoteHandle)

  • target_value_or_values – target value (or list thereof) for the parameter

  • transition_length_or_lengths – transition time(s) in beats to the target value(s)

  • transition_curve_shape_or_shapes – curve shape(s) for the transition(s)

  • clock – which clock all of this happens on; “from_note” simply reuses the clock that the note started on.

split_note(note_id: Union[int, NoteHandle]) → None[source]

Adds a split point in a note, causing it later to be rendered as tied pieces.

Parameters

note_id – Which note or NoteHandle to split

end_note(note_id: Union[int, NoteHandle] = None) → None[source]

Ends the note with the given note id. If none is specified, ends oldest note started. Note that this only applies to notes started in an open-ended way with start_note(), notes created using play_note() have their lifecycle controlled automatically.

Parameters

note_id – either the id itself or a NoteHandle with that id. Default of None ends the oldest note

end_all_notes() → None[source]

Ends all notes currently playing

num_notes_playing() → int[source]

Returns the number of notes currently playing.

add_soundfont_playback(preset: Union[str, int, Sequence] = 'auto', soundfont: str = 'default', num_channels: int = 8, audio_driver: str = 'default', max_pitch_bend: int = 'default', note_on_and_off_only: bool = False)scamp.instruments.ScampInstrument[source]

Add a soundfont playback implementation for this instrument.

Parameters
  • preset – either a preset number, a tuple of (bank, preset), a string giving a name to search for in the soundfont, or the string “auto”, in which case the name of this instrument is used to search for a preset.

  • soundfont – which soundfont to use. This can be either a path to a soundfont or the name of one of the soundfonts specified in playback_settings.named_soundfonts. If this instrument belongs to an Ensemble, “default” means use the Ensemble default; if not, we will fall back to the default provided in playback_settings.

  • num_channels – how many channels to allocate for managing pitch bends, etc.

  • audio_driver – which driver to use

  • max_pitch_bend – max pitch bend to allow

  • note_on_and_off_only – This enforces a rule of no dynamic pitch bends, expression (volume) changes, or other cc messages. Valuable when using start_note() instead of play_note() in music that doesn’t do any dynamic pitch/volume/parameter changes. Without this flag, notes will all be placed on separate MIDI channels, since they could potentially change pitch or volume; with this flags, we know they won’t, so they can share the same MIDI channels, only using an extra one due to microtonality.

Returns

self, for chaining purposes

remove_soundfont_playback()scamp.instruments.ScampInstrument[source]

Remove the most recent SoundfontPlaybackImplementation from this instrument.

Returns

self, for chaining purposes

add_streaming_midi_playback(midi_output_device: Union[int, str] = 'default', num_channels: int = 8, midi_output_name: str = None, max_pitch_bend: int = 'default', note_on_and_off_only: bool = False, start_channel: int = 0)scamp.instruments.ScampInstrument[source]

Add a streaming MIDI playback implementation for this instrument.

Parameters
  • midi_output_device – name or number of the device to use

  • num_channels – how many channels to allocate for managing pitch bends, etc.

  • midi_output_name – name given to the output stream

  • max_pitch_bend – max pitch bend to allow

  • note_on_and_off_only – This enforces a rule of no dynamic pitch bends, expression (volume) changes, or other cc messages. Valuable when using start_note() instead of play_note() in music that doesn’t do any dynamic pitch/volume/parameter changes. Without this flag, notes will all be placed on separate MIDI channels, since they could potentially change pitch or volume; with this flags, we know they won’t, so they can share the same MIDI channels, only using an extra one due to microtonality.

  • start_channel – the first channel to use. For instance, if start_channel is 4, and num_channels is 5, we will use channels (4, 5, 6, 7, 8). NOTE: channel counting in SCAMP starts from 0, so this may show up as channels 5-9 in your MIDI software.

Returns

self, for chaining purposes

remove_streaming_midi_playback()scamp.instruments.ScampInstrument[source]

Remove the most recent MIDIStreamPlaybackImplementation from this instrument.

Returns

self, for chaining purposes

add_osc_playback(port: int, ip_address: str = '127.0.0.1', message_prefix: str = None, osc_message_addresses: dict = 'default')[source]

Add an OSCPlaybackImplementation for this instrument.

Parameters
  • port – port to use

  • ip_address – ip address to use

  • message_prefix – the prefix to give to all outgoing osc messages; defaults to the instrument name with all spaces removed.

  • osc_message_addresses – the specifix message addresses to be used for each type of message. Defaults are defined in playback_settings

Returns

self, for chaining purposes

remove_osc_playback()scamp.instruments.ScampInstrument[source]

Remove the most recent OSCPlaybackImplementation from this instrument.

Returns

self, for chaining purposes

set_max_pitch_bend(semitones: int) → None[source]

Set the max pitch bend for all midi playback implementations on this instrument

send_midi_cc(cc_number: int, value_from_0_to_1: float) → None[source]

Sends a midi cc message to all midi-based playback implementations, affecting all channels this instrument uses. This is useful for stuff like pedal messages, that we don’t really want to bundle with note playback, and that we want to apply to all channels.

Parameters
  • cc_number – the cc number from 0 to 127

  • value_from_0_to_1 – the value to send, normalized from 0 to 1

property clef_preference

The clef preference for this instrument. Can be any of:

  • “from_name”, which picks clef based on the instrument name

  • “default”, which uses the default clef preferences for an unknown instrument

  • the name of a clef

  • the name of an instrument whose clef defaults to use

  • a list of possible clefs. Each of these choices should be either a valid clef name string or a tuple of (valid clef name string, center pitch).

resolve_clef_preference() → Sequence[Union[str, Tuple[str, numbers.Real]]][source]

Resolves the clef preference to a sequence of possible clef choices.

property default_spelling_policy

The default spelling policy for notes played back by this instrument. (Can be set with either a SpellingPolicy or a string, which is passed to from_string())

save_to_json(file_path: str) → None[source]

Save this object to a JSON file using the given path. This uses a custom encoder that recognizes and appropriately converts any attributes that are object inheriting from SavesToJSON.

Parameters

file_path – path for saving the file

json_dumps() → str[source]

Dump this object as a JSON string. This uses a custom encoder that recognizes and appropriately converts any attributes that are object inheriting from SavesToJSON.

duplicate() → T

Returns a copy of this object by serializing to and from JSON.

classmethod json_loads(s: str) → T

Load this object from a JSON string. This uses a custom decoder that looks for a “_type” key in any object/dictionary being parsed and converts it to the class specified (assuming it a subclass of SavesToJSON).

Parameters

s – a string representing this object in JSON format

classmethod load_from_json(file_path: str) → T

Load this object from a JSON file with the given path. This uses a custom decoder that looks for a “_type” key in any object/dictionary being parsed and converts it to the class specified (assuming it a subclass of SavesToJSON).

Parameters

file_path – path for loading the file