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
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
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
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
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
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
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
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
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 __init__(self): """ Constructor. """ self.__instrument_voices = list() # map from instrument class to the instrument voices added. self.class_map = dict() # map instrument class name to InstrumentClass self.name_class_map = dict() # HCT not utilized, TODO self.__hct = HarmonicContextTrack() self.__tempo_sequence = TempoEventSequence() self.__time_signature_sequence = TimeSignatureEventSequence()
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 _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
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
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_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)
def __init__(self, line, harmonic_context_track=None, instrument=None, tempo_seq=None, ts_seq=None): """ LiteScore constructor. :param line: Used as the single voice of the score. :param harmonic_context_track: provides the harmony for the line. :param instrument: Optionally an Instrument for the line :param tempo_seq: Optionally, a TempoEventSequence :param ts_seq: Optionally, a TimeSignatureEventSequence """ self.__line = line self.__hct = HarmonicContextTrack( ) if harmonic_context_track is None else harmonic_context_track self.__instrument = instrument self.__tempo_sequence = tempo_seq if tempo_seq is not None else TempoEventSequence( ) self.__time_signature_sequence = ts_seq if ts_seq is not None else TimeSignatureEventSequence( )
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)
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()
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
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