def test_hammer_on_tie_is_kept_on_first_note(self): position = FretPosition(string=3, fret=1) notes = [ Note(order=0, position=position, duration=Beat(3), elapsed_beats=Beat(3), slur=constants.HAMMER_ON), Note(order=1, position=position, duration=Beat(1), elapsed_beats=Beat(4)), ] result = normalise_note_durations(notes) expected = [ Note(order=0, position=position, duration=Beat(1, 2), elapsed_beats=Beat(1, 2), slur=constants.HAMMER_ON), Note(order=1, position=position, duration=Beat(1, 4, tie=True), elapsed_beats=Beat(3, 4)), Note(order=2, position=position, duration=Beat(1, 4), elapsed_beats=Beat(1, 1)), ] self.assertEqual(expected, result)
def test_chords_can_have_bends(self): duration = Beat(1, 4) notes = [ Note(order=0, position=FretPosition(12, 5), duration=duration, elapsed_beats=Beat(1, 4)), Note(order=0, position=FretPosition(12, 4), duration=duration, elapsed_beats=Beat(1, 4)), Note(order=1, position=FretPosition(14, 5), duration=duration, elapsed_beats=Beat(2, 4), slur=BEND), Note(order=1, position=FretPosition(14, 4), duration=duration, elapsed_beats=Beat(2, 4), slur=BEND), ] shapes = [GuitarShape(name='shape1', positions=[], category='scale')] sequence = Sequence(notes=notes, shapes=shapes) vextab = to_vextab(sequence) expected = ('tabstave notation=false\n' 'notes =|: :q (12/5.12/4) :q b(14/5.14/4) =:|') self.assertEqual(expected, vextab)
def test_split_beats_are_in_ascending_order_if_not_at_start_of_bar(self): position = FretPosition(string=3, fret=1) notes = [ Note(order=0, position=position, duration=Beat(1), elapsed_beats=Beat(1)), Note(order=1, position=position, duration=Beat(3), elapsed_beats=Beat(4)), ] result = normalise_note_durations(notes) expected = [ Note(order=0, position=position, duration=Beat(1, 4), elapsed_beats=Beat(1, 4)), Note(order=1, position=position, duration=Beat(1, 4), elapsed_beats=Beat(2, 4)), Note(order=2, position=position, duration=Beat(2, 4, tie=True), elapsed_beats=Beat(1, 1)), ] self.assertEqual(expected, result)
def test_half_notes_have_a_h_duration(self): position = FretPosition(string=6, fret=5) duration = Beat(2, 4) notes = [ Note(order=1, position=position, duration=duration, elapsed_beats=Beat(2, 4)), Note(order=2, position=position, duration=duration, elapsed_beats=Beat(4, 4)), Note(order=3, position=position, duration=duration, elapsed_beats=Beat(6, 4)), Note(order=4, position=position, duration=duration, elapsed_beats=Beat(8, 4)), ] shapes = [ GuitarShape(name='shape1', positions=[position], category='scale') ] sequence = Sequence(notes=notes, shapes=shapes) vextab = to_vextab(sequence) expected = ('tabstave notation=false\n' 'notes =|: :h 5/6 :h 5/6 | :h 5/6 :h 5/6 =:|') self.assertEqual(expected, vextab)
def test_odd_length_quarter_note_is_split(self): position = FretPosition(string=3, fret=1) notes = [ Note(order=0, position=position, duration=Beat(3), elapsed_beats=Beat(3)), Note(order=1, position=position, duration=Beat(1), elapsed_beats=Beat(4)), ] result = normalise_note_durations(notes) expected = [ Note(order=0, position=position, duration=Beat(1, 2), elapsed_beats=Beat(1, 2)), Note(order=1, position=position, duration=Beat(1, 4, tie=True), elapsed_beats=Beat(3, 4)), Note(order=2, position=position, duration=Beat(1, 4), elapsed_beats=Beat(1, 1)), ] self.assertEqual(expected, result)
def test_can_add_two_half_notes_together(self): beat1 = Beat(duration=1, division=2) beat2 = Beat(duration=1, division=2) result = beat1 + beat2 self.assertEqual(Beat(duration=1, division=1), result)
def test_can_add_two_triplets_together(self): beat1 = Beat(duration=1, division=3) beat2 = Beat(duration=1, division=3) result = beat1 + beat2 self.assertEqual(Beat(duration=2, division=3), result)
def test_palm_mutes_are_added_to_tab_as_text(self): position = FretPosition(string=6, fret=5) duration = Beat(1, 8) notes = [ Note(order=0, position=position, duration=duration, elapsed_beats=Beat(1, 4), annotations=[PALM_MUTE]), Note(order=1, position=position, duration=duration, elapsed_beats=Beat(2, 4), annotations=[PALM_MUTE]), ] shapes = [ GuitarShape(name='shape1', positions=[position], category='scale') ] sequence = Sequence(notes=notes, shapes=shapes) vextab = to_vextab(sequence) expected = ('tabstave notation=false\n' 'notes =|: :8 5/6 $.top.pm$ :8 5/6 $.top.pm$ =:|') self.assertEqual(expected, vextab)
def test_can_palm_mute_and_down_pick_on_tabs(self): duration = Beat(1, 4) notes = [ Note(order=0, position=FretPosition(12, 5), duration=duration, elapsed_beats=Beat(1, 4), annotations=[DOWN_PICK, PALM_MUTE]), Note(order=1, position=FretPosition(14, 5), duration=duration, elapsed_beats=Beat(2, 4), annotations=[DOWN_PICK, PALM_MUTE]), ] shapes = [GuitarShape(name='shape1', positions=[], category='scale')] sequence = Sequence(notes=notes, shapes=shapes) vextab = to_vextab(sequence) expected = ( 'tabstave notation=false\n' 'notes =|: :q 12/5 $.am/top.$ $.top.pm$ :q 14/5 $.am/top.$ $.top.pm$ =:|' ) self.assertEqual(expected, vextab)
def test_shape_is_converted_into_notes(self): positions = [ FretPosition(string=1, fret=1), FretPosition(string=1, fret=2), FretPosition(string=1, fret=3), FretPosition(string=1, fret=4), ] shape = GuitarShape(name='shape1', positions=positions, category='scale') sequence = make_sequence([shape]) duration = Beat(duration=1) expected_notes = [ Note(order=0, position=positions[0], duration=duration, elapsed_beats=Beat(1)), Note(order=1, position=positions[1], duration=duration, elapsed_beats=Beat(2)), Note(order=2, position=positions[2], duration=duration, elapsed_beats=Beat(3)), Note(order=3, position=positions[3], duration=duration, elapsed_beats=Beat(4)), ] self.assertEqual(expected_notes, sequence.notes) self.assertEqual([shape], sequence.shapes)
def test_taps_are_added_to_tab(self): position = FretPosition(string=6, fret=5) duration = Beat(1, 8) notes = [ Note(order=0, position=position, duration=duration, elapsed_beats=Beat(1, 4)), Note(order=1, position=position, duration=duration, elapsed_beats=Beat(2, 4), slur=TAP), ] shapes = [ GuitarShape(name='shape1', positions=[position], category='scale') ] sequence = Sequence(notes=notes, shapes=shapes) vextab = to_vextab(sequence) expected = ('tabstave notation=false\n' 'notes =|: :8 5/6 t:8: 5/6 =:|') self.assertEqual(expected, vextab)
def test_shape_name_is_not_added_if_short_name_is_none(self): positions = [ FretPosition(0, 6), FretPosition(2, 5), ] shapes = [ GuitarShape(category='chord', name='E5 Power Chord', positions=positions) ] result = make_sequence(shapes, pick_pattern=pickpatterns.strum, tab_labels=True, rhythm=[Beat(4)]) expected = [ Note(position=positions[0], duration=Beat(4), elapsed_beats=Beat(1, 1), order=0), Note(position=positions[1], duration=Beat(4), elapsed_beats=Beat(1, 1), order=0), ] self.assertEqual(expected, result.notes)
def test_shape_name_is_added_to_annotations(self): positions = [ FretPosition(0, 6), FretPosition(2, 5), ] shapes = [ GuitarShape(category='chord', name='E5 Power Chord', positions=positions, short_name='E5') ] sequence = make_sequence(shapes, pick_pattern=pickpatterns.strum, tab_labels=True, rhythm=[Beat(4)]) expected_notes = [ Note(position=positions[0], duration=Beat(4), elapsed_beats=Beat(1, 1), order=0, annotations=['label:E5']), Note(position=positions[1], duration=Beat(4), elapsed_beats=Beat(1, 1), order=0, annotations=['label:E5']), ] self.assertEqual(expected_notes, sequence.notes) self.assertEqual(shapes, sequence.shapes)
def test_can_add_to_zero_duration_beat(self): beat1 = Beat(duration=0, division=1) beat2 = Beat(duration=1, division=1) result = beat1 + beat2 self.assertEqual(Beat(duration=1, division=1), result)
def test_can_add_a_half_and_whole_note_together(self): beat1 = Beat(duration=1, division=2) beat2 = Beat(duration=1, division=1) result = beat1 + beat2 self.assertEqual(Beat(duration=3, division=2), result)
def test_ties_are_not_added_to_rests(self): position = FretPosition(string=3, fret=1) notes = [ Note(order=0, position=None, duration=Beat(3, rest=True), elapsed_beats=Beat(3)), Note(order=1, position=position, duration=Beat(1), elapsed_beats=Beat(4)), ] result = normalise_note_durations(notes) expected = [ Note(order=0, position=None, duration=Beat(1, 2, rest=True), elapsed_beats=Beat(1, 2)), Note(order=1, position=None, duration=Beat(1, 4, rest=True), elapsed_beats=Beat(3, 4)), Note(order=2, position=position, duration=Beat(1, 4), elapsed_beats=Beat(1, 1)), ] self.assertEqual(expected, result)
def test_rest_beats_are_added_to_sequence_and_ignored_by_pick_pattern( self): rhythm = [ Beat(duration=1), Beat(duration=1, rest=True), Beat(duration=1), ] pattern = make_single_position_pattern(length=2) notes = apply_rhythm(pattern, rhythm) self.assertEqual(3, len(notes)) self.assertEqual( Note(position=pattern[0][0], duration=Beat(1), order=0, elapsed_beats=Beat(1)), notes[0]) self.assertEqual( Note(position=None, duration=Beat(1, rest=True), order=1, elapsed_beats=Beat(2)), notes[1]) self.assertEqual( Note(position=pattern[1][0], duration=Beat(1), order=2, elapsed_beats=Beat(3)), notes[2])
def test_can_set_rhythm_for_sequence(self): rhythm = [ Beat(duration=1, division=4), Beat(duration=1, division=2), Beat(duration=1, division=4), ] positions = [ FretPosition(string=1, fret=1), FretPosition(string=1, fret=2), FretPosition(string=1, fret=3), ] shape = GuitarShape(name='shape1', positions=positions, category='scale') sequence = make_sequence([shape], rhythm=rhythm) expected_notes = [ Note(order=0, position=positions[0], duration=Beat(1), elapsed_beats=Beat(1)), Note(order=1, position=positions[1], duration=Beat(1, 2), elapsed_beats=Beat(3, 4)), Note(order=2, position=positions[2], duration=Beat(1, 4), elapsed_beats=Beat(4, 4)), ] self.assertEqual(expected_notes, sequence.notes) self.assertEqual([shape], sequence.shapes)
def test_rhythm_is_repeated_when_shorter_than_pattern(self): rhythm = [ Beat(duration=1), ] pattern = make_single_position_pattern(length=4) notes = apply_rhythm(pattern, rhythm) self.assertEqual(4, len(notes)) self.assertEqual( Note(position=pattern[0][0], duration=Beat(1), order=0, elapsed_beats=Beat(1)), notes[0]) self.assertEqual( Note(position=pattern[1][0], duration=Beat(1), order=1, elapsed_beats=Beat(2)), notes[1]) self.assertEqual( Note(position=pattern[2][0], duration=Beat(1), order=2, elapsed_beats=Beat(3)), notes[2]) self.assertEqual( Note(position=pattern[3][0], duration=Beat(1), order=3, elapsed_beats=Beat(4)), notes[3])
def eighth_chugs() -> Dict: return { 'shapes': [ open_string(), open_string(), ], 'rhythm': [ Beat(1, 8), Beat(1, 8), ], }
def down_pick_alternating_beats(notes: List[Note], shapes: List[GuitarShape]) -> List[Note]: prev_elapsed_beat = Beat(0, 1) for note in notes: beat_division = (prev_elapsed_beat + Beat(1, 1)).division if beat_division == 2 or beat_division == 1: note.annotations.append(DOWN_PICK) prev_elapsed_beat = note.elapsed_beats return notes
def test_multi_bar_beats_are_broken_down(self): duration = Beat(5, 1) + Beat(1, 2) result = duration.tie_split() expected = [ Beat(1, 1), Beat(1, 1), Beat(1, 1), Beat(1, 1), Beat(1, 1), Beat(1, 2) ] self.assertEqual(expected, result)
def test_hammer_on_tie_is_added_to_asc_positions(self): notes = [ Note(order=0, position=FretPosition(5, 6), duration=Beat(1), elapsed_beats=Beat(1)), Note(order=1, position=FretPosition(7, 6), duration=Beat(1), elapsed_beats=Beat(2)), ] result = hammer_on_asc(notes, None) expected = [ Note(order=0, position=FretPosition(5, 6), duration=Beat(1), elapsed_beats=Beat(1)), Note(order=1, position=FretPosition(7, 6), duration=Beat(1), elapsed_beats=Beat(2), slur=HAMMER_ON), ] self.assertEqual(expected, result)
def test_can_apply_rhythm_to_chords_and_individual_notes(self): pattern = [ [ FretPosition(string=6, fret=1), FretPosition(string=5, fret=3), ], [FretPosition(string=6, fret=0)], ] rhythm = [ Beat(duration=1), Beat(duration=1), ] notes = apply_rhythm(pattern, rhythm) self.assertEqual(3, len(notes)) self.assertEqual( Note(position=pattern[0][0], duration=Beat(1), order=0, elapsed_beats=Beat(1)), notes[0]) self.assertEqual( Note(position=pattern[0][1], duration=Beat(1), order=0, elapsed_beats=Beat(1)), notes[1]) self.assertEqual( Note(position=pattern[1][0], duration=Beat(1), order=1, elapsed_beats=Beat(2)), notes[2])
def test_hammer_on_is_not_added_after_string_change(self): notes = [ Note(order=0, position=FretPosition(string=6, fret=5), duration=Beat(1), elapsed_beats=Beat(1)), Note(order=1, position=FretPosition(string=5, fret=5), duration=Beat(1), elapsed_beats=Beat(2)), ] result = hammer_on_asc(notes, None) expected = [ Note(order=0, position=FretPosition(string=6, fret=5), duration=Beat(1), elapsed_beats=Beat(1)), Note(order=1, position=FretPosition(string=5, fret=5), duration=Beat(1), elapsed_beats=Beat(2)), ] self.assertEqual(expected, result)
def test_rests_are_added_to_incomplete_bars_at_the_end(self): rhythm = [ Beat(duration=1, division=1), Beat(duration=1, division=4), ] positions = [ FretPosition(string=1, fret=1), FretPosition(string=1, fret=2), ] shape = GuitarShape(name='shape1', positions=positions, category='scale') sequence = make_sequence([shape], rhythm=rhythm) expected_notes = [ Note(order=0, position=positions[0], duration=Beat(1, 1), elapsed_beats=Beat(1, 1)), Note(order=1, position=positions[1], duration=Beat(1, 4), elapsed_beats=Beat(5, 4)), Note(order=2, position=None, duration=Beat(3, 4, rest=True), elapsed_beats=Beat(2, 1)), ] self.assertEqual(expected_notes, sequence.notes) self.assertEqual([shape], sequence.shapes)
def test_pull_off_tie_is_not_added_to_asc_positions(self): notes = [ Note(order=0, position=FretPosition(5, 6), duration=Beat(1), elapsed_beats=Beat(1)), Note(order=1, position=FretPosition(7, 6), duration=Beat(1), elapsed_beats=Beat(2)), ] result = pull_off_desc(notes, None) expected = [ Note(order=0, position=FretPosition(5, 6), duration=Beat(1), elapsed_beats=Beat(1)), Note(order=1, position=FretPosition(7, 6), duration=Beat(1), elapsed_beats=Beat(2)), ] self.assertEqual(expected, result)
def test_tie_split_breaks_down_quarter_notes(self): calculations = [ (Beat(1, 4), [Beat(1, 4)]), (Beat(2, 4), [Beat(1, 2)]), (Beat(3, 4), [Beat(1, 2), Beat(1, 4)]), (Beat(4, 4), [Beat(1, 1)]), ] for calculation in calculations: split = calculation[0].tie_split() self.assertEqual(calculation[1], split)
def test_individual_notes_are_returned_in_order(self): position = FretPosition(string=3, fret=1) duration = Beat(1) notes = [ Note(order=1, position=position, duration=duration, elapsed_beats=Beat(1)), Note(order=2, position=position, duration=duration, elapsed_beats=Beat(2)), Note(order=3, position=position, duration=duration, elapsed_beats=Beat(3)), Note(order=4, position=position, duration=duration, elapsed_beats=Beat(4)), ] result = group_notes(notes) expected = { 1: [ Note(order=1, position=position, duration=duration, elapsed_beats=Beat(1)) ], 2: [ Note(order=2, position=position, duration=duration, elapsed_beats=Beat(2)) ], 3: [ Note(order=3, position=position, duration=duration, elapsed_beats=Beat(3)) ], 4: [ Note(order=4, position=position, duration=duration, elapsed_beats=Beat(4)) ], } self.assertEqual(expected, result)
def test_level_one_has_eighth_notes(self): random.seed(10) result = technique_hammers_pulls(variation='level-1') self.assertEqual(8, len(result.notes)) self.assertTrue( all(Beat(1, 8) == note.duration for note in result.notes))