Esempio n. 1
0
def make_note(note_attr_vals: ndarray,
              attr_name_idx_map: Mapping[str, int],
              attr_val_cast_map: Mapping[str, Any] = None):
    validate_type('note_attr_vals', note_attr_vals, ndarray)
    validate_type('attr_name_idx_map', attr_name_idx_map, Mapping)
    validate_sequence_of_type('attr_name_idx_map', attr_name_idx_map.keys(),
                              str)
    validate_optional_type('attr_val_cast_map', attr_val_cast_map, Mapping)
    if attr_val_cast_map:
        validate_optional_sequence_of_type('attr_val_cast_map',
                                           attr_val_cast_map.keys(), str)

    cls = _make_cls(attr_name_idx_map)
    note = cls()

    # Assign core attributes
    note.note_attr_vals = note_attr_vals
    note.attr_name_idx_map = attr_name_idx_map

    # Set mapping of attribute names to functions that cast return type of get() calls, e.g. cast instrument to int
    note.attr_val_cast_map = attr_val_cast_map or {}
    for attr_name in note.attr_name_idx_map:
        if attr_name not in note.attr_val_cast_map:
            note.attr_val_cast_map[attr_name] = lambda x: x
    # These are always returned as an int
    note.attr_val_cast_map['instrument'] = int
    note.attr_val_cast_map['velocity'] = int
    note.attr_val_cast_map['amplitude'] = int
    note.attr_val_cast_map['pitch'] = int
    note.attr_val_cast_map['channel'] = int

    return note
Esempio n. 2
0
    def __init__(self,
                 instruments: Sequence[str] = None,
                 sampling_rate: int = 44100,
                 ksmps: int = 100,
                 num_channels: int = 1,
                 zed_dbfs: int = 1):
        validate_sequence_of_type('instruments', instruments, str)
        validate_optional_types(
            ('sampling_rate', sampling_rate, int), ('ksmps', ksmps, int),
            ('num_channels', num_channels, int), ('zed_dbfs', zed_dbfs, int))

        # These keys should always be defined. Their values are sensible CSound defaults that can be set
        #  to other values if you know what you are doing.
        self.global_vars = {
            # Output sampling rate
            'sr': sampling_rate,
            # Ratio of output sampling rate to control rate (actual samples per control period)
            'ksmps': ksmps,
            # Number output channels (mono, stereo, quadraphonic)
            'nchnls': num_channels,
            # Value of 0 decibels, 1 means don't alert amp of output and is most compatible with plugins
            # Must be written as '0dbfs' in CSound output, but Py vars can't start with a number
            '0dbfs': zed_dbfs
        }

        self.instruments = instruments
Esempio n. 3
0
 def extend(self, to_add: List[Track]) -> 'Song':
     validate_sequence_of_type('to_add', to_add, Track)
     self.track_list.extend(to_add)
     for track in to_add:
         if track.name:
             self.track_map[track.name] = track
     return self
Esempio n. 4
0
    def remove(self, range_to_remove: Tuple[int, int]) -> 'NoteSequence':
        assert len(range_to_remove) == 2
        validate_sequence_of_type('range_to_remove', range_to_remove, int)
        # noinspection PyTupleAssignmentBalance
        range_start, range_end = range_to_remove
        self.note_attr_vals = np_delete(self.note_attr_vals, range(range_start, range_end), axis=0)

        self.update_range_map()
        return self
Esempio n. 5
0
def get_chord_pitches(mingus_keys: Sequence[str],
                      mingus_key_to_key_enum_mapping: Mapping,
                      pitch_for_key: Any, octave: int) -> Sequence[Any]:
    validate_types(('mingus_key_to_key_enum_mapping',
                    mingus_key_to_key_enum_mapping, Mapping),
                   ('octave', octave, int))
    validate_sequence_of_type('mingus_keys', mingus_keys, str)
    return [
        pitch_for_key(mingus_key_to_key_enum_mapping[mingus_key.upper()],
                      octave=octave) for mingus_key in mingus_keys
    ]
Esempio n. 6
0
 def remove(self, to_remove: Tuple[int, int]) -> 'Song':
     assert len(to_remove) == 2
     validate_sequence_of_type('to_remove', to_remove, int)
     start_range = to_remove[0]
     end_range = to_remove[1]
     assert start_range >= 0 and end_range <= len(self.track_list)
     tracks_to_remove = self.track_list[start_range:end_range]
     for track in tracks_to_remove:
         if track.name:
             del self.track_map[track.name]
     del self.track_list[start_range:end_range]
     return self
Esempio n. 7
0
    def __init__(self,
                 note_lines: Sequence[str] = None,
                 include_lines: Optional[Sequence[str]] = None,
                 header_lines: Optional[Sequence[str]] = None):
        validate_sequence_of_type('note_lines', note_lines, str)
        validate_optional_sequence_of_type('include_lines', include_lines, str)
        validate_optional_sequence_of_type('header_lines', header_lines, str)

        self.score_lines = []
        if include_lines:
            self.score_lines.extend(include_lines)
        if header_lines:
            self.score_lines.extend(header_lines)
        self.score_lines.extend(note_lines)
Esempio n. 8
0
def make_note(note_attr_vals: np.array,
              attr_name_idx_map: Mapping[str, int],
              attr_val_cast_map: Mapping[str, Any] = None) -> Any:
    # TODO THIS VALIDATION BREAKS BECAUSE numpy.array IS A FUNCTION NOT A TYPE
    # validate_type('note_attr_vals', note_attr_vals, np.array)
    validate_type('attr_name_idx_map', attr_name_idx_map, Mapping)
    validate_sequence_of_type('attr_name_idx_map', attr_name_idx_map.keys(),
                              str)
    validate_optional_type('attr_val_cast_map', attr_val_cast_map, Mapping)
    if attr_val_cast_map:
        validate_optional_sequence_of_type('attr_val_cast_map',
                                           attr_val_cast_map.keys(), str)

    cls = _make_cls(attr_name_idx_map)
    note = cls()

    # Assign core attributes
    note.note_attr_vals = note_attr_vals
    note.attr_name_idx_map = attr_name_idx_map

    # Set string formatters for note attributes, this is specific to CSound per the comments
    note.set_attr_str_formatter('instrument', lambda x: str(x))
    note.set_attr_str_formatter('start', lambda x: f'{x:.5f}')
    note.set_attr_str_formatter('duration', lambda x: f'{x:.5f}')
    note.set_attr_str_formatter('amplitude', lambda x: str(x))
    # Handle case that pitch is a float and will have rounding but that sometimes we want
    # to use it to represent fixed pitches in Western scale, e.g. 4.01 == Middle C, and other times
    # we want to use to represent arbitrary floats in Hz. The former case requires .2f precision,
    # and for the latter case we default to .5f precision but allow any precision.
    # This is DEFAULT_PITCH_PRECISION to start with. User can call setter to update the value.
    note.set_attr_str_formatter('pitch', pitch_to_str(note.pitch_precision))

    # Set mapping of attribute names to functions that cast return type of get() calls, e.g. cast instrument to int
    note.attr_val_cast_map = attr_val_cast_map or {}
    for attr_name in note.attr_name_idx_map:
        if attr_name not in note.attr_val_cast_map:
            note.attr_val_cast_map[attr_name] = lambda x: x
    # Instrument is always returned as an int
    note.attr_val_cast_map['instrument'] = int

    return note
Esempio n. 9
0
    def insert(self, index: int, to_add: Union[List[Track], Track]) -> 'Song':
        validate_type('index', index, int)

        try:
            validate_type('to_add', to_add, Track)
            self.track_list.insert(index, to_add)
            if to_add.name:
                self.track_map[to_add.name] = to_add
            return self
        except ValueError:
            pass

        validate_sequence_of_type('to_add', to_add, Track)
        for track in to_add:
            self.track_list.insert(index, track)
            # noinspection PyUnresolvedReferences
            if track.name:
                # noinspection PyUnresolvedReferences
                self.track_map[track.name] = track
            index += 1
        return self
Esempio n. 10
0
def set_notes_pitches_to_mingus_keys(mingus_keys: Sequence[str],
                                     mingus_key_to_key_enum_mapping: Mapping,
                                     notes: NoteSequence,
                                     pitch_for_key: Any,
                                     octave: int,
                                     validate=True):
    if validate:
        validate_sequence_of_type('mingus_key_list', mingus_keys, str)
        validate_types(('mingus_key_to_key_enum_mapping',
                        mingus_key_to_key_enum_mapping, Dict),
                       ('notes', notes, NoteSequence), ('octave', octave, int))
        if len(mingus_keys) != len(notes):
            raise ValueError((
                'mingus_keys and notes must have same length. '
                f'len(mingus_keys): {len(mingus_keys)} len(notes): {len(notes)}'
            ))

    for i, mingus_key in enumerate(mingus_keys):
        set_note_pitch_to_mingus_key(mingus_key,
                                     mingus_key_to_key_enum_mapping,
                                     notes[i],
                                     pitch_for_key,
                                     octave,
                                     validate=False)
Esempio n. 11
0
    def __init__(self,
                 num_notes: int = None,
                 child_sequences: Sequence['NoteSequence'] = None,
                 mn: MakeNoteConfig = None):
        validate_types(('num_notes', num_notes, int), ('num_attributes', mn.num_attributes, int),
                       ('attr_name_idx_map', mn.attr_name_idx_map, dict))
        validate_optional_type('attr_val_default_map', mn.attr_val_default_map, dict)
        validate_sequence_of_type('attr_name_idx_map', mn.attr_name_idx_map.keys(), str)
        validate_sequence_of_type('attr_name_idx_map', mn.attr_name_idx_map.values(), int)
        if mn.attr_val_default_map:
            validate_sequence_of_type('attr_vals_map', list(mn.attr_val_default_map.keys()), str)
            validate_sequence_of_type_choice('attr_vals_map', list(mn.attr_val_default_map.values()), (float, int))
        validate_optional_type_choice('child_sequences', child_sequences, (list, set))
        validate_optional_sequence_of_type('child_sequences', child_sequences, NoteSequence)

        self.mn = mn

        # Construct empty 2D numpy array of the specified dimensions. Each row stores a Note's values.
        rows = [[0.0] * self.mn.num_attributes for _ in range(num_notes)]
        self.note_attr_vals = np_array(rows)
        if num_notes > 0:
            # THIS MUST NOT BE ALTERED
            self._num_attributes = self.note_attr_vals.shape[1]

        if self.mn.attr_val_default_map:
            assert set(self.mn.attr_val_default_map.keys()) <= set(self.mn.attr_name_idx_map.keys())
            for note_attr in self.note_attr_vals:
                for attr_name, attr_val in self.mn.attr_val_default_map.items():
                    note_attr[self.mn.attr_name_idx_map[attr_name]] = attr_val

        self.child_sequences = child_sequences or []

        # Absolute index position over all sequences, that is self.note_attr_vals and the note_attr_vals of each
        # child_sequence, and, recursively, any of its child sequences.
        # So if this sequence has 10 notes and it has one child sequence with 11 notes then self.index
        # will move from 0 to 20 and then reset to 0.
        self.index = 0
        self.range_map = {0: self}
Esempio n. 12
0
 def add_score_events(self, events: Sequence[CSoundScoreEvent]):
     validate_sequence_of_type('events', events, CSoundScoreEvent)
     for event in events:
         self.add_score_event(event)
Esempio n. 13
0
 def remove(self, to_remove: Tuple[int, int]) -> 'Track':
     assert len(to_remove) == 2
     validate_sequence_of_type('to_remove', to_remove, int)
     del self.measure_list[to_remove[0]:to_remove[1]]
     return self
 def remove(self, to_remove: Tuple[int, int]) -> 'NoteSequenceSequence':
     validate_type('to_remove', to_remove, Tuple)
     validate_sequence_of_type('to_remove', to_remove, int)
     del self.note_seq_seq[to_remove[0]:to_remove[1]]
     return self
 def extend(self, seqs: Sequence[NoteSequence]) -> 'NoteSequenceSequence':
     validate_sequence_of_type('seqs', seqs, NoteSequence)
     self.note_seq_seq.extend(seqs)
     return self