예제 #1
0
    # adding melody to track
    for new_note in Voice.midi_score[0]:
        if isinstance(new_note.pitch, int):
            MyMIDI.addNote(track, channel, *new_note, 100)

    strum_ending = random.choice((True, True, True, False))
    print(f"Strum ending: {strum_ending}")
    if strum_ending:
        time_shift = 0
        for voice_index, part in enumerate(Voice.midi_score[2:], 2):
            time_shift += 90
            old_midi_obj = Voice.midi_score[voice_index][-2]
            new_midi_obj = Voice.Note(
                old_midi_obj.pitch,
                old_midi_obj.time + time_shift,
                old_midi_obj.duration,
            )
            Voice.midi_score[voice_index][-2] = new_midi_obj

    # adding chords to track
    for voice_index, part in enumerate(Voice.midi_score[1:]):
        track += 1
        channel += 1
        volume = Voice.voice_volumes[voice_index]
        for new_note in part:
            if isinstance(new_note.pitch, int):
                MyMIDI.addNote(track, channel, *new_note, volume)
    """
	3/4 time sig feels slower at same tempo because 
	beats are in groups of 3 instead of 2
예제 #2
0
    def add_midi_section(self,
                         melody_section,
                         chord_start_index,
                         note_start_indices,
                         index_shift=None):
        """Add midi notes to the pitch sequence using scale degrees"""

        object_index = 0
        melodic_minor = False
        add_rest = False

        melody_section_iter = iter(melody_section)
        next_scale_group = next(melody_section_iter, None)
        for chord_index, current_scale_group in enumerate(
                melody_section, chord_start_index):

            next_scale_group = next(melody_section_iter, None)
            current_chord_name = Voice.chord_sequence[chord_index].chord_name
            if self.mode == "ionian" and current_chord_name in Chord.major_mode_alterations:
                note_alterations = Chord.major_mode_alterations[
                    current_chord_name]
            elif self.mode == "aeolian" and current_chord_name in Chord.minor_mode_alterations:
                note_alterations = Chord.minor_mode_alterations[
                    current_chord_name]
            else:
                note_alterations = {}

            if self.mode == "aeolian" and current_chord_name in self.primary_dominants:
                if melodic_minor:
                    note_alterations[5] = 1
                else:
                    # catch raised notes inbetween 2 chords
                    next_chord_name = Voice.chord_sequence[chord_index +
                                                           1].chord_name
                    if next_chord_name in self.primary_dominants:
                        affected_scale_group = current_scale_group + next_scale_group
                    else:
                        affected_scale_group = current_scale_group
                    scale_group_str = "".join(
                        str(scale_degree)
                        for scale_degree in affected_scale_group)
                    if any(str_combo in scale_group_str
                           for str_combo in ("56", "65", "-1-2", "-2-1")):
                        melodic_minor = True
                        note_alterations[5] = 1
                        print("Melodic minor!")

            for embellish_index, scale_degree in enumerate(
                    current_scale_group,
                    note_start_indices.get(chord_index, 0)):
                embellish_duration = self.finalized_rhythms[chord_index][
                    embellish_index]
                # account for negative scale degrees
                note_offset = note_alterations.get(scale_degree % 7, 0)
                embellish_fraction = Fraction(numerator=embellish_duration,
                                              denominator=self.unit_length)

                raw_note_duration = int(Voice.max_note_duration *
                                        embellish_fraction)
                # integers required for midi output

                if raw_note_duration > 960 and self.rhythm_symbols[
                        chord_index] >= 0 and self.break_notes:
                    fixed_note_duration = 960
                    add_rest = True
                    extra_duration = raw_note_duration - 960
                else:
                    fixed_note_duration = raw_note_duration

                midi_pitch = self.melody_range[scale_degree + 3] + note_offset
                if chord_index == 7 and embellish_index == 0 and self.rhythm_symbols[
                        6] == -1:
                    self.midi_notes.append(
                        Voice.Note("Rest", self.current_time,
                                   fixed_note_duration))
                    # needed all numbers in unnested sequence for validation
                    self.unnested_scale_degrees.pop(object_index + index_shift)
                else:
                    self.midi_notes.append(
                        Voice.Note(midi_pitch, self.current_time,
                                   fixed_note_duration))
                    if add_rest:
                        self.midi_notes.append(
                            Voice.Note("Rest", self.current_time + 960,
                                       extra_duration))

                self.current_time += raw_note_duration
                add_rest = False
                object_index += 1

        return object_index
예제 #3
0
    def make_accompanyment(self):
        """Rhythmically embellish chord progression"""

        if Voice.pickup:
            for _ in range(4):
                Voice.midi_score.append(
                    [Voice.Note("Rest", 0, Voice.pickup_duration)])
                Voice.chorale_scale_degrees.append([None])
        else:
            for _ in range(4):
                Voice.midi_score.append([])
                Voice.chorale_scale_degrees.append([])

        chord_accompaniments = {
            (2, 2): [
                ((960, 960), ({0, 1, 2, 3}, {})),
                ((960 * 3 // 2, 480), ({0, 1, 2, 3}, {})),
                ((480, 480, 480, 480), ({0, 1, 2, 3}, {}, {0, 1, 2, 3}, {})),
                (
                    (480, 240, 480, 240, 480),
                    ({0, 1, 2, 3}, {}, {0, 1, 2, 3}, {}, {0, 1, 2, 3}),
                ),
            ],
            (2, 3): [
                ((960, 960), ({0, 1, 2, 3}, {})),
                ((960 * 10 // 6, 960 * 2 // 6), ({0, 1, 2, 3}, {})),
                (
                    (960 * 2 // 3, 320, 960 * 2 // 3, 320),
                    ({0, 1, 2, 3}, {}, {0, 1, 2, 3}, {}),
                ),
            ],
            (3, 2): [
                ((960, 960 * 2), ({0, 1, 2, 3}, {})),
                ((960 * 2, 960), ({0, 1, 2, 3}, {})),
                (
                    (480, 480, 480, 480, 480, 480),
                    ({0, 1, 2, 3}, {}, {0, 1, 2, 3}, {}, {0, 1, 2, 3}, {}),
                ),
            ],
            (4, 2): [
                ((960, 960), ({0, 1, 2, 3}, {})),
                ((960 * 3 // 2, 480), ({0, 1, 2, 3}, {})),
                ((480, 480, 480, 480), ({0, 1, 2, 3}, {}, {0, 1, 2, 3}, {})),
                (
                    (480, 240, 480, 240, 480),
                    ({0, 1, 2, 3}, {}, {0, 1, 2, 3}, {}, {0, 1, 2, 3}),
                ),
                ((960 * 2, 960 * 2), ({0, 1, 2, 3}, {})),
            ],
            (4, 3): [((960, 960), ({0, 1, 2, 3}, {})),
                     ((960 * 10 // 6, 960 * 2 // 6), ({0, 1, 2, 3}, {})),
                     (
                         (960 * 2 // 3, 320, 960 * 2 // 3, 320),
                         ({0, 1, 2, 3}, {}, {0, 1, 2, 3}, {}),
                     ), ((960 * 2, 960 * 2), ({0, 1, 2, 3}, {}))]
        }

        chord_accompaniment = chord_accompaniments[Voice.time_sig]

        if Voice.time_sig[0] == 4:
            if Voice.chord_acceleration:
                chord_accompaniment.pop()

        note_durations, voices_used = random.choice(chord_accompaniment)

        chord_units_used = sum(note_durations) // Voice.max_note_duration
        if chord_units_used == 0:
            chord_units_used = 1
        print(f"Chord units used: {chord_units_used}")
        all_note_durations = []
        all_voices_used = []
        note_index = 0
        for _ in range(chord_units_used):
            all_note_durations.append([])
            all_voices_used.append([])
            while sum(all_note_durations[-1]) < Voice.max_note_duration:
                all_note_durations[-1].append(note_durations[note_index])
                all_voices_used[-1].append(voices_used[note_index])
                note_index += 1

        print(f"All note durations: {all_note_durations}")
        print(f"All voices used: {all_voices_used}")
        num_chords = len(Voice.chord_sequence)
        self.current_time = Voice.pickup_duration
        self.add_chord_section(0, -2, all_note_durations, all_voices_used,
                               chord_units_used)

        end_note_durations = ((Voice.max_note_duration, ),
                              (Voice.max_note_duration, ))
        end_voices_used = [[{0, 1, 2, 3}], [{}]]

        if self.repeat_ending:
            self.add_chord_section(-2 % num_chords, num_chords,
                                   all_note_durations, all_voices_used,
                                   chord_units_used)
            self.add_chord_section(-4 % num_chords, -2, all_note_durations,
                                   all_voices_used, chord_units_used)

        self.add_chord_section(-2 % num_chords, num_chords, end_note_durations,
                               end_voices_used, 2)