Example #1
0
    def build_hct(hc_expressed_list):
        parse_str = '{'
        for t in hc_expressed_list:
            parse_str += '<' + t[0] + '> qC:4 '
        parse_str += '}'

        lge = LineGrammarExecutor()

        _, hct = lge.parse(parse_str)
        new_hct = HarmonicContextTrack()
        for hc, t in zip(hct.hc_list(), hc_expressed_list):
            duration = t[1] if isinstance(t[1], Duration) else Duration(t[1])
            new_hc = HarmonicContext(hc.tonality, hc.chord, duration)
            new_hct.append(new_hc)
        return new_hct
    def test_append(self):
        diatonic_tonality = Tonality.create(ModalityType.Major,
                                            DiatonicTone("C"))
        chord_t = TertianChordTemplate.parse('tIV')
        chord1 = chord_t.create_chord(diatonic_tonality)
        chord_t = TertianChordTemplate.parse('tV')
        chord2 = chord_t.create_chord(diatonic_tonality)
        chord_t = TertianChordTemplate.parse('tVI')
        chord3 = chord_t.create_chord(diatonic_tonality)

        hc_track = HarmonicContextTrack()
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord1, Duration(1, 2)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord2, Duration(1, 4)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord3, Duration(1, 3)))

        assert len(hc_track) == 3
        assert hc_track[Position(0)].duration == Duration(1, 2)
        assert hc_track[Position(1, 2)].duration == Duration(1, 4)
        assert hc_track[Position(3, 4)].duration == Duration(1, 3)

        print(hc_track)
Example #3
0
def build_vst_midi_list():
    """

    :return:
    """
    c = InstrumentCatalog.instance()

    # Add notes to the score
    vnote0 = Note(DiatonicPitch(4, 'a'), Duration(1, 8))
    vnote1 = Note(DiatonicPitch(4, 'b'), Duration(1, 8))
    vnote2 = Note(DiatonicPitch(4, 'c'), Duration(1, 8))
    vnote3 = Note(DiatonicPitch(4, 'd'), Duration(1, 8))
    vnote4 = Note(DiatonicPitch(4, 'e'), Duration(1, 8))
    vnote5 = Note(DiatonicPitch(4, 'f'), Duration(1, 8))

    # Set up a violin voice with 6 8th notes
    vline = Line([vnote0, vnote1, vnote2, vnote3, vnote4, vnote5])

    tempo_seq = TempoEventSequence()
    ts_seq = EventSequence()
    tempo_seq.add(TempoEvent(Tempo(60), Position(0)))
    ts_seq.add(
        TimeSignatureEvent(TimeSignature(3, Duration(1, 4), 'sww'),
                           Position(0)))

    hc_track = HarmonicContextTrack()
    diatonic_tonality = Tonality.create(ModalityType.Major, DiatonicTone("C"))
    chord_t = TertianChordTemplate.parse('tIV')
    chord = chord_t.create_chord(diatonic_tonality)
    hc_track.append(HarmonicContext(diatonic_tonality, chord, Duration(2)))

    score = Score()

    score.tempo_sequence.add(TempoEvent(Tempo(60), Position(0)))
    score.time_signature_sequence.add(
        TimeSignatureEvent(TimeSignature(3, Duration(1, 4)), Position(0)))

    violin = c.get_instrument("violin")
    violin_instrument_voice = InstrumentVoice(violin, 1)
    score.add_instrument_voice(violin_instrument_voice)
    violin_instrument_voice.voice(0).pin(vline)

    return ScoreToVstMidiConverter.convert_score(score, {0: 0}), score
Example #4
0
    def __init__(self, coverage_node_list, tempo_seq, ts_seq, hct, line):
        """
        Constructor
        :param coverage_node_list: List of note structures that are affected by on beat constraints.
        :param tempo_seq: TempoEventSequence
        :param ts_seq: EventSequence of TimeSignatures
        :param hct: HarmonicContextTrack
        :param line: Line
        """
        self.__coverage_node_list = coverage_node_list

        self.__coverage_node_aggregates = dict()
        self.__coverage_node_deltas = dict()

        # duplicate time signature event sequence
        new_ts_list = []
        for e in ts_seq.sequence_list:
            new_ts_list.append(
                TimeSignatureEvent(
                    TimeSignature(e.object.beats_per_measure,
                                  e.object.beat_duration,
                                  e.object.beat_pattern), e.time))
        self.__ts_event_sequence = EventSequence(new_ts_list)

        # duplicate tempo event sequence
        new_tempo_list = []
        for e in tempo_seq.sequence_list:
            new_tempo_list.append(
                TempoEvent(Tempo(e.object.tempo, e.object.beat_duration),
                           e.time))
        self.__tempo_event_sequence = TempoEventSequence(new_tempo_list)

        self.__line = line

        self.__hct = HarmonicContextTrack()
        for hc in hct.hc_list():
            self.__hct.append(
                HarmonicContext(hc.tonality, hc.chord, Duration(hc.duration),
                                Position(hc.position)))

        for n in self.coverage_node_list:
            self.__coverage_node_aggregates[n] = 0
            self.__coverage_node_deltas[n] = 0
Example #5
0
    def sub_hct(self, sub_track_interval=None):
        """
        Take a sub_track of this hct.
        :param sub_track_interval: NmericInterval.  If none, the entire hct.
        :return:
        """
        sub_track_interval = NumericInterval(Fraction(0), self.duration.duration) if sub_track_interval is None else \
            sub_track_interval

        new_track = HarmonicContextTrack()
        for hc in self.hc_list():
            hc_interval = NumericInterval(
                hc.position.position,
                hc.position.position + hc.duration.duration)
            hc_intersect = hc_interval.intersection(sub_track_interval)
            if hc_intersect is not None:
                new_hc = HarmonicContext(hc.tonality, hc.chord,
                                         Duration(hc_intersect.length()),
                                         Position(hc_intersect.lower))
                new_track.append(new_hc)

        return new_track
    def test_insert(self):
        diatonic_tonality = Tonality.create(ModalityType.Major,
                                            DiatonicTone("C"))
        chord_t = TertianChordTemplate.parse('tIV')
        chord = chord_t.create_chord(diatonic_tonality)

        hc_track = HarmonicContextTrack()
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord, Duration(1, 2)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord, Duration(1, 3)))
        hc_track.insert(
            Position(1, 2),
            HarmonicContext(diatonic_tonality, chord, Duration(1, 4)))

        assert len(hc_track) == 3
        assert hc_track[Position(0)].duration == Duration(1, 2)
        assert hc_track[Position(1, 2)].duration == Duration(1, 4)
        assert hc_track[Position(3, 4)].duration == Duration(1, 3)

        hc_track = HarmonicContextTrack()
        hc_track.insert(
            Position(0),
            HarmonicContext(diatonic_tonality, chord, Duration(1, 4)))
        hc_track.insert(
            Position(0),
            HarmonicContext(diatonic_tonality, chord, Duration(1, 3)))
        hc_track.insert(
            Position(0),
            HarmonicContext(diatonic_tonality, chord, Duration(1, 2)))

        assert len(hc_track) == 3
        assert hc_track[Position(0)].duration == Duration(1, 2)
        assert hc_track[Position(1, 2)].duration == Duration(1, 3)
        assert hc_track[Position(5, 6)].duration == Duration(1, 4)

        assert len(hc_track) == 3
    def test_hct_rebuild_imperfect_overlap(self):
        print('----- test_hct_rebuild_imperfect_overlap -----')
        diatonic_tonality = Tonality.create(ModalityType.Major,
                                            DiatonicTone("D"))
        chord_t_i = TertianChordTemplate.parse('tI')
        chord_i = chord_t_i.create_chord(diatonic_tonality)

        chord_t_iv = TertianChordTemplate.parse('tIV')
        chord_iv = chord_t_iv.create_chord(diatonic_tonality)

        chord_t_v = TertianChordTemplate.parse('tV')
        chord_v = chord_t_v.create_chord(diatonic_tonality)

        chord_t_vi = TertianChordTemplate.parse('tVI')
        chord_vi = chord_t_vi.create_chord(diatonic_tonality)

        hc_track = HarmonicContextTrack()
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord_i, Duration(1, 2)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord_iv, Duration(1)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord_v, Duration(1, 2)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord_vi, Duration(1)))
        TestTFlip.print_hct(hc_track)

        line_str = '{<D-Major: I> hA:5 <:IV> B  C# <:V> qD E <:VI> hF# qG A}'
        lge = LineGrammarExecutor()
        target_line, target_hct = lge.parse(line_str)
        TestTFlip.print_hct(target_hct)

        cue = DiatonicPitch(5, 'f#')

        tflip = TDiatonicReflection(target_line, target_hct, cue)

        temporal_extent = Interval(Fraction(1, 4), Fraction(9, 4))
        score_line, score_hct = tflip.apply(temporal_extent, cue)
        TestTFlip.print_notes(score_line)
        TestTFlip.print_hct(score_hct)

        notes = score_line.get_all_notes()
        assert len(notes) == 8
        assert str(notes[0].diatonic_pitch) == 'A:5'
        assert str(notes[1].diatonic_pitch) == 'C#:5'
        assert str(notes[2].diatonic_pitch) == 'B:5'
        assert str(notes[3].diatonic_pitch) == 'A:5'
        assert str(notes[4].diatonic_pitch) == 'G:5'
        assert str(notes[5].diatonic_pitch) == 'F#:5'
        assert str(notes[6].diatonic_pitch) == 'G:5'
        assert str(notes[7].diatonic_pitch) == 'A:5'

        hc_list = score_hct.hc_list()
        assert len(hc_list) == 6
        assert hc_list[0].chord.chord_template.scale_degree == 1
        assert {t[0].diatonic_symbol
                for t in hc_list[0].chord.tones} == {'D', 'F#', 'A'}
        assert hc_list[0].chord.chord_template.inversion == 1

        assert hc_list[1].chord.chord_template.scale_degree == 1
        assert {t[0].diatonic_symbol
                for t in hc_list[1].chord.tones} == {'D', 'F#', 'A'}
        assert hc_list[1].chord.chord_template.inversion == 3

        assert hc_list[2].chord.chord_template.scale_degree == 5
        assert {t[0].diatonic_symbol
                for t in hc_list[2].chord.tones} == {'E', 'A', 'C#'}
        assert hc_list[2].chord.chord_template.inversion == 3

        assert hc_list[3].chord.chord_template.scale_degree == 4
        assert {t[0].diatonic_symbol
                for t in hc_list[3].chord.tones} == {'D', 'G', 'B'}
        assert hc_list[3].chord.chord_template.inversion == 3

        assert hc_list[4].chord.chord_template.scale_degree == 3
        assert {t[0].diatonic_symbol
                for t in hc_list[4].chord.tones} == {'C#', 'F#', 'A'}
        assert hc_list[4].chord.chord_template.inversion == 3

        assert hc_list[5].chord.chord_template.scale_degree == 6
        assert {t[0].diatonic_symbol
                for t in hc_list[5].chord.tones} == {'B', 'D', 'F#'}
        assert hc_list[5].chord.chord_template.inversion == 1
    def test_mozart(self):
        print('----- Mozart -----')
        diatonic_tonality = Tonality.create(ModalityType.Major,
                                            DiatonicTone("C"))
        chort_t_i = TertianChordTemplate.parse('tI')
        chord_i = chort_t_i.create_chord(diatonic_tonality)

        chort_t_v = TertianChordTemplate.parse('tVMaj7')
        chord_v = chort_t_v.create_chord(diatonic_tonality)

        chord_t_i_1 = TertianChordTemplate.parse('tI')
        chord_i_1 = chord_t_i_1.create_chord(diatonic_tonality)

        hc_track = HarmonicContextTrack()
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord_i, Duration(1)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord_v, Duration(1, 2)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord_i_1, Duration(1, 2)))
        TestTFlip.print_hct(hc_track)

        tune = [('C:5', (1, 2)), ('E:5', (1, 4)), ('G:5', (1, 4)),
                ('B:4', (3, 8)), ('C:5', (1, 16)), ('D:5', (1, 16)),
                ('C:5', (1, 4))]
        line = TestTFlip.build_line(tune)

        cue = DiatonicPitch(5, 'd')

        tflip = TDiatonicReflection(line, hc_track, cue)

        temporal_extent = Interval(Fraction(0), Fraction(2))
        score_line, score_hct = tflip.apply(temporal_extent, cue)
        TestTFlip.print_notes(score_line)
        TestTFlip.print_hct(score_hct)

        notes = score_line.get_all_notes()
        assert len(notes) == 7
        assert str(notes[0].diatonic_pitch) == 'E:5'
        assert str(notes[1].diatonic_pitch) == 'C:5'
        assert str(notes[2].diatonic_pitch) == 'A:4'
        assert str(notes[3].diatonic_pitch) == 'F:5'
        assert str(notes[4].diatonic_pitch) == 'E:5'
        assert str(notes[5].diatonic_pitch) == 'D:5'
        assert str(notes[6].diatonic_pitch) == 'E:5'

        hc_list = score_hct.hc_list()
        assert len(hc_list) == 3
        assert hc_list[0].chord.chord_template.scale_degree == 6
        assert {t[0].diatonic_symbol
                for t in hc_list[0].chord.tones} == {'E', 'A', 'C'}
        assert hc_list[0].chord.chord_template.inversion == 3

        assert hc_list[1].chord.chord_template.scale_degree == 2
        assert {t[0].diatonic_symbol
                for t in hc_list[1].chord.tones} == {'A', 'D', 'F', 'Bb'}
        assert hc_list[1].chord.chord_template.inversion == 3

        assert hc_list[2].chord.chord_template.scale_degree == 6
        assert {t[0].diatonic_symbol
                for t in hc_list[2].chord.tones} == {'E', 'A', 'C'}
        assert hc_list[2].chord.chord_template.inversion == 3
Example #9
0
    def interpret(self, hc_list, duration=Duration(1, 4)):
        """
        Give a list of HarmonicContext's, interpret the HCExpression into a HarmonicContext.
        :param hc_list:
        :param duration:
        :return: HarmonicContext
        """
        if isinstance(self.key, str):
            key_tone = DiatonicToneCache.get_tone(self.key)
        else:
            if self.key not in range(0, len(hc_list)):
                raise Exception('@{0} not in range.'.format(self.key))
            key_tone = hc_list[self.key].tonality.diatonic_tone

        if self.key_modifier is not None:
            key_tone = self.key_modifier.get_end_tone(key_tone)

        if self.modality_index:
            if isinstance(self.modality_index, str):
                modal_index = int(self.modality_index)
            else:
                if self.modality_index not in range(0, len(hc_list)):
                    raise Exception('@{0} not in range.'.format(
                        self.modality_index))
                modal_index = hc_list[self.modality_index].tonality.modal_index
        else:
            modal_index = 0

        if isinstance(self.key_modality, str):
            modality_type = ModalityType(self.key_modality)
        else:
            if self.key_modality not in range(0, len(hc_list)):
                raise Exception('@{0} not in range.'.format(self.key_modality))
            modality_type = hc_list[self.key_modality].tonality.modality_type

        #  Note: chord_numeral is origin 1
        if isinstance(self.chord_numeral, str):
            chord_numeral = ChordTemplate.SCALE_DEGREE_MAP[self.chord_numeral]
        else:
            if self.chord_numeral not in range(0, len(hc_list)):
                raise Exception('@{0} not in range.'.format(
                    self.chord_numeral))
            chord_numeral = hc_list[
                self.chord_numeral].chord.chord_template.scale_degree

        if self.chord_type:
            if isinstance(self.chord_type, str):
                chord_type = TertianChordType.to_type(self.chord_type)
            else:
                if self.chord_type not in range(0, len(hc_list)):
                    raise Exception('@{0} not in range.'.format(
                        self.chord_type))
                chord_type = hc_list[self.chord_type].chord.chord_type
        else:
            chord_type = None

        tonality = Tonality.create(modality_type, key_tone, modal_index)
        chord_template = ChordTemplate.generic_chord_template_parse(
            ChordTemplate.SCALE_DEGREE_REVERSE_MAP[chord_numeral] +
            (str(chord_type) if chord_type else ''))
        chord = chord_template.create_chord(tonality)

        hc = HarmonicContext(tonality, chord, duration)

        return hc
    def test_simple_setup(self):
        print('--- test_simple_setup')

        line = Line()

        notes = [
            Note(DiatonicPitch.parse('a:4'), Duration(1, 4)),
            Note(DiatonicPitch.parse('b:4'), Duration(1, 4)),
            Note(DiatonicPitch.parse('c:4'), Duration(1, 4)),
            Note(DiatonicPitch.parse('d:4'), Duration(1, 4)),
            Note(DiatonicPitch.parse('e:4'), Duration(1, 2)),
            Note(DiatonicPitch.parse('f:4'), Duration(1, 2)),
        ]

        location = 0
        for note in notes:
            line.pin(note, Offset(location))
            location += note.duration.duration

        tempo_seq = TempoEventSequence()
        ts_seq = EventSequence()
        tempo_seq.add(TempoEvent(Tempo(60, Duration(1, 4)), Position(0)))
        ts_seq.add(
            TimeSignatureEvent(TimeSignature(3, Duration(1, 4), 'sww'),
                               Position(0)))

        diatonic_tonality = Tonality.create(ModalityType.Major,
                                            DiatonicTone("C"))
        chord_t = TertianChordTemplate.parse('tIV')
        chord = chord_t.create_chord(diatonic_tonality)

        hc_track = HarmonicContextTrack()
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord, Duration(1, 1)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord, Duration(1, 2)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord, Duration(1, 2)))

        c = InstrumentCatalog.instance()
        violin = c.get_instrument("violin")

        score = LiteScore(line, hc_track, violin, tempo_seq, ts_seq)

        constraints = [
            OnBeatConstraint(notes[1], BeatType.Strong),
            StepSequenceConstraint(notes, [1, 1, 1, -1, -1])
        ]

        solver = MelodicConstraintSolver.create(score, constraints)

        cheat = {notes[2]: DiatonicPitch.parse('E:5')}

        results = solver.solve(cheat)
        assert results is not None
        assert results.beat_results is not None
        assert results.pitch_results is not None

        print(len(results.beat_results))
        print(len(results.pitch_results))
        assert 1 == len(results.beat_results)
        assert 1 == len(results.pitch_results)

        new_line = results.apply(next(iter(results.beat_results)),
                                 next(iter(results.pitch_results)))
        assert new_line is not None

        print(new_line)
        all_notes = new_line.get_all_notes()
        assert 'C:5' == str(all_notes[0].diatonic_pitch)
        assert 'D:5' == str(all_notes[1].diatonic_pitch)
        assert 'E:5' == str(all_notes[2].diatonic_pitch)
        assert 'F:5' == str(all_notes[3].diatonic_pitch)
        assert 'E:5' == str(all_notes[4].diatonic_pitch)
        assert 'D:5' == str(all_notes[5].diatonic_pitch)

        assert Position(3, 4) == all_notes[1].get_absolute_position()