def recursive_dilate(self, strct, new_to_old_map): if isinstance(strct, Note): d = strct.base_duration.duration / strct.contextual_reduction_factor n = Note(strct.diatonic_pitch, Duration(d * self.dilation_factor), strct.num_dots) new_to_old_map[n] = strct return n else: collect = list() for s in strct.sub_notes: collect.append(self.recursive_dilate(s, new_to_old_map)) if isinstance(strct, Beam): b = Beam(collect) new_to_old_map[b] = strct return b elif isinstance(strct, Tuplet): t = Tuplet(strct.unit_duration * self.dilation_factor, strct.unit_duration_factor, collect) new_to_old_map[t] = strct return t elif isinstance(strct, Line): line = Line() new_to_old_map[line] = strct for s in collect: line.pin( s, new_to_old_map[s].relative_position * self.dilation_factor) return line
def test_simple_motif(self): line = Line() notes = [ Note(DiatonicPitch.parse('C:4'), Duration(1, 4)), Note(DiatonicPitch.parse('D:4'), Duration(1, 8)), Note(DiatonicPitch.parse('E:4'), Duration(1, 8)), Note(DiatonicPitch.parse('F#:4'), Duration(1, 2)), ] line.pin(notes) c = [ EqualPitchConstraint([notes[0], notes[2]]), NotEqualPitchConstraint([notes[1], notes[3]]) ] nm = Phrase(notes, c, 'B') print(nm) assert nm.name == 'B' actors = nm.actors assert len(actors) == 4 cc = nm.constraints assert isinstance(cc[0], EqualPitchConstraint) cc_a = cc[0].actors assert len(cc_a) == 2 assert cc_a[0] == actors[0] assert cc_a[1] == actors[2] assert isinstance(cc[1], NotEqualPitchConstraint) cc_b = cc[1].actors assert len(cc_a) == 2 assert cc_b[0] == actors[1] assert cc_b[1] == actors[3] assert 'F#:4' == str(actors[3].diatonic_pitch) # More notes for copy to: first_note = Note(DiatonicPitch.parse('C:3'), Duration(1, 4)) notes1 = [ first_note, Note(DiatonicPitch.parse('D:3'), Duration(1, 8)), Note(DiatonicPitch.parse('E:3'), Duration(1, 8)), Note(DiatonicPitch.parse('F#:3'), Duration(1, 2)), ] line.pin(notes1, Offset(2)) nm_clone = nm.copy_to(first_note) assert isinstance(nm_clone, Phrase) assert nm_clone.name == 'B' c_actors = nm_clone.actors assert len(c_actors) == 4 assert 'F#:3' == str(c_actors[3].diatonic_pitch)
def test_compute_with_minor_key(self): print('-- test_compute_with_minor_key ---') line = Line() f = GenericUnivariatePitchFunction( TestFitPitchToFunctionConstraint.sinasoidal, Position(0), Position(2)) v_notes = [ Note(DiatonicPitch.parse('A:4'), Duration(1, 16)) for _ in range(0, 33) ] for i in range(0, 33): line.pin(v_notes[i], Offset(i, 16)) constraint, lower_policy_context = \ TestFitPitchToFunctionConstraint.build_simple_constraint(v_notes[0], f, ModalityType.NaturalMinor, 'C', 'tV') constraints = list() constraints.append(constraint) for i in range(1, 33): c, _ = \ TestFitPitchToFunctionConstraint.build_simple_constraint(v_notes[i], f, ModalityType.NaturalMinor, 'C', 'tV') constraints.append(c) p_map = PMap() p_map[v_notes[0]] = ContextualNote(lower_policy_context) results = constraint.values(p_map, v_notes[0]) assert results is not None assert len(results) == 1 print(next(iter(results)).diatonic_pitch) assert 'C:4' == str(next(iter(results)).diatonic_pitch) result_pitches = [] for i in range(0, 33): p_map = PMap() p_map[v_notes[i]] = ContextualNote(lower_policy_context) results = constraints[i].values(p_map, v_notes[i]) result_pitches.append(next(iter(results)).diatonic_pitch) assert len(result_pitches) == 33 for i in range(0, 33): print('[{0}] {1}'.format(i, str(result_pitches[i]))) checks = [ 'C:4', 'G:4', 'D:5', 'F:5', 'G:5', 'F:5', 'D:5', 'G:4', 'C:4' ] for i in range(0, len(checks)): assert checks[i] == str(result_pitches[i])
def test_two_voices(self): print('test two voices') c = InstrumentCatalog.instance() violin = c.get_instrument("violin") note0 = Note(DiatonicPitch(4, 'a'), Duration(1, 8)) note1 = Note(DiatonicPitch(4, 'b'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) tuplet = Tuplet(Duration(1, 8), 2, [note0, note1, note2]) note3 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) note4 = Note(DiatonicPitch(4, 'e'), Duration(1, 8)) subbeam = Beam([note3, note4]) beam = Beam(subbeam) line1 = Line([tuplet, beam]) print(line1) notee0 = Note(DiatonicPitch(5, 'a'), Duration(1, 8)) notee1 = Note(DiatonicPitch(5, 'b'), Duration(1, 8), 1) notee2 = Note(DiatonicPitch(5, 'c'), Duration(1, 8)) notee3 = Note(DiatonicPitch(5, 'd'), Duration(1, 16)) line2 = Line([notee0, notee1, notee2]) line2.pin(notee3, Offset(1, 2)) print(line2) voice = Voice(violin) voice.pin(line1, Offset(1, 4)) voice.pin(line2, Offset(0, 1)) print(voice) interval = Interval(Position(1, 2), Position(1)) notes = voice.get_notes_by_interval(interval) assert len(notes) == 3 assert TestVoice.has_pitch(notes, DiatonicPitch.parse('D:4')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('E:4')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('D:5')) interval = Interval(Position(1, 4), Position(7, 16)) notes = voice.get_notes_by_interval(interval) assert len(notes) == 5 assert TestVoice.has_pitch(notes, DiatonicPitch.parse('A:4')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('B:4')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('C:4')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('B:5')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('C:5'))
def test_pin(self): print('----- test_pin -----') l1_notes = [Note(DiatonicPitch(4, y), Duration(1, 8)) for y in 'abcd'] l2_notes = [Note(DiatonicPitch(4, y), Duration(1, 8)) for y in 'efgab'] line = Line() line.pin(Line(l1_notes), Offset(1, 8)) line.pin(Line(l2_notes), Offset(1, 4)) all_notes = line.get_all_notes() print('... pinned notes ...') for n in all_notes: print('({0}) : {1}'.format(n.get_absolute_position(), n.diatonic_pitch)) print('... end pinned notes ...') print('End test_pin')
def test_add_notes_to_tuplet(self): c = InstrumentCatalog.instance() violin = c.get_instrument("violin") note0 = Note(DiatonicPitch(4, 'a'), Duration(1, 8)) note1 = Note(DiatonicPitch(4, 'b'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note3 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) beam = Beam([note0, note1]) line = Line() line.pin(beam, Offset(1, 2)) voice = Voice(violin) voice.pin(line, Offset(0)) tuplet = Tuplet(Duration(1, 8), 3, [note2, note3]) beam.append(tuplet) notee0 = Note(DiatonicPitch(5, 'a'), Duration(1, 8)) tuplet.append(notee0) print(voice) notes = voice.get_notes_starting_in_interval( Interval(Position(1, 2), Position(5, 4))) assert len(notes) == 5 assert TestVoice.has_pitch(notes, DiatonicPitch.parse('A:5')) beam_prime = beam.clone() notes = beam_prime.get_all_notes() AbstractNote.print_structure(beam_prime) assert notes[0].duration == Duration(1, 8) assert str(notes[0].diatonic_pitch) == 'A:4' line_prime = line.clone() notes = line_prime.get_all_notes() AbstractNote.print_structure(line_prime) assert notes[0].duration == Duration(1, 8) assert str(notes[0].diatonic_pitch) == 'A:4' assert notes[2].duration == Duration(1, 8) assert str(notes[2].diatonic_pitch) == 'C:4'
def test_line_structures(self): print('----- test line structures -----') source_instance_expression = '{<C-Major:I> iC:4 D E F G A B C:5 D E F G} }' lge = LineGrammarExecutor() source_instance_line, source_instance_hct = lge.parse(source_instance_expression) notes = source_instance_line.get_all_notes() line = Line() line.pin(notes[0], Offset(Fraction(1, 2))) line.pin(notes[1], Offset(Fraction(3, 4))) line1 = Line() line1.pin(notes[3], Offset(Fraction(1, 4))) line1.pin(notes[4], Offset(Fraction(1, 2))) line.pin(line1, Offset(Fraction(2))) lite_score = TestTDilation.create_score_1(line, source_instance_hct, 'piano', (4, 4, 'swww')) trans = TDilation(lite_score) new_score = trans.apply(Fraction(2), False, True) all_notes = new_score.line.get_all_notes() assert all_notes[2].get_absolute_position().position == Fraction(9, 2) print(line) print(new_score.line)
def test_add_notes_to_line(self): c = InstrumentCatalog.instance() violin = c.get_instrument("violin") note0 = Note(DiatonicPitch(4, 'a'), Duration(1, 8)) note1 = Note(DiatonicPitch(4, 'b'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note3 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) line = Line() line.pin(note0, Offset(1, 4)) line.pin(note1, Offset(3, 8)) line.pin(note2, Offset(1, 2)) line.pin(note3, Offset(5, 8)) voice = Voice(violin) voice.pin(line, Offset(0)) notee0 = Note(DiatonicPitch(5, 'a'), Duration(1, 8)) notee1 = Note(DiatonicPitch(5, 'b'), Duration(1, 8)) line.pin([notee0, notee1], Offset(3, 4)) notes = voice.get_notes_starting_in_interval( Interval(Position(5, 8), Position(2, 1))) assert len(notes) == 3 assert TestVoice.has_pitch(notes, DiatonicPitch.parse('D:4')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('A:5')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('B:5'))
def test_book_example(self): print('----- book_example -----') voice_line = Line() melody_line = Line() melody_1 = Line( [Note(DiatonicPitch(4, y), Duration(1, 8)) for y in 'aceg']) melody_2 = Line( [Note(DiatonicPitch(4, y), Duration(1, 8)) for y in 'cadg']) base_line = Line( [Note(DiatonicPitch(4, y), Duration(1, 4)) for y in 'dddddddd']) melody_line.pin(melody_1, Offset(1, 8)) melody_line.pin(melody_2, Offset(1, 4)) voice_line.pin(melody_line) voice_line.pin(base_line) print(voice_line) all_notes = voice_line.get_all_notes() print('... pinned notes ...') for n in all_notes: print('({0}) : {1}'.format(n.get_absolute_position(), n.diatonic_pitch)) print('... end pinned notes ...') print('End test_pin')
def test_add_notes_to_two_level_line(self): score = Score() catalogue = InstrumentCatalog.instance() score.add_instrument_voice( InstrumentVoice(catalogue.get_instrument("violin"))) # 1 beat == 1 sec, 3/4 TS + 60 beats per minute, score.tempo_sequence.add(TempoEvent(Tempo(60), Position(0))) score.time_signature_sequence.add( TimeSignatureEvent(TimeSignature(3, Duration(1, 4)), Position(0))) violin_voice = score.get_instrument_voice("violin")[0] top_line = Line( [Note(DiatonicPitch(4, y), Duration(1, 8)) for y in 'afdecd']) violin_voice.voice(0).pin(top_line, Offset(0)) level1_line = Line( [Note(DiatonicPitch(5, y), Duration(1, 8)) for y in 'af']) top_line.pin(level1_line, Offset(2)) level2_line = Line( [Note(DiatonicPitch(6, y), Duration(1, 8)) for y in 'de']) level1_line.pin(level2_line, Offset(1))
def test_overlap_vs_start(self): c = InstrumentCatalog.instance() violin = c.get_instrument("violin") note0 = Note(DiatonicPitch(4, 'a'), Duration(1, 8)) note1 = Note(DiatonicPitch(4, 'b'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note3 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) line = Line() line.pin(note0, Offset(1, 4)) line.pin(note1, Offset(3, 8)) line.pin(note2, Offset(1, 2)) line.pin(note3, Offset(5, 8)) voice = Voice(violin) voice.pin(line, Offset(0)) interval = Interval(Position(5, 16), Position(5, 8)) notes = voice.get_notes_by_interval(interval) assert len(notes) == 3 assert TestVoice.has_pitch(notes, DiatonicPitch.parse('A:4')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('B:4')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('C:4')) notes = voice.get_notes_starting_in_interval(interval) assert len(notes) == 2 assert TestVoice.has_pitch(notes, DiatonicPitch.parse('B:4')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('C:4')) notee0 = Note(DiatonicPitch(5, 'a'), Duration(1, 2)) notee1 = Note(DiatonicPitch(5, 'b'), Duration(1, 2)) line1 = Line() line1.pin([notee0, notee1], Offset(0)) voice.pin(line1, Offset(1, 4)) notes = voice.get_notes_by_interval(interval) assert len(notes) == 4 assert TestVoice.has_pitch(notes, DiatonicPitch.parse('A:4')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('B:4')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('C:4')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('A:5')) notes = voice.get_notes_by_interval(interval, line1) assert len(notes) == 1 assert TestVoice.has_pitch(notes, DiatonicPitch.parse('A:5')) notes = voice.get_notes_starting_in_interval(interval) assert len(notes) == 2 assert TestVoice.has_pitch(notes, DiatonicPitch.parse('B:4')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('C:4')) notes = voice.get_notes_starting_in_interval( Interval(Position(1, 8), Position(3, 8)), line1) assert len(notes) == 1 assert TestVoice.has_pitch(notes, DiatonicPitch.parse('A:5'))
def test_compute_simple_function_tone(self): print('--- test_compute_simple_function_tone ---') line = Line() f = GenericUnivariatePitchFunction( TestFitPitchToFunctionConstraint.sinasoidal, Position(0), Position(2)) v_note = Note(DiatonicPitch.parse('A:4'), Duration(1, 32)) line.pin(v_note, Offset(0)) constraint, lower_policy_context = TestFitPitchToFunctionConstraint.build_simple_constraint( v_note, f, ModalityType.Major, 'G', 'tV') p_map = PMap() p_map[v_note] = ContextualNote(lower_policy_context) results = constraint.values(p_map, v_note) assert results is not None assert len(results) == 1 print(next(iter(results)).diatonic_pitch) assert 'C:4' == str(next(iter(results)).diatonic_pitch) v_note = Note(DiatonicPitch.parse('A:4'), Duration(1, 32)) line.pin(v_note, Offset(1, 32)) constraint, lower_policy_context = TestFitPitchToFunctionConstraint.build_simple_constraint( v_note, f, ModalityType.Major, 'G', 'tV') p_map = PMap() p_map[v_note] = ContextualNote(lower_policy_context) results = constraint.values(p_map, v_note) assert results is not None assert len(results) == 1 print(next(iter(results)).diatonic_pitch) assert 'E:4' == str(next(iter(results)).diatonic_pitch) p_map[v_note].note = next(iter(results)) assert constraint.verify(p_map)
def test_remove_notes(self): c = InstrumentCatalog.instance() violin = c.get_instrument("violin") note0 = Note(DiatonicPitch(4, 'a'), Duration(1, 8)) note1 = Note(DiatonicPitch(4, 'b'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note3 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) line = Line() line.pin(note0, Offset(1, 4)) line.pin(note1, Offset(3, 8)) line.pin(note2, Offset(1, 2)) line.pin(note3, Offset(5, 8)) voice = Voice(violin) voice.pin(line, Offset(0)) line.unpin([note1, note2]) notes = voice.get_all_notes() assert len(notes) == 2 assert note0 in notes assert note3 in notes assert note1 not in notes assert note2 not in notes notes = voice.get_notes_starting_in_interval( Interval(Position(0), Position(2, 1))) assert len(notes) == 2 line.clear() notes = voice.get_all_notes() assert len(notes) == 0 notes = voice.get_notes_starting_in_interval( Interval(Position(0), Position(2, 1))) assert len(notes) == 0
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_simple_form(self): line = Line() s = Beam() s.append(Note(DiatonicPitch.parse('C:4'), Duration(1, 8))) s.append(Note(DiatonicPitch.parse('D:4'), Duration(1, 8))) s.append(Note(DiatonicPitch.parse('E:4'), Duration(1, 8))) s.append(Note(DiatonicPitch.parse('F#:4'), Duration(1, 8))) line.pin(s) notes = s.get_all_notes() c = [ EqualPitchConstraint([notes[0], notes[2]]), NotEqualPitchConstraint([notes[1], notes[3]]) ] a = Motif(s, c, 'A') s1 = [ Note(DiatonicPitch(4, 'c'), Duration(1, 8)), Note(DiatonicPitch(4, 'd'), Duration(1, 8)), Note(DiatonicPitch(4, 'e'), Duration(1, 8)), ] tuplet = Tuplet(Duration(1, 8), 2, s1) line.pin(tuplet, Offset(1, 2)) notes = tuplet.get_all_notes() c1 = [ EqualPitchConstraint([notes[0], notes[2]]), RelativeScalarStepConstraint(notes[1], notes[2], -2, 2) ] b = Motif(tuplet, c1, 'B') f = Form([a, b]) print(f) constraints = [ EqualPitchConstraint([a.actors[0], b.actors[1]]) ] # Ensure a, b cloned for reliability - see comment in Form. ff = Form([a, b], constraints) print(ff) constr = ff.external_constraints assert len(constr) == 1 actors = ff.actors assert len(actors) == 7 assert isinstance(constr[0], EqualPitchConstraint) assert constr[0].actors[0] == actors[0] assert constr[0].actors[1] == actors[4 + 1] all_constr = ff.constraints assert len(all_constr) == 5 # Add more notes to clone ff as: s3 = Beam() first_note = Note(DiatonicPitch.parse('C:5'), Duration(1, 8)) s3.append(first_note) s3.append(Note(DiatonicPitch.parse('D:5'), Duration(1, 8))) s3.append(Note(DiatonicPitch.parse('E:5'), Duration(1, 8))) s3.append(Note(DiatonicPitch.parse('F#:5'), Duration(1, 8))) line.pin(s3, Offset(3)) s2 = [ Note(DiatonicPitch(5, 'c'), Duration(1, 8)), Note(DiatonicPitch(5, 'd'), Duration(1, 8)), Note(DiatonicPitch(5, 'e'), Duration(1, 8)), ] tuplet1 = Tuplet(Duration(1, 8), 2, s2) line.pin(tuplet1, Offset(7, 2)) fff = ff.copy_to(first_note) assert fff is not None print(fff) constr = fff.external_constraints assert len(constr) == 1 assert len(fff.constraints) == 5 actors = fff.actors assert len(actors) == 7 assert isinstance(constr[0], EqualPitchConstraint) assert constr[0].actors[0] == actors[0] assert constr[0].actors[1] == actors[4 + 1] all_constr = fff.constraints assert len(all_constr) == 5
def test_richer_structure(self): line = Line() s = Beam() s.append(Note(DiatonicPitch.parse('C:4'), Duration(1, 8))) s.append(Note(DiatonicPitch.parse('D:4'), Duration(1, 8))) line.pin(s) q1 = Note(DiatonicPitch.parse('E:4'), Duration(1, 4)) line.pin(q1, Offset(1, 4)) q2 = Note(DiatonicPitch.parse('F#:4'), Duration(1, 4)) line.pin(q2, Offset(1, 2)) cs = Beam() first_note = Note(DiatonicPitch.parse('C:3'), Duration(1, 8)) cs.append(first_note) cs.append(Note(DiatonicPitch.parse('D:3'), Duration(1, 8))) line.pin(cs, Offset(2)) cq1 = Note(DiatonicPitch.parse('E:3'), Duration(1, 4)) line.pin(cq1, Offset(9, 4)) cq2 = Note(DiatonicPitch.parse('F#:3'), Duration(1, 4)) line.pin(cq2, Offset(5, 2)) notes = line.get_all_notes() c = [ EqualPitchConstraint([notes[0], notes[2]]), NotEqualPitchConstraint([notes[1], notes[3]]) ] m = Motif([s, q1, q2], c, 'A') print(m) actors = m.actors assert 'A' == m.name assert len(actors) == 4 cc = m.constraints assert len(cc) == len(c) assert isinstance(cc[0], EqualPitchConstraint) cc_a = cc[0].actors assert len(cc_a) == 2 assert cc_a[0] == actors[0] assert cc_a[1] == actors[2] assert isinstance(cc[1], NotEqualPitchConstraint) cc_b = cc[1].actors assert len(cc_a) == 2 assert cc_b[0] == actors[1] assert cc_b[1] == actors[3] assert 'F#:4' == str(actors[3].diatonic_pitch) c_motif = m.copy_to(first_note) assert c_motif is not None c_actors = c_motif.actors assert 'A' == c_motif.name assert len(c_actors) == 4 ccc = c_motif.constraints assert len(ccc) == len(c) assert isinstance(ccc[0], EqualPitchConstraint) ccc_a = ccc[0].actors assert len(ccc_a) == 2 assert ccc_a[0] == c_actors[0] assert ccc_a[1] == c_actors[2] assert isinstance(ccc[1], NotEqualPitchConstraint) ccc_b = ccc[1].actors assert len(ccc_a) == 2 assert ccc_b[0] == c_actors[1] assert ccc_b[1] == c_actors[3] assert 'F#:3' == str(c_actors[3].diatonic_pitch) print(c_motif)
def test_compute_simple_scale_tones(self): logging.debug('Start test_compute_simple_scale_tones') lower_policy_context = TestPMap.policy_creator(ModalityType.Major, DiatonicTone('G'), 'tV', 'C:2', 'C:8') upper_pitch_txts = [ 'C:5', 'D:5', 'E:5', 'G:5', 'B:5', 'C:6', 'B:5', 'G:5', 'E:5', 'D:5', 'C:5', 'C:5' ] actors = list() differentials = [1, 1, 2, 2, 1, -1, -2, -2, -1, -1, 0] p_map = OrderedDict() for pitch_txt in upper_pitch_txts: upper_note = Note(DiatonicPitch.parse(pitch_txt), Duration(1, 8)) lower_note = ContextualNote(lower_policy_context) p_map[upper_note] = lower_note actors.append(upper_note) policy = StepSequenceConstraint(actors, differentials) p_map[actors[2]].note = Note(DiatonicPitch.parse('G:5'), Duration(1, 8)) solver = PitchConstraintSolver([policy]) results = None try: results, _ = solver.solve(p_map) if results is None: print("Results is None") else: print("Results is not None") if len(results) == 0: print("Results is empty") else: print('Results has {0} results.'.format(len(results))) # verify for pm in results: if not policy.verify(pm.p_map): print('Policy failure: {0}'.format( type(policy).__name__)) print(pm) continue for pm in results: print(pm) except Exception as e: print(e) # print >> sys.stderr, traceback.format_exc() traceback.print_exc() assert results is not None assert len(results) == 1 pm = next(iter(results)) answers = [ 'E:5', 'F#:5', 'G:5', 'B:5', 'D:6', 'E:6', 'D:6', 'B:5', 'G:5', 'F#:5', 'E:5', 'E:5' ] for i in range(0, len(actors)): assert str(pm[actors[i]].note.diatonic_pitch) == answers[i] print('-----') # Build a line and test apply on pm line = Line() begin_note = Note(DiatonicPitch.parse('A:2'), Duration(1, 2)) end_note = Note(DiatonicPitch.parse('B:2'), Duration(1, 2)) offset = Offset(0) line.pin(begin_note, offset) offset = offset + begin_note.duration.duration for note in actors: line.pin(note, offset) offset += note.duration.duration line.pin(end_note, offset) new_line = pm.apply(line) assert new_line is not None assert new_line != line all_notes = new_line.get_all_notes() assert len(all_notes) == 2 + len(actors) assert str(all_notes[0].diatonic_pitch) == 'A:2' assert str(all_notes[-1].diatonic_pitch) == 'B:2' for i in range(1, len(all_notes) - 1): assert str(all_notes[i].diatonic_pitch) == answers[i - 1]
def test_add_notes_to_beam(self): c = InstrumentCatalog.instance() violin = c.get_instrument("violin") note0 = Note(DiatonicPitch(4, 'a'), Duration(1, 8)) note1 = Note(DiatonicPitch(4, 'b'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note3 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) beam = Beam([note2, note3]) line = Line() line.pin(note0, Offset(1, 4)) line.pin(note1, Offset(3, 8)) line.pin(beam, Offset(1, 2)) voice = Voice(violin) voice.pin(line, Offset(0)) notee0 = Note(DiatonicPitch(5, 'a'), Duration(1, 8)) notee1 = Note(DiatonicPitch(5, 'b'), Duration(1, 8)) beam.append([notee0, notee1]) print(voice) notes = voice.get_notes_starting_in_interval( Interval(Position(3, 4), Position(1, 1))) assert len(notes) == 2 assert TestVoice.has_pitch(notes, DiatonicPitch.parse('A:5')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('B:5')) # Do the same but append a Beam to a line violin = c.get_instrument("violin") note0 = Note(DiatonicPitch(4, 'a'), Duration(1, 8)) note1 = Note(DiatonicPitch(4, 'b'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note3 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) line = Line() line.pin(note0, Offset(1, 4)) line.pin(note1, Offset(3, 8)) voice = Voice(violin) voice.pin(line, Offset(0)) beam = Beam([note2, note3]) line.pin(beam, Offset(1, 2)) print(voice) notes = voice.get_notes_starting_in_interval( Interval(Position(1, 2), Position(1, 1))) assert len(notes) == 2 assert TestVoice.has_pitch(notes, DiatonicPitch.parse('C:4')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('D:4')) # Do the same but append a Beam to a Beam violin = c.get_instrument("violin") note0 = Note(DiatonicPitch(4, 'a'), Duration(1, 8)) note1 = Note(DiatonicPitch(4, 'b'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note3 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) line = Line() beam = Beam([note0, note1]) line.pin(beam, Offset(1, 4)) voice = Voice(violin) voice.pin(line, Offset(0)) beam1 = Beam([note2, note3]) beam.append(beam1) print(voice) notes = voice.get_notes_starting_in_interval( Interval(Position(1, 2), Position(1, 1))) assert len(notes) == 2 assert TestVoice.has_pitch(notes, DiatonicPitch.parse('C:4')) assert TestVoice.has_pitch(notes, DiatonicPitch.parse('D:4')) # try to add note out of range on violin. notex = Note(DiatonicPitch(7, 'b'), Duration(1, 8)) with self.assertRaises(Exception): line.pin(notex, Offset(3, 1))
def test_simple_form(self): line = Line() notes = [ Note(DiatonicPitch.parse('C:4'), Duration(1, 8)), Note(DiatonicPitch.parse('D:4'), Duration(1, 8)), Note(DiatonicPitch.parse('E:4'), Duration(1, 8)), Note(DiatonicPitch.parse('F:4'), Duration(1, 8)), Note(DiatonicPitch.parse('G:4'), Duration(1, 8)), Note(DiatonicPitch.parse('A:4'), Duration(1, 8)), Note(DiatonicPitch.parse('B:4'), Duration(1, 8)), Note(DiatonicPitch.parse('C:4'), Duration(1, 4)), Note(DiatonicPitch.parse('C:3'), Duration(1, 8)), Note(DiatonicPitch.parse('D:3'), Duration(1, 8)), Note(DiatonicPitch.parse('E:3'), Duration(1, 8)), Note(DiatonicPitch.parse('F:3'), Duration(1, 8)), Note(DiatonicPitch.parse('G:3'), Duration(1, 8)), Note(DiatonicPitch.parse('A:3'), Duration(1, 8)), Note(DiatonicPitch.parse('B:3'), Duration(1, 8)), Note(DiatonicPitch.parse('C:3'), Duration(1, 4)), ] f = Fraction(0) for n in notes: line.pin(n, Offset(f)) f = f + n.duration.duration ca = [ EqualPitchConstraint([notes[0], notes[2]]), NotEqualPitchConstraint([notes[1], notes[3]]) ] cb = [ NotEqualPitchConstraint([notes[4], notes[5]]), EqualPitchConstraint([notes[6], notes[7]]) ] a = Motif([notes[0], notes[1], notes[2], notes[3]], ca, 'A') b = Motif([notes[4], notes[5], notes[6], notes[7]], cb, 'B') p1_constraints = [ EqualPitchConstraint([notes[4], notes[5]]), ] p1 = Phrase([notes[2], notes[3], notes[4], notes[5]], p1_constraints, 'P1') mf_constraints = [ EqualPitchConstraint([notes[2], notes[5]]), ] mf = MelodicForm([a, b], [p1], mf_constraints, 'MF1') actors = mf.actors assert actors is not None assert len(actors) == 8 assert actors[0] == notes[0] motifs = mf.motifs assert motifs is not None assert len(motifs) == 2 assert motifs[0].name == 'A' assert motifs[1].name == 'B' p_constraints = mf.phrase_constraints assert p_constraints is not None assert len(p_constraints) == 1 assert type(p_constraints[0]) == EqualPitchConstraint p_actors = mf.phrase_actors assert p_actors is not None assert len(p_actors) == 4 mf1 = mf.copy_to(notes[8]) assert mf1 is not None actors = mf1.actors assert actors is not None assert len(actors) == 8 assert actors[0] == notes[8] motifs = mf1.motifs assert motifs is not None assert len(motifs) == 2 assert motifs[0].name == 'A' assert motifs[1].name == 'B' p_constraints = mf1.phrase_constraints assert p_constraints is not None assert len(p_constraints) == 1 assert type(p_constraints[0]) == EqualPitchConstraint p_actors = mf1.phrase_actors assert p_actors is not None assert len(p_actors) == 4 phs = mf1.phrases assert phs is not None assert len(phs) == 1 assert phs[0].actors[0] == notes[10]