def test_simple_tuplet_reverse(self): print('test simple tuplet reverse') a = Note(DiatonicPitch(3, 'a'), Duration(1, 8)) b = Note(DiatonicPitch(3, 'b'), Duration(1, 8)) c = Note(DiatonicPitch(3, 'c'), Duration(1, 8)) d = Note(DiatonicPitch(3, 'd'), Duration(1, 8)) tuplet = Tuplet(Duration(1, 8), 3, [a, b, c, d]) print(tuplet) tuplet.reverse() print(tuplet) notes = tuplet.get_all_notes() assert notes is not None assert len(notes) == 4 assert notes[0].diatonic_pitch == DiatonicPitch(3, 'd') assert notes[1].diatonic_pitch == DiatonicPitch(3, 'c') assert notes[2].diatonic_pitch == DiatonicPitch(3, 'b') assert notes[3].diatonic_pitch == DiatonicPitch(3, 'a') assert notes[0].relative_position == Offset(0) assert notes[1].relative_position == Offset(3, 32) assert notes[2].relative_position == Offset(3, 16) assert notes[3].relative_position == Offset(9, 32)
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_tie_break(self): print('test tie break') a = Note(DiatonicPitch(3, 'a'), Duration(1, 8)) b = Note(DiatonicPitch(3, 'b'), Duration(1, 8)) c = Note(DiatonicPitch(3, 'c'), Duration(1, 8)) d = Note(DiatonicPitch(3, 'a'), Duration(1, 8)) sub_beam = Beam([b, c]) tuplet = Tuplet(Duration(1, 8), 2, [a, d]) a.tie() assert a.is_tied_to assert d.is_tied_from tuplet.add(sub_beam, 1) assert not a.is_tied_to assert not d.is_tied_from
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_tuplet_with_nested_beam(self): note1 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) n_list = [ Note(DiatonicPitch(3, 'c'), Duration(1, 8)), Note(DiatonicPitch(3, 'd'), Duration(1, 8)) ] add_beam = Beam(n_list) tuplet = Tuplet(Duration(1, 8), 2, [note1, add_beam, note2]) print(tuplet) AbstractNote.print_structure(tuplet) notes = tuplet.get_all_notes() assert len(notes) == 4 assert tuplet.sub_notes[0].duration == Duration(1, 16) assert tuplet.sub_notes[0].relative_position == Offset(0) assert tuplet.sub_notes[1].duration == Duration(1, 8) assert tuplet.sub_notes[1].relative_position == Offset(1, 16) assert tuplet.sub_notes[2].duration == Duration(1, 16) assert tuplet.sub_notes[2].relative_position == Offset(3, 16) assert notes[1].duration == Duration(1, 16) assert notes[1].relative_position == Offset(0) assert notes[2].duration == Duration(1, 16) assert notes[2].relative_position == Offset(1, 16) add_beam_prime = add_beam.clone() notes = add_beam_prime.get_all_notes() AbstractNote.print_structure(add_beam_prime) assert notes[0].duration == Duration(1, 8) assert str(notes[0].diatonic_pitch) == 'C:3' tuplet_prime = tuplet.clone() notes = tuplet_prime.get_all_notes() AbstractNote.print_structure(tuplet_prime) assert notes[0].duration == Duration(1, 16) assert str(notes[0].diatonic_pitch) == 'C:4' assert notes[1].duration == Duration(1, 16)
def test_simple_tuplet(self): note1 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) note3 = Note(DiatonicPitch(4, 'e'), Duration(1, 8)) tuplet = Tuplet(Duration(1, 8), 2, [note1, note2, note3]) print(tuplet) AbstractNote.print_structure(tuplet) notes = tuplet.get_all_notes() assert len(notes) == 3 assert notes[0].diatonic_pitch == DiatonicPitch(4, 'c') assert notes[1].diatonic_pitch == DiatonicPitch(4, 'd') assert notes[2].diatonic_pitch == DiatonicPitch(4, 'e') assert notes[0].duration == Duration(1, 12) assert notes[1].duration == Duration(1, 12) assert notes[2].duration == Duration(1, 12) assert notes[0].relative_position == Offset(0) assert notes[1].relative_position == Offset(1, 12) assert notes[2].relative_position == Offset(1, 6)
def test_book_example(self): print("test_book_example") a = Note(DiatonicPitch(3, 'a'), Duration(1, 8)) b = Note(DiatonicPitch(3, 'b'), Duration(1, 8)) c = Note(DiatonicPitch(3, 'c'), Duration(1, 8)) d = Note(DiatonicPitch(3, 'd'), Duration(1, 8)) e = Note(DiatonicPitch(3, 'e'), Duration(1, 8)) tuplet = Tuplet(Duration(1, 8), 2, [b, c, d]) beam = Beam([a, tuplet, e]) print(beam) a1 = Note(DiatonicPitch(3, 'a'), Duration(1, 8)) b1 = Note(DiatonicPitch(3, 'b'), Duration(1, 8)) c1 = Note(DiatonicPitch(3, 'c'), Duration(1, 8)) d1 = Note(DiatonicPitch(3, 'd'), Duration(1, 8)) e1 = Note(DiatonicPitch(3, 'e'), Duration(1, 8)) tuplet1 = Tuplet(Duration(1, 8), 2, [b1, c1, d1]) beam1 = Beam([tuplet1]) final_beam = Beam([a1, beam1, e1]) print(final_beam) a2 = Note(DiatonicPitch(3, 'a'), Duration(1, 8)) b2 = Note(DiatonicPitch(3, 'b'), Duration(1, 8)) c2 = Note(DiatonicPitch(3, 'c'), Duration(1, 8)) d2 = Note(DiatonicPitch(3, 'd'), Duration(1, 8)) e2 = Note(DiatonicPitch(3, 'e'), Duration(1, 8)) beam2 = Beam([b2, c2, d2]) tuplet2 = Tuplet(Duration(1, 16), 2, [beam2]) final_beam2 = Beam([a2, tuplet2, e2]) print(final_beam2) print("end test_book_example")
def test_odd_structure(self): print('test odd structure') n1 = Note(DiatonicPitch(4, 'c'), Duration(1, 12)) n2 = Note(DiatonicPitch(4, 'c'), Duration(1, 12)) from structure.tuplet import Tuplet tuplet = Tuplet(Duration(1, 12), 1, [n1, n2]) n3 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) beam = Beam([tuplet, n3]) AbstractNote.print_structure(beam)
def test_dilation(self): print('test dilation') a = Note(DiatonicPitch(3, 'a'), Duration(1, 8)) b = Note(DiatonicPitch(3, 'b'), Duration(1, 8)) c = Note(DiatonicPitch(3, 'c'), Duration(1, 8)) d = Note(DiatonicPitch(3, 'd'), Duration(1, 8)) e = Note(DiatonicPitch(3, 'e'), Duration(1, 8)) tuplet = Tuplet(Duration(1, 8), 2, [a, b, c]) sub_beam = Beam([tuplet]) beam = Beam([d, sub_beam, e]) AbstractNote.print_structure(beam) f = Note(DiatonicPitch(3, 'f'), Duration(1, 8)) tuplet.add(f, 2) AbstractNote.print_structure(beam) print('end test dilation')
def test_TBB_layers(self): print('start test_TBB_layers') sub_sub_beam = Beam([ Note(DiatonicPitch(2, 'c'), Duration(1, 8)), Note(DiatonicPitch(2, 'd'), Duration(1, 8)) ]) sub_beam = Beam([ Note(DiatonicPitch(3, 'c'), Duration(1, 8)), sub_sub_beam, Note(DiatonicPitch(3, 'd'), Duration(1, 8)) ]) AbstractNote.print_structure(sub_beam) note1 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) print('-----------') tuplet = Tuplet(Duration(1, 8), 2, [note1, sub_beam, note2]) AbstractNote.print_structure(tuplet) notes = tuplet.get_all_notes() assert len(notes) == 6 assert tuplet.sub_notes[1].duration == Duration(3, 20) assert tuplet.sub_notes[1].relative_position == Offset(1, 20) assert tuplet.sub_notes[1].sub_notes[1].duration == Duration(1, 20) assert tuplet.sub_notes[1].sub_notes[1].relative_position == Offset( 1, 20) sub_sub_beam.add(Note(DiatonicPitch(2, 'c'), Duration(1, 8)), 1) AbstractNote.print_structure(tuplet) assert tuplet.sub_notes[1].duration == Duration(7, 44) assert tuplet.sub_notes[1].relative_position == Offset(1, 22) assert tuplet.sub_notes[1].sub_notes[1].duration == Duration(3, 44) assert tuplet.sub_notes[1].sub_notes[1].relative_position == Offset( 1, 22) print('end test_TBB_layers')
def test_absolute_position(self): print('test absolute position') a = Note(DiatonicPitch(4, 'a'), Duration(1, 8)) b = Note(DiatonicPitch(4, 'b'), Duration(1, 8)) c = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) d = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) tuplet = Tuplet(Duration(1, 8), 3, [a, b, c, d]) e = Note(DiatonicPitch(4, 'e'), Duration(1, 8)) f = Note(DiatonicPitch(4, 'f'), Duration(1, 8)) g = Note(DiatonicPitch(4, 'g'), Duration(1, 8)) a1 = Note(DiatonicPitch(3, 'a'), Duration(1, 8)) sub_beam = Beam([e, f, g, a1]) b1 = Note(DiatonicPitch(3, 'b'), Duration(1, 8)) c1 = Note(DiatonicPitch(3, 'c'), Duration(1, 8)) d1 = Note(DiatonicPitch(3, 'd'), Duration(1, 8)) e1 = Note(DiatonicPitch(3, 'e'), Duration(1, 8)) beam = Beam([b1, tuplet, c1, sub_beam, d1, e1]) AbstractNote.print_structure(beam) notes = beam.get_all_notes() assert notes is not None assert len(notes) == 12 results = [ Position(0), Position(1, 8), Position(7, 32), Position(5, 16), Position(13, 32), Position(1, 2), Position(5, 8), Position(11, 16), Position(3, 4), Position(13, 16), Position(7, 8), Position(1) ] index = 0 for n in notes: print('{0} abs. position = {1}'.format(n, n.get_absolute_position())) assert n.get_absolute_position() == results[index] index += 1
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_nested_structure_reverse(self): print('test nested structure reverse') a = Note(DiatonicPitch(4, 'a'), Duration(1, 8)) b = Note(DiatonicPitch(4, 'b'), Duration(1, 8)) c = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) d = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) tuplet = Tuplet(Duration(1, 8), 3, [a, b, c, d]) e = Note(DiatonicPitch(4, 'e'), Duration(1, 8)) f = Note(DiatonicPitch(4, 'f'), Duration(1, 8)) g = Note(DiatonicPitch(4, 'g'), Duration(1, 8)) a1 = Note(DiatonicPitch(3, 'a'), Duration(1, 8)) sub_beam = Beam([e, f, g, a1]) b1 = Note(DiatonicPitch(3, 'b'), Duration(1, 8)) c1 = Note(DiatonicPitch(3, 'c'), Duration(1, 8)) d1 = Note(DiatonicPitch(3, 'd'), Duration(1, 8)) e1 = Note(DiatonicPitch(3, 'e'), Duration(1, 8)) beam = Beam([b1, tuplet, c1, sub_beam, d1, e1]) AbstractNote.print_structure(beam) beam.reverse() AbstractNote.print_structure(beam) notes = beam.get_all_notes() assert notes is not None assert len(notes) == 12 assert notes[0].diatonic_pitch == DiatonicPitch(3, 'e') assert notes[1].diatonic_pitch == DiatonicPitch(3, 'd') assert notes[2].diatonic_pitch == DiatonicPitch(3, 'a') assert notes[3].diatonic_pitch == DiatonicPitch(4, 'g') assert notes[4].diatonic_pitch == DiatonicPitch(4, 'f') assert notes[5].diatonic_pitch == DiatonicPitch(4, 'e') assert notes[6].diatonic_pitch == DiatonicPitch(3, 'c') assert notes[7].diatonic_pitch == DiatonicPitch(4, 'd') assert notes[8].diatonic_pitch == DiatonicPitch(4, 'c') assert notes[9].diatonic_pitch == DiatonicPitch(4, 'b') assert notes[10].diatonic_pitch == DiatonicPitch(4, 'a') assert notes[11].diatonic_pitch == DiatonicPitch(3, 'b')
def test_ties_reverse(self): print('test ties reverse') a = Note(DiatonicPitch(3, 'b'), Duration(1, 8)) b = Note(DiatonicPitch(4, 'b'), Duration(1, 8)) c = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) d = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) tuplet = Tuplet(Duration(1, 8), 3, [a, b, c, d]) e = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) f = Note(DiatonicPitch(4, 'f'), Duration(1, 8)) g = Note(DiatonicPitch(4, 'g'), Duration(1, 8)) a1 = Note(DiatonicPitch(3, 'd'), Duration(1, 8)) sub_beam = Beam([e, f, g, a1]) b1 = Note(DiatonicPitch(3, 'b'), Duration(1, 8)) c1 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) d1 = Note(DiatonicPitch(3, 'd'), Duration(1, 8)) e1 = Note(DiatonicPitch(3, 'e'), Duration(1, 8)) beam = Beam([b1, tuplet, c1, sub_beam, d1, e1]) b1.tie() d.tie() c1.tie() a1.tie() AbstractNote.print_structure(beam) beam.reverse() AbstractNote.print_structure(beam) assert a.is_tied_to and a.tied_to == b1 assert b1.is_tied_from and b1.tied_from == a assert c1.is_tied_to and c1.tied_to == d assert d.is_tied_from and d.tied_from == c1 assert e.is_tied_to and e.tied_to == c1 assert c1.is_tied_from and c1.tied_from == e assert d1.is_tied_to and d1.tied_to == a1 assert a1.is_tied_from and a1.tied_from == d1
def test_nested_tuplet(self): note1 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) sub_tuplet = Tuplet(Duration(1, 8), 2, [ Note(DiatonicPitch(3, 'c'), Duration(1, 8)), Note(DiatonicPitch(3, 'd'), Duration(1, 8)), Note(DiatonicPitch(3, 'e'), Duration(1, 8)) ]) tuplet = Tuplet(Duration(1, 8), 2, [note1, sub_tuplet, note2]) print(tuplet) AbstractNote.print_structure(tuplet) notes = tuplet.get_all_notes() assert len(notes) == 5 assert notes[0].duration == Duration(1, 16) assert notes[1].duration == Duration(1, 24) assert notes[2].duration == Duration(1, 24) assert notes[3].duration == Duration(1, 24) assert notes[4].duration == Duration(1, 16) assert notes[0].relative_position == Offset(0) assert notes[1].relative_position == Offset(0) assert notes[2].relative_position == Offset(1, 24) assert notes[3].relative_position == Offset(1, 12) assert notes[4].relative_position == Offset(3, 16) assert tuplet.sub_notes[1].duration == Duration(1, 8) assert tuplet.sub_notes[1].relative_position == Offset(1, 16) sub_tuplet_prime = sub_tuplet.clone() notes = sub_tuplet_prime.get_all_notes() AbstractNote.print_structure(sub_tuplet_prime) assert notes[0].duration == Duration(1, 12) assert str(notes[0].diatonic_pitch) == 'C:3' tuplet_prime = tuplet.clone() notes = tuplet_prime.get_all_notes() AbstractNote.print_structure(tuplet_prime) assert notes[0].duration == Duration(1, 16) assert str(notes[0].diatonic_pitch) == 'C:4' assert notes[1].duration == Duration(1, 24)
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_tuplet_variations(self): print('test tuplet variations') # 1. Beam with 3 1/8 notes note1 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) note3 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) beam = Beam([note1, note2, note3]) AbstractNote.print_structure(beam) notes = beam.get_all_notes() assert len(notes) == 3 assert notes[0].duration == Duration(1, 8) assert notes[1].duration == Duration(1, 8) assert notes[2].duration == Duration(1, 8) assert notes[0].relative_position == Offset(0) assert notes[1].relative_position == Offset(1, 8) assert notes[2].relative_position == Offset(1, 4) # 2. beam with a tuplet note1 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) note3 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) tuplet = Tuplet(Duration(1, 8), 2, [note1, note2, note3]) beam = Beam([tuplet]) AbstractNote.print_structure(beam) notes = beam.get_all_notes() assert len(notes) == 3 assert notes[0].duration == Duration(1, 12) assert notes[1].duration == Duration(1, 12) assert notes[2].duration == Duration(1, 12) assert notes[0].relative_position == Offset(0) assert notes[1].relative_position == Offset(1, 12) assert notes[2].relative_position == Offset(1, 6) # 3. tuplet with a beam note1 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) note3 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) beam = Beam([note1, note2, note3]) tuplet = Tuplet(Duration(1, 8), 2, beam) AbstractNote.print_structure(tuplet) notes = beam.get_all_notes() assert len(notes) == 3 assert notes[0].duration == Duration(1, 12) assert notes[1].duration == Duration(1, 12) assert notes[2].duration == Duration(1, 12) assert notes[0].relative_position == Offset(0) assert notes[1].relative_position == Offset(1, 12) assert notes[2].relative_position == Offset(1, 6) # 4. beam a beam of a tuplet note1 = Note(DiatonicPitch(4, 'c'), Duration(1, 8)) note2 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) note3 = Note(DiatonicPitch(4, 'd'), Duration(1, 8)) tuplet = Tuplet(Duration(1, 8), 2, [note1, note2, note3]) sub_beam = Beam([tuplet]) beam = Beam(sub_beam) AbstractNote.print_structure(beam) notes = beam.get_all_notes() assert len(notes) == 3 assert notes[0].duration == Duration(1, 24) assert notes[1].duration == Duration(1, 24) assert notes[2].duration == Duration(1, 24) assert notes[0].relative_position == Offset(0) assert notes[1].relative_position == Offset(1, 24) assert notes[2].relative_position == Offset(1, 12)