Exemplo n.º 1
0
 def create_track(chords, tonality):
     hc_track = HarmonicContextTrack()
     for c in chords:
         chord_t = ChordTemplate.generic_chord_template_parse(c[0])
         chord = chord_t.create_chord(tonality)
         duration = Duration(c[1]) if isinstance(c[1], int) else Duration(c[1][0], c[1][1])
         hc_track.append(HarmonicContext(tonality, chord, duration))
     return hc_track
Exemplo n.º 2
0
    def dilate_hct(self, hct):
        new_hct = HarmonicContextTrack()

        for hc in hct.hc_list():
            new_hc = HarmonicContext(
                hc.tonality, hc.chord, hc.duration *
                self.dilation_factor if self.apply_to_notes else hc.duration)
            new_hct.append(new_hc)

        return new_hct
Exemplo n.º 3
0
    def _build_target_hct(self, source_instance_hct):
        target_hct = HarmonicContextTrack()

        source_pat_hc_list = source_instance_hct.hc_list()
        target_pat_hc_list = self.substitution_pattern.target_pattern_hct.hc_list(
        )
        for hc_expr, target_pat_hc in zip(
                self.substitution_pattern.target_hc_exprs, target_pat_hc_list):
            hc = hc_expr.interpret(source_pat_hc_list, target_pat_hc.duration)
            target_hct.append(hc)

        return target_hct
Exemplo n.º 4
0
    def test_basic_setup(self):
        c = InstrumentCatalog.instance()
        violin = c.get_instrument("violin")

        # 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 = LiteScore(vline, hc_track, violin, tempo_seq, ts_seq)

        bp = score.beat_position(Position(0))
        print(bp)
        assert bp.beat_number == 0

        bp = score.beat_position(Position(5, 8))
        print(bp)
        assert bp.measure_number == 0
        assert bp.beat_number == Fraction(5, 2)
        assert int(bp.beat_number) == 2
        assert bp.beat_number - bp.beat == Fraction(1, 2)

        tse = score.time_signature_sequence.floor_event(Position(5, 8))
        assert tse is not None
        print(tse.object.beat_type(bp.beat))
        assert tse.object.beat_type(bp.beat) == BeatType.Weak
        assert bp.beat_fraction == Fraction(1, 2)

        bp = score.beat_position(Position(1, 16))
        print(bp)
        tse = score.time_signature_sequence.floor_event(Position(1, 16))
        print(tse.object.beat_type(bp.beat))
        assert tse.object.beat_type(bp.beat) == BeatType.Strong
Exemplo n.º 5
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):
            new_hc = HarmonicContext(hc.tonality, hc.chord, t[1])
            new_hct.append(new_hc)
        return new_hct
Exemplo n.º 6
0
    def build_harmonic_context_track(self):
        # Prune superfluous harmonic tags.
        new_tag_list = [tag for tag in self.harmonic_tag_list if tag.first_note is not None]
        self.harmonic_tag_list = new_tag_list

        hct = HarmonicContextTrack()
        for i in range(0, len(self.harmonic_tag_list)):
            harmonic_tag = self.harmonic_tag_list[i]
            duration = (self.harmonic_tag_list[i + 1].first_note.get_absolute_position()
                        if i < len(self.harmonic_tag_list) - 1 else Position(self.__line.duration)) - \
                       self.harmonic_tag_list[i].first_note.get_absolute_position()
            harmonic_context = HarmonicContext(harmonic_tag.tonality, harmonic_tag.chord, duration,
                                               harmonic_tag.first_note.get_absolute_position())
            hct.append(harmonic_context)
        return hct
    def test_secondary_chord(self):
        print('----- test_secondary_tonality -----')
        diatonic_tonality = Tonality.create(ModalityType.Major,
                                            DiatonicTone("C"))
        chort_t_i = TertianChordTemplate.parse('tI')
        chord_i = chort_t_i.create_chord(diatonic_tonality)

        chord_v_ii = SecondaryChordTemplate.parse('V/ii').create_chord(
            diatonic_tonality)
        chord_vi_v = SecondaryChordTemplate.parse('vi/V').create_chord(
            diatonic_tonality)

        chord_t_ii = TertianChordTemplate.parse('tii')
        chord_ii = chord_t_ii.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_ii, Duration(1)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord_vi_v, Duration(1)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord_ii, Duration(1)))
        TestTFlip.print_hct(hc_track)

        tune = [('C:5', (1, 1)), ('E:5', (1, 1)), ('E:5', (1, 1)),
                ('G:5', (1, 1))]
        line = TestTFlip.build_line(tune)

        cue = DiatonicPitch(5, 'd')

        tflip = TDiatonicReflection(line, hc_track, cue)

        temporal_extent = Interval(Fraction(0), Fraction(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) == 4
        assert str(notes[0].diatonic_pitch) == 'E:5'
        assert str(notes[1].diatonic_pitch) == 'C#:5'
        assert str(notes[2].diatonic_pitch) == 'C:5'
        assert str(notes[3].diatonic_pitch) == 'A:4'

        hc_list = score_hct.hc_list()
        assert len(hc_list) == 4
        assert hc_list[1].chord.primary_chord.chord_template.scale_degree == 7
        assert {t[0].diatonic_symbol
                for t in hc_list[1].chord.tones} == {'C#', 'E', 'G'}
        assert hc_list[1].chord.primary_chord.chord_template.inversion == 3

        assert hc_list[2].chord.primary_chord.chord_template.scale_degree == 7
        assert {t[0].diatonic_symbol
                for t in hc_list[2].chord.tones} == {'C', 'F#', 'A'}
        assert hc_list[2].chord.primary_chord.chord_template.inversion == 3
Exemplo n.º 8
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
    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
Exemplo n.º 10
0
    def _rebuild_hct(self, orig_hct, as_copy):
        hc_list = orig_hct.hc_list()
        if not as_copy:
            orig_hct.clear()
        new_hct = HarmonicContextTrack() if as_copy else orig_hct
        next_index = 0
        position = Position(0)
        if self.pre_extent is not None:
            for hc in hc_list:
                intersect = hc.extent.intersection(self.pre_extent)
                if intersect is None:
                    break
                duration = Duration(
                    min(intersect.length(), hc.duration.duration))
                new_hc = HarmonicContext(hc.tonality, hc.chord, duration,
                                         hc.position)
                new_hct.append(new_hc)
                position += new_hc.duration
                if hc.extent.upper > self.pre_extent.upper:
                    break
                next_index += 1

        for hc in islice(hc_list, next_index, None):
            intersect = hc.extent.intersection(self.temporal_extent)
            if intersect is None:
                break
            duration = Duration(intersect.length())
            if self.keep_hct:
                new_hc = HarmonicContext(hc.tonality, hc.chord, duration,
                                         position)
            else:
                f = self.__hc_flip_map[hc] if hc in self.__hc_flip_map.keys() else \
                    ChromaticPitchReflectionFunction(hc.tonality, self.cue_pitch, self.domain_pitch_range)
                new_hc = HarmonicContext(f.range_tonality,
                                         self.remap_chord(hc), duration,
                                         position)
            new_hct.append(new_hc)
            position += new_hc.duration
            if hc.extent.upper > self.temporal_extent.upper:
                break
            next_index += 1

        if self.post_extent is not None:
            for hc in islice(hc_list, next_index, None):
                intersect = hc.extent.intersection(self.post_extent)
                if intersect is None:
                    break
                duration = Duration(intersect.length())
                new_hc = HarmonicContext(hc.tonality, hc.chord, duration,
                                         position)
                new_hct.append(new_hc)
                position += new_hc.duration

        return new_hct
Exemplo n.º 11
0
    def _rebuild_hct(self, orig_hct, as_copy):
        hc_list = orig_hct.hc_list()
        if not as_copy:
            orig_hct.clear()
        new_hct = HarmonicContextTrack() if as_copy else orig_hct
        next_index = 0
        position = Position(0)
        if self.pre_extent is not None:
            for hc in hc_list:
                intersect = hc.extent.intersection(self.pre_extent)
                if intersect is None:
                    break
                duration = Duration(
                    min(intersect.length(), hc.duration.duration))
                new_hc = HarmonicContext(hc.tonality, hc.chord, duration,
                                         hc.position)
                new_hct.append(new_hc)
                position += new_hc.duration
                if hc.extent.upper > self.pre_extent.upper:
                    break
                next_index += 1

        for hc in islice(hc_list, next_index, None):
            intersect = hc.extent.intersection(self.temporal_extent)
            if intersect is None:
                break
            duration = Duration(intersect.length())
            if self.keep_hct:
                new_hc = HarmonicContext(hc.tonality, hc.chord, duration,
                                         position)
            else:
                f, range_tonality = self._build_shift_function(hc)
                # TODO: the range tonality below is incorrect.
                new_hc = HarmonicContext(
                    range_tonality, self.remap_chord(hc, f.range_tonality),
                    duration, position)
            new_hct.append(new_hc)
            position += new_hc.duration
            if hc.extent.upper > self.temporal_extent.upper:
                break
            next_index += 1

        if self.post_extent is not None:
            for hc in islice(hc_list, next_index, None):
                intersect = hc.extent.intersection(self.post_extent)
                if intersect is None:
                    break
                duration = Duration(intersect.length())
                new_hc = HarmonicContext(hc.tonality, hc.chord, duration,
                                         position)
                new_hct.append(new_hc)
                position += new_hc.duration

        return new_hct
Exemplo n.º 12
0
    def test_secondary_chord(self):
        print('----- test_secondary_tonality -----')
        diatonic_tonality = Tonality.create(ModalityType.Major,
                                            DiatonicFoundation.get_tone("C"))
        chort_t_i = TertianChordTemplate.parse('tI')
        chord_i = chort_t_i.create_chord(diatonic_tonality)

        chord_v_ii = SecondaryChordTemplate.parse('V/ii').create_chord(
            diatonic_tonality)
        chord_vi_v = SecondaryChordTemplate.parse('vi/V').create_chord(
            diatonic_tonality)

        chord_t_ii = TertianChordTemplate.parse('tii')
        chord_ii = chord_t_ii.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_ii, Duration(1)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord_vi_v, Duration(1)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord_ii, Duration(1)))
        TestTChromaticFlip.print_hct(hc_track)

        tune = [('C:5', (1, 1)), ('E:5', (1, 1)), ('E:5', (1, 1)),
                ('G:5', (1, 1))]
        line = TestTChromaticFlip.build_line(tune)

        cue = DiatonicPitch(5, 'd')

        tflip = TChromaticReflection(line, hc_track, cue)

        score_line, score_hct = tflip.apply()
        TestTChromaticFlip.print_notes(score_line)
        TestTChromaticFlip.print_hct(score_hct)
Exemplo n.º 13
0
    def _rebuild_hct(self, orig_hct):
        hc_list = orig_hct.hc_list()
        new_hct = HarmonicContextTrack()

        next_index = 0
        position = Position(0)
        if self.pre_extent is not None:
            for hc in hc_list:
                intersect = hc.extent.intersection(self.pre_extent)
                if intersect is None:
                    break
                duration = Duration(min(intersect.length(), hc.duration.duration))
                new_hc = HarmonicContext(hc.tonality, hc.chord, duration, hc.position)
                new_hct.append(new_hc)
                position += new_hc.duration
                if hc.extent.upper > self.pre_extent.upper:
                    break
                next_index += 1

        for hc in islice(hc_list, next_index, None):
            intersect = hc.extent.intersection(self.temporal_extent)
            if intersect is None:
                break
            duration = Duration(intersect.length())

            new_hc = self.rebuild_hc(hc, position, duration)
            new_hct.append(new_hc)

            # TODO: this has to be called, but not sure what side effects are necessary.
            self._build_step_shift_function(new_hc, hc)

            position += new_hc.duration
            if hc.extent.upper > self.temporal_extent.upper:
                break
            next_index += 1

        if self.post_extent is not None:
            for hc in islice(hc_list, next_index, None):
                intersect = hc.extent.intersection(self.post_extent)
                if intersect is None:
                    break
                duration = Duration(intersect.length())
                new_hc = HarmonicContext(hc.tonality, hc.chord, duration, position)
                new_hct.append(new_hc)
                position += new_hc.duration

        return new_hct
Exemplo n.º 14
0
    def test_remove(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, 4)))
        hc_track.append(
            HarmonicContext(diatonic_tonality, chord, Duration(1, 3)))

        remove_item = hc_track[Position(1, 2)]
        hc_track.remove(remove_item)

        assert len(hc_track) == 2
        assert hc_track[Position(0)].duration == Duration(1, 2)
        assert hc_track[Position(1, 2)].duration == Duration(1, 3)
Exemplo n.º 15
0
    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)
    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()
Exemplo n.º 17
0
    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
Exemplo n.º 18
0
    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
Exemplo n.º 19
0
class PositionDeltaInfo(object):
    """
    This class hold information about the movement of various note structures in a line that in sum
    make all the OnBeat constraints work. This class not only records those movements, but is able to either
    create an image of the original line with movements made, or alter the original with the movements.
    """
    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

    @property
    def coverage_node_list(self):
        return self.__coverage_node_list

    @property
    def line(self):
        return self.__line

    @property
    def hct(self):
        return self.__hct

    @property
    def ts_event_sequence(self):
        return self.__ts_event_sequence

    @property
    def tempo_event_sequence(self):
        return self.__tempo_event_sequence

    @property
    def coverage_node_deltas(self):
        return self.__coverage_node_deltas

    def line_duration(self):
        return Duration(self.correct_position(self.line.duration).position)

    def correct_position(self, position):
        # Adjust position by the set aggregates on structure.
        p_prime = Position(position)
        for cover in self.coverage_node_list:
            if cover.get_absolute_position() > p_prime:
                break
            p_prime = p_prime + self.coverage_node_deltas[cover]
        return p_prime

    def alter_at(self, cover, delta):
        self.coverage_node_deltas[cover] = delta.duration

        changed = list()
        for tse in self.ts_event_sequence.sequence_list:
            if tse.time >= self.correct_position(
                    cover.get_absolute_position()) - delta.duration:
                changed.append(tse)

        for tse in changed:
            self.ts_event_sequence.remove(tse)
            tse.time += delta
            self.ts_event_sequence.add(tse)

        changed = list()
        for te in self.tempo_event_sequence.sequence_list:
            if te.time >= self.correct_position(
                    cover.get_absolute_position()) - delta.duration:
                changed.append(te)

        for te in changed:
            self.tempo_event_sequence.remove(te)
            te.time += delta
            self.tempo_event_sequence.add(te)

        cover_start_position = self.correct_position(
            cover.get_absolute_position()) - delta.duration
        hc = self.hct[cover_start_position]
        if hc is not None:
            hc.duration = hc.duration + delta
            hc_list = self.hct.hc_list()
            index = hc_list.index(hc)
            for i in range(index + 1, len(hc_list)):
                hc_list[i].position = hc_list[i].position + delta
            self.hct.reset()

    def apply(self, line_copy=True):
        if line_copy:
            line = self.line.clone()
            line_map = self.map_lines(dict(), self.line, line)
        else:
            line = self.line
            line_map = None

        all_notes = sorted(self.line.get_all_notes(),
                           key=lambda z: z.get_absolute_position())
        delta_sum = 0
        index = 0
        while index < len(all_notes):
            note = all_notes[index]
            cover = PositionDeltaInfo._compute_cover(note)
            if cover in self.coverage_node_list:
                delta_sum += self.coverage_node_deltas[cover]

            if delta_sum != 0:
                cover_prime = line_map[cover] if line_copy else cover
                new_rel_pos = cover_prime.relative_position + delta_sum
                parent = cover_prime.parent
                parent.unpin(cover_prime)
                parent.pin(cover_prime, new_rel_pos)
            index += len(cover.get_all_notes())

        return line

    @staticmethod
    def _compute_cover(note):
        c = note
        while not isinstance(c.parent, Line):
            c = c.parent
        return c

    def map_lines(self, line_map, p1, p2):
        line_map[p1] = p2
        if isinstance(p1, AbstractNoteCollective):
            for from_note, to_note in zip(p1.sub_notes, p2.sub_notes):
                self.map_lines(line_map, from_note, to_note)
        return line_map

    def clone(self):
        c = PositionDeltaInfo(self.coverage_node_list,
                              self.tempo_event_sequence,
                              self.ts_event_sequence, self.hct, self.line)
        for n in self.coverage_node_list:
            c.__coverage_node_aggregates[n] = self.__coverage_node_aggregates[
                n]
            c.__coverage_node_deltas[n] = self.__coverage_node_deltas[n]
        return c

    def __str__(self):
        str_list = list()
        for key, value in self.coverage_node_deltas.items():
            str_list.append('{0} ==> {1}'.format(key, value))
        return '\n'.join(s for s in str_list)