Exemplo n.º 1
0
 def testExtractLeadSheetFragments(self):
     self.quantized_sequence.steps_per_quarter = 1
     testing_lib.add_quantized_track(self.quantized_sequence, 0,
                                     [(12, 100, 2, 4), (11, 1, 6, 11)])
     testing_lib.add_quantized_track(self.quantized_sequence, 1,
                                     [(12, 127, 2, 4), (14, 50, 6, 8),
                                      (50, 100, 33, 37), (52, 100, 34, 37)])
     testing_lib.add_quantized_chords(self.quantized_sequence,
                                      [('C', 2), ('G7', 6), ('Cmaj7', 33)])
     lead_sheets, _ = lead_sheets_lib.extract_lead_sheet_fragments(
         self.quantized_sequence,
         min_bars=1,
         gap_bars=2,
         min_unique_pitches=2,
         ignore_polyphonic_notes=True,
         require_chords=True)
     melodies, _ = melodies_lib.extract_melodies(
         self.quantized_sequence,
         min_bars=1,
         gap_bars=2,
         min_unique_pitches=2,
         ignore_polyphonic_notes=True)
     chord_progressions, _ = chords_lib.extract_chords_for_melodies(
         self.quantized_sequence, melodies)
     self.assertEqual(list(melodies),
                      list(lead_sheet.melody for lead_sheet in lead_sheets))
     self.assertEqual(list(chord_progressions),
                      list(lead_sheet.chords for lead_sheet in lead_sheets))
Exemplo n.º 2
0
  def testExtractMelodiesStatistics(self):
    testing_lib.add_track_to_sequence(
        self.note_sequence, 0,
        [(12, 100, 2, 4), (11, 1, 6, 7), (10, 100, 8, 10), (9, 100, 11, 14),
         (8, 100, 16, 40), (7, 100, 41, 42)])
    testing_lib.add_track_to_sequence(
        self.note_sequence, 1,
        [(12, 127, 2, 4), (14, 50, 2, 8)])
    testing_lib.add_track_to_sequence(
        self.note_sequence, 2,
        [(12, 127, 0, 1)])
    testing_lib.add_track_to_sequence(
        self.note_sequence, 3,
        [(12, 127, 2, 4), (12, 50, 6, 8)])

    quantized_sequence = sequences_lib.quantize_note_sequence(
        self.note_sequence, steps_per_quarter=1)

    _, stats = melodies_lib.extract_melodies(
        quantized_sequence, min_bars=1, gap_bars=1, min_unique_pitches=2,
        ignore_polyphonic_notes=False)

    stats_dict = dict([(stat.name, stat) for stat in stats])
    self.assertEqual(stats_dict['polyphonic_tracks_discarded'].count, 1)
    self.assertEqual(stats_dict['melodies_discarded_too_short'].count, 1)
    self.assertEqual(stats_dict['melodies_discarded_too_few_pitches'].count, 1)
    self.assertEqual(
        stats_dict['melody_lengths_in_bars'].counters,
        {float('-inf'): 0, 0: 0, 1: 0, 2: 0, 10: 1, 20: 0, 30: 0, 40: 0, 50: 0,
         100: 0, 200: 0, 500: 0})
Exemplo n.º 3
0
 def testExtractMelodiesTooFewPitches(self):
     # Test that extract_melodies discards melodies with too few pitches where
     # pitches are equivalent by octave.
     self.quantized_sequence.steps_per_quarter = 1
     testing_lib.add_quantized_track_to_sequence(self.quantized_sequence, 0,
                                                 [(12, 100, 0, 1),
                                                  (13, 100, 1, 2),
                                                  (18, 100, 2, 3),
                                                  (24, 100, 3, 4),
                                                  (25, 100, 4, 5)])
     testing_lib.add_quantized_track_to_sequence(self.quantized_sequence, 1,
                                                 [(12, 100, 0, 1),
                                                  (13, 100, 1, 2),
                                                  (18, 100, 2, 3),
                                                  (25, 100, 3, 4),
                                                  (26, 100, 4, 5)])
     expected = [[12, 13, 18, 25, 26]]
     melodies, _ = melodies_lib.extract_melodies(
         self.quantized_sequence,
         min_bars=1,
         gap_bars=1,
         min_unique_pitches=4,
         ignore_polyphonic_notes=True)
     melodies = [list(melody) for melody in melodies]
     self.assertEqual(expected, melodies)
Exemplo n.º 4
0
  def testExtractMelodiesSimple(self):
    testing_lib.add_track_to_sequence(
        self.note_sequence, 0,
        [(12, 100, 2, 4), (11, 1, 6, 7)])
    testing_lib.add_track_to_sequence(
        self.note_sequence, 1,
        [(12, 127, 2, 4), (14, 50, 6, 9)])
    testing_lib.add_track_to_sequence(
        self.note_sequence, 9,
        [(13, 100, 2, 4), (15, 25, 6, 8)],
        is_drum=True)

    quantized_sequence = sequences_lib.quantize_note_sequence(
        self.note_sequence, steps_per_quarter=1)

    expected = [[NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 11],
                [NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 14,
                 NO_EVENT, NO_EVENT]]
    melodies, _ = melodies_lib.extract_melodies(
        quantized_sequence, min_bars=1, gap_bars=1, min_unique_pitches=2,
        ignore_polyphonic_notes=True)

    self.assertEqual(2, len(melodies))
    self.assertTrue(isinstance(melodies[0], melodies_lib.Melody))
    self.assertTrue(isinstance(melodies[1], melodies_lib.Melody))

    melodies = sorted([list(melody) for melody in melodies])
    self.assertEqual(expected, melodies)
Exemplo n.º 5
0
    def testExtractMultipleMelodiesFromSameTrack(self):
        testing_lib.add_track_to_sequence(self.note_sequence, 0,
                                          [(12, 100, 2, 4), (11, 1, 6, 11)])
        testing_lib.add_track_to_sequence(self.note_sequence,
                                          1, [(12, 127, 2, 4), (14, 50, 6, 8),
                                              (50, 100, 33, 37),
                                              (52, 100, 34, 37)])

        quantized_sequence = sequences_lib.quantize_note_sequence(
            self.note_sequence, steps_per_quarter=1)

        expected = [[
            NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 11, NO_EVENT,
            NO_EVENT, NO_EVENT, NO_EVENT
        ], [
            NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 14, NO_EVENT
        ], [NO_EVENT, 50, 52, NO_EVENT, NO_EVENT]]
        melodies, _ = melodies_lib.extract_melodies(
            quantized_sequence,
            min_bars=1,
            gap_bars=2,
            min_unique_pitches=2,
            ignore_polyphonic_notes=True)
        melodies = sorted([list(melody) for melody in melodies])
        self.assertEqual(expected, melodies)
Exemplo n.º 6
0
    def testExtractChordsForMelodiesCoincidentChords(self):
        testing_lib.add_track_to_sequence(self.note_sequence, 0,
                                          [(12, 100, 2, 4), (11, 1, 6, 11)])
        testing_lib.add_track_to_sequence(self.note_sequence,
                                          1, [(12, 127, 2, 4), (14, 50, 6, 8),
                                              (50, 100, 33, 37),
                                              (52, 100, 34, 37)])
        testing_lib.add_chords_to_sequence(self.note_sequence, [('C', 2),
                                                                ('G7', 6),
                                                                ('E13', 8),
                                                                ('Cmaj7', 8)])
        quantized_sequence = sequences_lib.quantize_note_sequence(
            self.note_sequence, self.steps_per_quarter)

        melodies, _ = melodies_lib.extract_melodies(
            quantized_sequence,
            min_bars=1,
            gap_bars=2,
            min_unique_pitches=2,
            ignore_polyphonic_notes=True)
        chord_progressions, stats = chords_lib.extract_chords_for_melodies(
            quantized_sequence, melodies)
        expected = [[NO_CHORD, NO_CHORD, 'C', 'C', 'C', 'C', 'G7', 'G7'],
                    ['Cmaj7', 'Cmaj7', 'Cmaj7', 'Cmaj7', 'Cmaj7']]
        stats_dict = dict([(stat.name, stat) for stat in stats])
        self.assertIsNone(chord_progressions[0])
        self.assertEqual(expected,
                         [list(chords) for chords in chord_progressions[1:]])
        self.assertEqual(stats_dict['coincident_chords'].count, 1)
Exemplo n.º 7
0
    def testExtractChordsForMelodies(self):
        testing_lib.add_track_to_sequence(self.note_sequence, 0,
                                          [(12, 100, 2, 4), (11, 1, 6, 11)])
        testing_lib.add_track_to_sequence(self.note_sequence,
                                          1, [(12, 127, 2, 4), (14, 50, 6, 8),
                                              (50, 100, 33, 37),
                                              (52, 100, 34, 37)])
        testing_lib.add_chords_to_sequence(self.note_sequence, [('C', 2),
                                                                ('G7', 6),
                                                                ('Cmaj7', 33)])
        quantized_sequence = sequences_lib.quantize_note_sequence(
            self.note_sequence, self.steps_per_quarter)

        melodies, _ = melodies_lib.extract_melodies(
            quantized_sequence,
            min_bars=1,
            gap_bars=2,
            min_unique_pitches=2,
            ignore_polyphonic_notes=True)
        chord_progressions, _ = chords_lib.extract_chords_for_melodies(
            quantized_sequence, melodies)
        expected = [[
            NO_CHORD, NO_CHORD, 'C', 'C', 'C', 'C', 'G7', 'G7', 'G7', 'G7',
            'G7'
        ], [NO_CHORD, NO_CHORD, 'C', 'C', 'C', 'C', 'G7', 'G7'],
                    ['G7', 'Cmaj7', 'Cmaj7', 'Cmaj7', 'Cmaj7']]
        self.assertEqual(expected,
                         [list(chords) for chords in chord_progressions])
Exemplo n.º 8
0
 def testExtractLeadSheetFragmentsNoChords(self):
   self.quantized_sequence.steps_per_quarter = 1
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 0,
       [(12, 100, 2, 4), (11, 1, 6, 11)])
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 1,
       [(12, 127, 2, 4), (14, 50, 6, 8),
        (50, 100, 33, 37), (52, 100, 34, 37)])
   testing_lib.add_quantized_chords_to_sequence(
       self.quantized_sequence,
       [('C', 2), ('G7', 6), (NO_CHORD, 10)])
   lead_sheets, stats = lead_sheets_lib.extract_lead_sheet_fragments(
       self.quantized_sequence, min_bars=1, gap_bars=2, min_unique_pitches=2,
       ignore_polyphonic_notes=True, require_chords=True)
   melodies, _ = melodies_lib.extract_melodies(
       self.quantized_sequence, min_bars=1, gap_bars=2, min_unique_pitches=2,
       ignore_polyphonic_notes=True)
   chord_progressions, _ = chords_lib.extract_chords_for_melodies(
       self.quantized_sequence, melodies)
   stats_dict = dict([(stat.name, stat) for stat in stats])
   # Last lead sheet should be rejected for having no chords.
   self.assertEqual(list(melodies[:2]),
                    list(lead_sheet.melody for lead_sheet in lead_sheets))
   self.assertEqual(list(chord_progressions[:2]),
                    list(lead_sheet.chords for lead_sheet in lead_sheets))
   self.assertEqual(stats_dict['empty_chord_progressions'].count, 1)
Exemplo n.º 9
0
  def testExtractChordsForMelodiesCoincidentChords(self):
    testing_lib.add_track_to_sequence(
        self.note_sequence, 0,
        [(12, 100, 2, 4), (11, 1, 6, 11)])
    testing_lib.add_track_to_sequence(
        self.note_sequence, 1,
        [(12, 127, 2, 4), (14, 50, 6, 8),
         (50, 100, 33, 37), (52, 100, 34, 37)])
    testing_lib.add_chords_to_sequence(
        self.note_sequence,
        [('C', 2), ('G7', 6), ('E13', 8), ('Cmaj7', 8)])
    quantized_sequence = sequences_lib.quantize_note_sequence(
        self.note_sequence, self.steps_per_quarter)

    melodies, _ = melodies_lib.extract_melodies(
        quantized_sequence, min_bars=1, gap_bars=2, min_unique_pitches=2,
        ignore_polyphonic_notes=True)
    chord_progressions, stats = chords_lib.extract_chords_for_melodies(
        quantized_sequence, melodies)
    expected = [[NO_CHORD, NO_CHORD, 'C', 'C', 'C', 'C', 'G7', 'G7'],
                ['Cmaj7', 'Cmaj7', 'Cmaj7', 'Cmaj7', 'Cmaj7']]
    stats_dict = dict((stat.name, stat) for stat in stats)
    self.assertIsNone(chord_progressions[0])
    self.assertEqual(expected,
                     [list(chords) for chords in chord_progressions[1:]])
    self.assertEqual(stats_dict['coincident_chords'].count, 1)
Exemplo n.º 10
0
 def testExtractLeadSheetFragmentsCoincidentChords(self):
   self.quantized_sequence.steps_per_quarter = 1
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 0,
       [(12, 100, 2, 4), (11, 1, 6, 11)])
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 1,
       [(12, 127, 2, 4), (14, 50, 6, 8),
        (50, 100, 33, 37), (52, 100, 34, 37)])
   testing_lib.add_quantized_chords_to_sequence(
       self.quantized_sequence,
       [('C', 2), ('G7', 6), ('Cmaj7', 33), ('F', 33)])
   lead_sheets, _ = lead_sheets_lib.extract_lead_sheet_fragments(
       self.quantized_sequence, min_bars=1, gap_bars=2, min_unique_pitches=2,
       ignore_polyphonic_notes=True, require_chords=True)
   melodies, _ = melodies_lib.extract_melodies(
       self.quantized_sequence, min_bars=1, gap_bars=2, min_unique_pitches=2,
       ignore_polyphonic_notes=True)
   chord_progressions, _ = chords_lib.extract_chords_for_melodies(
       self.quantized_sequence, melodies)
   # Last lead sheet should be rejected for coincident chords.
   self.assertEqual(list(melodies[:2]),
                    list(lead_sheet.melody for lead_sheet in lead_sheets))
   self.assertEqual(list(chord_progressions[:2]),
                    list(lead_sheet.chords for lead_sheet in lead_sheets))
Exemplo n.º 11
0
 def testExtractLeadSheetFragmentsCoincidentChords(self):
   testing_lib.add_track_to_sequence(
       self.note_sequence, 0,
       [(12, 100, 2, 4), (11, 1, 6, 11)])
   testing_lib.add_track_to_sequence(
       self.note_sequence, 1,
       [(12, 127, 2, 4), (14, 50, 6, 8),
        (50, 100, 33, 37), (52, 100, 34, 37)])
   testing_lib.add_chords_to_sequence(
       self.note_sequence,
       [('C', 2), ('G7', 6), ('Cmaj7', 33), ('F', 33)])
   quantized_sequence = sequences_lib.quantize_note_sequence(
       self.note_sequence, steps_per_quarter=1)
   lead_sheets, _ = lead_sheets_lib.extract_lead_sheet_fragments(
       quantized_sequence, min_bars=1, gap_bars=2, min_unique_pitches=2,
       ignore_polyphonic_notes=True, require_chords=True)
   melodies, _ = melodies_lib.extract_melodies(
       quantized_sequence, min_bars=1, gap_bars=2, min_unique_pitches=2,
       ignore_polyphonic_notes=True)
   chord_progressions, _ = chords_lib.extract_chords_for_melodies(
       quantized_sequence, melodies)
   # Last lead sheet should be rejected for coincident chords.
   self.assertEqual(list(melodies[:2]),
                    list(lead_sheet.melody for lead_sheet in lead_sheets))
   self.assertEqual(list(chord_progressions[:2]),
                    list(lead_sheet.chords for lead_sheet in lead_sheets))
Exemplo n.º 12
0
 def testExtractLeadSheetFragmentsNoChords(self):
   testing_lib.add_track_to_sequence(
       self.note_sequence, 0,
       [(12, 100, 2, 4), (11, 1, 6, 11)])
   testing_lib.add_track_to_sequence(
       self.note_sequence, 1,
       [(12, 127, 2, 4), (14, 50, 6, 8),
        (50, 100, 33, 37), (52, 100, 34, 37)])
   testing_lib.add_chords_to_sequence(
       self.note_sequence,
       [('C', 2), ('G7', 6), (NO_CHORD, 10)])
   quantized_sequence = sequences_lib.quantize_note_sequence(
       self.note_sequence, steps_per_quarter=1)
   lead_sheets, stats = lead_sheets_lib.extract_lead_sheet_fragments(
       quantized_sequence, min_bars=1, gap_bars=2, min_unique_pitches=2,
       ignore_polyphonic_notes=True, require_chords=True)
   melodies, _ = melodies_lib.extract_melodies(
       quantized_sequence, min_bars=1, gap_bars=2, min_unique_pitches=2,
       ignore_polyphonic_notes=True)
   chord_progressions, _ = chords_lib.extract_chords_for_melodies(
       quantized_sequence, melodies)
   stats_dict = dict((stat.name, stat) for stat in stats)
   # Last lead sheet should be rejected for having no chords.
   self.assertEqual(list(melodies[:2]),
                    list(lead_sheet.melody for lead_sheet in lead_sheets))
   self.assertEqual(list(chord_progressions[:2]),
                    list(lead_sheet.chords for lead_sheet in lead_sheets))
   self.assertEqual(stats_dict['empty_chord_progressions'].count, 1)
Exemplo n.º 13
0
  def testExtractMelodiesStatistics(self):
    testing_lib.add_track_to_sequence(
        self.note_sequence, 0,
        [(12, 100, 2, 4), (11, 1, 6, 7), (10, 100, 8, 10), (9, 100, 11, 14),
         (8, 100, 16, 40), (7, 100, 41, 42)])
    testing_lib.add_track_to_sequence(
        self.note_sequence, 1,
        [(12, 127, 2, 4), (14, 50, 2, 8)])
    testing_lib.add_track_to_sequence(
        self.note_sequence, 2,
        [(12, 127, 0, 1)])
    testing_lib.add_track_to_sequence(
        self.note_sequence, 3,
        [(12, 127, 2, 4), (12, 50, 6, 8)])

    quantized_sequence = sequences_lib.quantize_note_sequence(
        self.note_sequence, steps_per_quarter=1)

    _, stats = melodies_lib.extract_melodies(
        quantized_sequence, min_bars=1, gap_bars=1, min_unique_pitches=2,
        ignore_polyphonic_notes=False)

    stats_dict = dict((stat.name, stat) for stat in stats)
    self.assertEqual(stats_dict['polyphonic_tracks_discarded'].count, 1)
    self.assertEqual(stats_dict['melodies_discarded_too_short'].count, 1)
    self.assertEqual(stats_dict['melodies_discarded_too_few_pitches'].count, 1)
    self.assertEqual(
        stats_dict['melody_lengths_in_bars'].counters,
        {float('-inf'): 0, 0: 0, 1: 0, 2: 0, 10: 1, 20: 0, 30: 0, 40: 0, 50: 0,
         100: 0, 200: 0, 500: 0})
Exemplo n.º 14
0
  def testExtractMelodiesPadEnd(self):
    testing_lib.add_track_to_sequence(
        self.note_sequence, 0,
        [(12, 127, 2, 4), (14, 50, 6, 7)])
    testing_lib.add_track_to_sequence(
        self.note_sequence, 1,
        [(12, 127, 2, 4), (14, 50, 6, 8)])
    testing_lib.add_track_to_sequence(
        self.note_sequence, 2,
        [(12, 127, 2, 4), (14, 50, 6, 9)])

    quantized_sequence = sequences_lib.quantize_note_sequence(
        self.note_sequence, steps_per_quarter=1)

    expected = [[NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 14,
                 NOTE_OFF],
                [NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 14,
                 NO_EVENT],
                [NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 14,
                 NO_EVENT, NO_EVENT, NOTE_OFF, NO_EVENT, NO_EVENT]]
    melodies, _ = melodies_lib.extract_melodies(
        quantized_sequence, min_bars=1, gap_bars=1, min_unique_pitches=2,
        ignore_polyphonic_notes=True, pad_end=True)
    melodies = [list(melody) for melody in melodies]
    self.assertEqual(expected, melodies)
Exemplo n.º 15
0
    def testExtractMelodiesMelodyTooLong(self):
        testing_lib.add_track_to_sequence(self.note_sequence, 0,
                                          [(12, 127, 2, 4), (14, 50, 6, 15)])
        testing_lib.add_track_to_sequence(self.note_sequence, 1,
                                          [(12, 127, 2, 4), (14, 50, 6, 18)])

        quantized_sequence = sequences_lib.quantize_note_sequence(
            self.note_sequence, steps_per_quarter=1)

        expected = [
            [NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 14] +
            [NO_EVENT] * 7,
            [NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 14] +
            [NO_EVENT] * 7
        ]
        melodies, _ = melodies_lib.extract_melodies(
            quantized_sequence,
            min_bars=1,
            max_steps_truncate=14,
            max_steps_discard=18,
            gap_bars=1,
            min_unique_pitches=2,
            ignore_polyphonic_notes=True)
        melodies = [list(melody) for melody in melodies]
        self.assertEqual(expected, melodies)
Exemplo n.º 16
0
 def testExtractLeadSheetFragments(self):
   testing_lib.add_track_to_sequence(
       self.note_sequence, 0,
       [(12, 100, .5, 1), (11, 1, 1.5, 2.75)])
   testing_lib.add_track_to_sequence(
       self.note_sequence, 1,
       [(12, 127, .5, 1), (14, 50, 1.5, 2),
        (50, 100, 8.25, 9.25), (52, 100, 8.5, 9.25)])
   testing_lib.add_chords_to_sequence(
       self.note_sequence,
       [('C', .5), ('G7', 1.5), ('Cmaj7', 8.25)])
   quantized_sequence = sequences_lib.quantize_note_sequence(
       self.note_sequence, self.steps_per_quarter)
   lead_sheets, _ = lead_sheets_lib.extract_lead_sheet_fragments(
       quantized_sequence, min_bars=1, gap_bars=2, min_unique_pitches=2,
       ignore_polyphonic_notes=True, require_chords=True)
   melodies, _ = melodies_lib.extract_melodies(
       quantized_sequence, min_bars=1, gap_bars=2, min_unique_pitches=2,
       ignore_polyphonic_notes=True)
   chord_progressions, _ = chords_lib.extract_chords_for_melodies(
       quantized_sequence, melodies)
   self.assertEqual(list(melodies),
                    list(lead_sheet.melody for lead_sheet in lead_sheets))
   self.assertEqual(list(chord_progressions),
                    list(lead_sheet.chords for lead_sheet in lead_sheets))
Exemplo n.º 17
0
  def testExtractMelodiesSimple(self):
    testing_lib.add_track_to_sequence(
        self.note_sequence, 0,
        [(12, 100, 2, 4), (11, 1, 6, 7)])
    testing_lib.add_track_to_sequence(
        self.note_sequence, 1,
        [(12, 127, 2, 4), (14, 50, 6, 9)])
    testing_lib.add_track_to_sequence(
        self.note_sequence, 9,
        [(13, 100, 2, 4), (15, 25, 6, 8)],
        is_drum=True)

    quantized_sequence = sequences_lib.quantize_note_sequence(
        self.note_sequence, steps_per_quarter=1)

    expected = [[NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 11],
                [NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 14,
                 NO_EVENT, NO_EVENT]]
    melodies, _ = melodies_lib.extract_melodies(
        quantized_sequence, min_bars=1, gap_bars=1, min_unique_pitches=2,
        ignore_polyphonic_notes=True)

    self.assertEqual(2, len(melodies))
    self.assertTrue(isinstance(melodies[0], melodies_lib.Melody))
    self.assertTrue(isinstance(melodies[1], melodies_lib.Melody))

    melodies = sorted([list(melody) for melody in melodies])
    self.assertEqual(expected, melodies)
Exemplo n.º 18
0
  def testExtractMelodiesPadEnd(self):
    testing_lib.add_track_to_sequence(
        self.note_sequence, 0,
        [(12, 127, 2, 4), (14, 50, 6, 7)])
    testing_lib.add_track_to_sequence(
        self.note_sequence, 1,
        [(12, 127, 2, 4), (14, 50, 6, 8)])
    testing_lib.add_track_to_sequence(
        self.note_sequence, 2,
        [(12, 127, 2, 4), (14, 50, 6, 9)])

    quantized_sequence = sequences_lib.quantize_note_sequence(
        self.note_sequence, steps_per_quarter=1)

    expected = [[NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 14,
                 NOTE_OFF],
                [NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 14,
                 NO_EVENT],
                [NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 14,
                 NO_EVENT, NO_EVENT, NOTE_OFF, NO_EVENT, NO_EVENT]]
    melodies, _ = melodies_lib.extract_melodies(
        quantized_sequence, min_bars=1, gap_bars=1, min_unique_pitches=2,
        ignore_polyphonic_notes=True, pad_end=True)
    melodies = [list(melody) for melody in melodies]
    self.assertEqual(expected, melodies)
Exemplo n.º 19
0
 def testExtractLeadSheetFragments(self):
   testing_lib.add_track_to_sequence(
       self.note_sequence, 0,
       [(12, 100, .5, 1), (11, 1, 1.5, 2.75)])
   testing_lib.add_track_to_sequence(
       self.note_sequence, 1,
       [(12, 127, .5, 1), (14, 50, 1.5, 2),
        (50, 100, 8.25, 9.25), (52, 100, 8.5, 9.25)])
   testing_lib.add_chords_to_sequence(
       self.note_sequence,
       [('C', .5), ('G7', 1.5), ('Cmaj7', 8.25)])
   quantized_sequence = sequences_lib.quantize_note_sequence(
       self.note_sequence, self.steps_per_quarter)
   lead_sheets, _ = lead_sheets_lib.extract_lead_sheet_fragments(
       quantized_sequence, min_bars=1, gap_bars=2, min_unique_pitches=2,
       ignore_polyphonic_notes=True, require_chords=True)
   melodies, _ = melodies_lib.extract_melodies(
       quantized_sequence, min_bars=1, gap_bars=2, min_unique_pitches=2,
       ignore_polyphonic_notes=True)
   chord_progressions, _ = chords_lib.extract_chords_for_melodies(
       quantized_sequence, melodies)
   self.assertEqual(list(melodies),
                    list(lead_sheet.melody for lead_sheet in lead_sheets))
   self.assertEqual(list(chord_progressions),
                    list(lead_sheet.chords for lead_sheet in lead_sheets))
Exemplo n.º 20
0
def extract_lead_sheet_fragments(quantized_sequence,
                                 min_bars=7,
                                 gap_bars=1.0,
                                 min_unique_pitches=5,
                                 ignore_polyphonic_notes=True,
                                 require_chords=False):
    """Extracts a list of lead sheet fragments from a quantized NoteSequence.

  This function first extracts melodies using melodies_lib.extract_melodies,
  then extracts the chords underlying each melody using
  chords_lib.extract_chords_for_melodies.

  Args:
    quantized_sequence: A quantized NoteSequence object.
    min_bars: Minimum length of melodies in number of bars. Shorter melodies are
        discarded.
    gap_bars: A melody comes to an end when this number of bars (measures) of
        silence is encountered.
    min_unique_pitches: Minimum number of unique notes with octave equivalence.
        Melodies with too few unique notes are discarded.
    ignore_polyphonic_notes: If True, melodies will be extracted from
        `quantized_sequence` tracks that contain polyphony (notes start at the
        same time). If False, tracks with polyphony will be ignored.
    require_chords: If True, only return lead sheets that have at least one
        chord other than NO_CHORD. If False, lead sheets with only melody will
        also be returned.

  Returns:
    A python list of LeadSheet instances.

  Raises:
    NonIntegerStepsPerBarException: If `quantized_sequence`'s bar length
        (derived from its time signature) is not an integer number of time
        steps.
  """
    sequences_lib.assert_is_quantized_sequence(quantized_sequence)
    stats = dict([('empty_chord_progressions',
                   statistics.Counter('empty_chord_progressions'))])
    melodies, melody_stats = melodies_lib.extract_melodies(
        quantized_sequence,
        min_bars=min_bars,
        gap_bars=gap_bars,
        min_unique_pitches=min_unique_pitches,
        ignore_polyphonic_notes=ignore_polyphonic_notes)
    chord_progressions, chord_stats = chords_lib.extract_chords_for_melodies(
        quantized_sequence, melodies)
    lead_sheets = []
    for melody, chords in zip(melodies, chord_progressions):
        if chords is not None:
            if require_chords and all(chord == chords_lib.NO_CHORD
                                      for chord in chords):
                stats['empty_chord_progressions'].increment()
            else:
                lead_sheet = LeadSheet(melody, chords)
                lead_sheets.append(lead_sheet)
    return lead_sheets, stats.values() + melody_stats + chord_stats
Exemplo n.º 21
0
def extract_lead_sheet_fragments(quantized_sequence,
                                 min_bars=7,
                                 gap_bars=1.0,
                                 min_unique_pitches=5,
                                 ignore_polyphonic_notes=True,
                                 require_chords=False):
  """Extracts a list of lead sheet fragments from a quantized NoteSequence.

  This function first extracts melodies using melodies_lib.extract_melodies,
  then extracts the chords underlying each melody using
  chords_lib.extract_chords_for_melodies.

  Args:
    quantized_sequence: A quantized NoteSequence object.
    min_bars: Minimum length of melodies in number of bars. Shorter melodies are
        discarded.
    gap_bars: A melody comes to an end when this number of bars (measures) of
        silence is encountered.
    min_unique_pitches: Minimum number of unique notes with octave equivalence.
        Melodies with too few unique notes are discarded.
    ignore_polyphonic_notes: If True, melodies will be extracted from
        `quantized_sequence` tracks that contain polyphony (notes start at the
        same time). If False, tracks with polyphony will be ignored.
    require_chords: If True, only return lead sheets that have at least one
        chord other than NO_CHORD. If False, lead sheets with only melody will
        also be returned.

  Returns:
    A python list of LeadSheet instances.

  Raises:
    NonIntegerStepsPerBarException: If `quantized_sequence`'s bar length
        (derived from its time signature) is not an integer number of time
        steps.
  """
  sequences_lib.assert_is_quantized_sequence(quantized_sequence)
  stats = dict([('empty_chord_progressions',
                 statistics.Counter('empty_chord_progressions'))])
  melodies, melody_stats = melodies_lib.extract_melodies(
      quantized_sequence, min_bars=min_bars, gap_bars=gap_bars,
      min_unique_pitches=min_unique_pitches,
      ignore_polyphonic_notes=ignore_polyphonic_notes)
  chord_progressions, chord_stats = chords_lib.extract_chords_for_melodies(
      quantized_sequence, melodies)
  lead_sheets = []
  for melody, chords in zip(melodies, chord_progressions):
    if chords is not None:
      if require_chords and all(chord == chords_lib.NO_CHORD
                                for chord in chords):
        stats['empty_chord_progressions'].increment()
      else:
        lead_sheet = LeadSheet(melody, chords)
        lead_sheets.append(lead_sheet)
  return lead_sheets, stats.values() + melody_stats + chord_stats
Exemplo n.º 22
0
 def transform(self, quantized_sequence):
     try:
         melodies, stats = melodies_lib.extract_melodies(
             quantized_sequence,
             min_bars=self.min_bars,
             min_unique_pitches=self.min_unique_pitches,
             gap_bars=self.gap_bars,
             ignore_polyphonic_notes=self.ignore_polyphonic_notes)
     except events_lib.NonIntegerStepsPerBarException as detail:
         tf.logging.warning('Skipped sequence: %s', detail)
         melodies = []
         stats = [statistics.Counter('non_integer_steps_per_bar', 1)]
     self._set_stats(stats)
     return melodies
Exemplo n.º 23
0
 def transform(self, quantized_sequence):
   try:
     melodies, stats = melodies_lib.extract_melodies(
         quantized_sequence,
         min_bars=self.min_bars,
         min_unique_pitches=self.min_unique_pitches,
         gap_bars=self.gap_bars,
         ignore_polyphonic_notes=self.ignore_polyphonic_notes)
   except melodies_lib.NonIntegerStepsPerBarException as detail:
     tf.logging.warning('Skipped sequence: %s', detail)
     melodies = []
     stats = [statistics.Counter('non_integer_steps_per_bar', 1)]
   self._set_stats(stats)
   return melodies
Exemplo n.º 24
0
 def testExtractMelodiesMelodyTooShort(self):
   self.quantized_sequence.steps_per_quarter = 1
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 0,
       [(12, 127, 2, 4), (14, 50, 6, 7)])
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 1,
       [(12, 127, 2, 4), (14, 50, 6, 9)])
   expected = [[NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 14,
                NO_EVENT, NO_EVENT]]
   melodies, _ = melodies_lib.extract_melodies(
       self.quantized_sequence, min_bars=2, gap_bars=1, min_unique_pitches=2,
       ignore_polyphonic_notes=True)
   melodies = [list(melody) for melody in melodies]
   self.assertEqual(expected, melodies)
Exemplo n.º 25
0
 def testExtractMelodiesLateStart(self):
   self.quantized_sequence.steps_per_quarter = 1
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 0,
       [(12, 100, 102, 103), (13, 100, 104, 106)])
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 1,
       [(12, 100, 100, 101), (13, 100, 102, 105)])
   expected = [[NO_EVENT, NO_EVENT, 12, NOTE_OFF, 13, NO_EVENT],
               [12, NOTE_OFF, 13, NO_EVENT, NO_EVENT]]
   melodies, _ = melodies_lib.extract_melodies(
       self.quantized_sequence, min_bars=1, gap_bars=1, min_unique_pitches=2,
       ignore_polyphonic_notes=True)
   melodies = sorted([list(melody) for melody in melodies])
   self.assertEqual(expected, melodies)
Exemplo n.º 26
0
 def testExtractMelodiesMelodyTooLongWithPad(self):
   self.quantized_sequence.steps_per_quarter = 1
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 0,
       [(12, 127, 2, 4), (14, 50, 6, 15)])
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 1,
       [(12, 127, 2, 4), (14, 50, 6, 18)])
   expected = [[NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 14,
                NO_EVENT, NO_EVENT, NO_EVENT, NO_EVENT, NO_EVENT]]
   melodies, _ = melodies_lib.extract_melodies(
       self.quantized_sequence, min_bars=1, max_steps_truncate=14,
       max_steps_discard=18, gap_bars=1, min_unique_pitches=2,
       ignore_polyphonic_notes=True, pad_end=True)
   melodies = [list(melody) for melody in melodies]
   self.assertEqual(expected, melodies)
Exemplo n.º 27
0
 def testExtractMelodiesTooFewPitches(self):
   # Test that extract_melodies discards melodies with too few pitches where
   # pitches are equivalent by octave.
   self.quantized_sequence.steps_per_quarter = 1
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 0,
       [(12, 100, 0, 1), (13, 100, 1, 2), (18, 100, 2, 3),
        (24, 100, 3, 4), (25, 100, 4, 5)])
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 1,
       [(12, 100, 0, 1), (13, 100, 1, 2), (18, 100, 2, 3),
        (25, 100, 3, 4), (26, 100, 4, 5)])
   expected = [[12, 13, 18, 25, 26]]
   melodies, _ = melodies_lib.extract_melodies(
       self.quantized_sequence, min_bars=1, gap_bars=1, min_unique_pitches=4,
       ignore_polyphonic_notes=True)
   melodies = [list(melody) for melody in melodies]
   self.assertEqual(expected, melodies)
Exemplo n.º 28
0
  def load_primer(self):
    """Loads default MIDI primer file.

    Also assigns the steps per bar of this file to be the model's defaults.
    """

    if not os.path.exists(self.midi_primer):
      tf.logging.warn('ERROR! No such primer file exists! %s', self.midi_primer)
      return

    self.primer_sequence = midi_io.midi_file_to_sequence_proto(self.midi_primer)
    quantized_seq = sequences_lib.quantize_note_sequence(
        self.primer_sequence, steps_per_quarter=4)
    extracted_melodies, _ = melodies_lib.extract_melodies(quantized_seq,
                                                          min_bars=0,
                                                          min_unique_pitches=1)
    self.primer = extracted_melodies[0]
    self.steps_per_bar = self.primer.steps_per_bar
Exemplo n.º 29
0
  def load_primer(self):
    """Loads default MIDI primer file.

    Also assigns the steps per bar of this file to be the model's defaults.
    """

    if not os.path.exists(self.midi_primer):
      tf.logging.warn('ERROR! No such primer file exists! %s', self.midi_primer)
      return

    self.primer_sequence = midi_io.midi_file_to_sequence_proto(self.midi_primer)
    quantized_seq = sequences_lib.quantize_note_sequence(
        self.primer_sequence, steps_per_quarter=4)
    extracted_melodies, _ = melodies_lib.extract_melodies(quantized_seq,
                                                          min_bars=0,
                                                          min_unique_pitches=1)
    self.primer = extracted_melodies[0]
    self.steps_per_bar = self.primer.steps_per_bar
Exemplo n.º 30
0
 def testExtractMultipleMelodiesFromSameTrack(self):
   self.quantized_sequence.steps_per_quarter = 1
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 0,
       [(12, 100, 2, 4), (11, 1, 6, 11)])
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 1,
       [(12, 127, 2, 4), (14, 50, 6, 8),
        (50, 100, 33, 37), (52, 100, 34, 37)])
   expected = [[NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 11,
                NO_EVENT, NO_EVENT, NO_EVENT, NO_EVENT],
               [NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 14,
                NO_EVENT],
               [NO_EVENT, 50, 52, NO_EVENT, NO_EVENT]]
   melodies, _ = melodies_lib.extract_melodies(
       self.quantized_sequence, min_bars=1, gap_bars=2, min_unique_pitches=2,
       ignore_polyphonic_notes=True)
   melodies = sorted([list(melody) for melody in melodies])
   self.assertEqual(expected, melodies)
Exemplo n.º 31
0
 def transform(self, quantized_sequence):
   try:
     melodies, stats = melodies_lib.extract_melodies(
         quantized_sequence,
         min_bars=self._min_bars,
         max_steps_truncate=self._max_steps,
         min_unique_pitches=self._min_unique_pitches,
         gap_bars=self._gap_bars,
         ignore_polyphonic_notes=self._ignore_polyphonic_notes,
         filter_drums=self._filter_drums)
   except events_lib.NonIntegerStepsPerBarException as detail:
     tf.logging.warning('Skipped sequence: %s', detail)
     melodies = []
     stats = [statistics.Counter('non_integer_steps_per_bar', 1)]
   except events_lib.ZeroDivisionError as detail:
     tf.logging.warning('Skipped sequence: %s', detail)
     melodies = []
     stats = [statistics.Counter('zero_division_error', 1)]
   self._set_stats(stats)
   return melodies
Exemplo n.º 32
0
 def testExtractMelodiesMelodyTooLongWithPad(self):
     self.quantized_sequence.steps_per_quarter = 1
     testing_lib.add_quantized_track(self.quantized_sequence, 0,
                                     [(12, 127, 2, 4), (14, 50, 6, 15)])
     testing_lib.add_quantized_track(self.quantized_sequence, 1,
                                     [(12, 127, 2, 4), (14, 50, 6, 18)])
     expected = [[
         NO_EVENT, NO_EVENT, 12, NO_EVENT, NOTE_OFF, NO_EVENT, 14, NO_EVENT,
         NO_EVENT, NO_EVENT, NO_EVENT, NO_EVENT
     ]]
     melodies, _ = melodies_lib.extract_melodies(
         self.quantized_sequence,
         min_bars=1,
         max_steps_truncate=14,
         max_steps_discard=18,
         gap_bars=1,
         min_unique_pitches=2,
         ignore_polyphonic_notes=True,
         pad_end=True)
     melodies = [list(melody) for melody in melodies]
     self.assertEqual(expected, melodies)
Exemplo n.º 33
0
 def testExtractChordsForMelodies(self):
   self.quantized_sequence.steps_per_quarter = 1
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 0,
       [(12, 100, 2, 4), (11, 1, 6, 11)])
   testing_lib.add_quantized_track_to_sequence(
       self.quantized_sequence, 1,
       [(12, 127, 2, 4), (14, 50, 6, 8),
        (50, 100, 33, 37), (52, 100, 34, 37)])
   testing_lib.add_quantized_chords_to_sequence(
       self.quantized_sequence,
       [('C', 2), ('G7', 6), ('Cmaj7', 33)])
   melodies, _ = melodies_lib.extract_melodies(
       self.quantized_sequence, min_bars=1, gap_bars=2, min_unique_pitches=2,
       ignore_polyphonic_notes=True)
   chord_progressions, _ = chords_lib.extract_chords_for_melodies(
       self.quantized_sequence, melodies)
   expected = [[NO_CHORD, NO_CHORD, 'C', 'C', 'C', 'C',
                'G7', 'G7', 'G7', 'G7', 'G7'],
               [NO_CHORD, NO_CHORD, 'C', 'C', 'C', 'C', 'G7', 'G7'],
               ['G7', 'Cmaj7', 'Cmaj7', 'Cmaj7', 'Cmaj7']]
   self.assertEqual(expected, [list(chords) for chords in chord_progressions])
Exemplo n.º 34
0
    def _generate(self, generate_sequence_request):
        if len(generate_sequence_request.generator_options.generate_sections
               ) != 1:
            raise sequence_generator.SequenceGeneratorException(
                'This model supports only 1 generate_sections message, but got %s'
                % (len(generate_sequence_request.generator_options.
                       generate_sections)))

        generate_section = (
            generate_sequence_request.generator_options.generate_sections[0])
        primer_sequence = generate_sequence_request.input_sequence

        notes_by_end_time = sorted(primer_sequence.notes,
                                   key=lambda n: n.end_time)
        last_end_time = notes_by_end_time[
            -1].end_time if notes_by_end_time else 0
        if last_end_time > generate_section.start_time_seconds:
            raise sequence_generator.SequenceGeneratorException(
                'Got GenerateSection request for section that is before the end of '
                'the NoteSequence. This model can only extend sequences. '
                'Requested start time: %s, Final note end time: %s' %
                (generate_section.start_time_seconds,
                 notes_by_end_time[-1].end_time))

        # Quantize the priming sequence.
        quantized_sequence = sequences_lib.QuantizedSequence()
        quantized_sequence.from_note_sequence(primer_sequence,
                                              self._steps_per_quarter)
        # Setting gap_bars to infinite ensures that the entire input will be used.
        extracted_melodies, _ = melodies_lib.extract_melodies(
            quantized_sequence,
            min_bars=0,
            min_unique_pitches=1,
            gap_bars=float('inf'),
            ignore_polyphonic_notes=True)
        assert len(extracted_melodies) <= 1

        qpm = (primer_sequence.tempos[0].qpm
               if primer_sequence and primer_sequence.tempos else
               constants.DEFAULT_QUARTERS_PER_MINUTE)
        start_step = self._seconds_to_steps(
            generate_section.start_time_seconds, qpm)
        end_step = self._seconds_to_steps(generate_section.end_time_seconds,
                                          qpm)

        if extracted_melodies and extracted_melodies[0]:
            melody = extracted_melodies[0]
        else:
            tf.logging.warn(
                'No melodies were extracted from the priming sequence. '
                'Melodies will be generated from scratch.')
            melody = melodies_lib.MonophonicMelody()
            melody.from_event_list([
                random.randint(self._melody_encoder_decoder.min_note,
                               self._melody_encoder_decoder.max_note)
            ])
            start_step += 1

        transpose_amount = melody.squash(
            self._melody_encoder_decoder.min_note,
            self._melody_encoder_decoder.max_note,
            self._melody_encoder_decoder.transpose_to_key)

        # Ensure that the melody extends up to the step we want to start generating.
        melody.set_length(start_step)

        inputs = self._session.graph.get_collection('inputs')[0]
        initial_state = self._session.graph.get_collection('initial_state')[0]
        final_state = self._session.graph.get_collection('final_state')[0]
        softmax = self._session.graph.get_collection('softmax')[0]

        final_state_ = None
        for i in range(end_step - len(melody)):
            if i == 0:
                inputs_ = self._melody_encoder_decoder.get_inputs_batch(
                    [melody], full_length=True)
                initial_state_ = self._session.run(initial_state)
            else:
                inputs_ = self._melody_encoder_decoder.get_inputs_batch(
                    [melody])
                initial_state_ = final_state_

            feed_dict = {inputs: inputs_, initial_state: initial_state_}
            final_state_, softmax_ = self._session.run([final_state, softmax],
                                                       feed_dict)
            self._melody_encoder_decoder.extend_event_sequences([melody],
                                                                softmax_)

        melody.transpose(-transpose_amount)

        generate_response = generator_pb2.GenerateSequenceResponse()
        generate_response.generated_sequence.CopyFrom(
            melody.to_sequence(qpm=qpm))
        return generate_response
Exemplo n.º 35
0
def extract_lead_sheet_fragments(quantized_sequence,
                                 search_start_step=0,
                                 min_bars=7,
                                 max_steps_truncate=None,
                                 max_steps_discard=None,
                                 gap_bars=1.0,
                                 min_unique_pitches=5,
                                 ignore_polyphonic_notes=True,
                                 pad_end=False,
                                 filter_drums=True,
                                 require_chords=False,
                                 all_transpositions=False):
    """Extracts a list of lead sheet fragments from a quantized NoteSequence.

  This function first extracts melodies using melodies_lib.extract_melodies,
  then extracts the chords underlying each melody using
  chords_lib.extract_chords_for_melodies.

  Args:
    quantized_sequence: A quantized NoteSequence object.
    search_start_step: Start searching for a melody at this time step. Assumed
        to be the first step of a bar.
    min_bars: Minimum length of melodies in number of bars. Shorter melodies are
        discarded.
    max_steps_truncate: Maximum number of steps in extracted melodies. If
        defined, longer melodies are truncated to this threshold. If pad_end is
        also True, melodies will be truncated to the end of the last bar below
        this threshold.
    max_steps_discard: Maximum number of steps in extracted melodies. If
        defined, longer melodies are discarded.
    gap_bars: A melody comes to an end when this number of bars (measures) of
        silence is encountered.
    min_unique_pitches: Minimum number of unique notes with octave equivalence.
        Melodies with too few unique notes are discarded.
    ignore_polyphonic_notes: If True, melodies will be extracted from
        `quantized_sequence` tracks that contain polyphony (notes start at the
        same time). If False, tracks with polyphony will be ignored.
    pad_end: If True, the end of the melody will be padded with NO_EVENTs so
        that it will end at a bar boundary.
    filter_drums: If True, notes for which `is_drum` is True will be ignored.
    require_chords: If True, only return lead sheets that have at least one
        chord other than NO_CHORD. If False, lead sheets with only melody will
        also be returned.
    all_transpositions: If True, also transpose each lead sheet fragment into
        all 12 keys.

  Returns:
    A python list of LeadSheet instances.

  Raises:
    NonIntegerStepsPerBarException: If `quantized_sequence`'s bar length
        (derived from its time signature) is not an integer number of time
        steps.
  """
    sequences_lib.assert_is_relative_quantized_sequence(quantized_sequence)
    stats = dict([('empty_chord_progressions',
                   statistics.Counter('empty_chord_progressions'))])
    melodies, melody_stats = melodies_lib.extract_melodies(
        quantized_sequence,
        search_start_step=search_start_step,
        min_bars=min_bars,
        max_steps_truncate=max_steps_truncate,
        max_steps_discard=max_steps_discard,
        gap_bars=gap_bars,
        min_unique_pitches=min_unique_pitches,
        ignore_polyphonic_notes=ignore_polyphonic_notes,
        pad_end=pad_end,
        filter_drums=filter_drums)
    chord_progressions, chord_stats = chords_lib.extract_chords_for_melodies(
        quantized_sequence, melodies)
    lead_sheets = []
    for melody, chords in zip(melodies, chord_progressions):
        # If `chords` is None, it's because a chord progression could not be
        # extracted for this particular melody.
        if chords is not None:
            if require_chords and all(chord == chords_lib.NO_CHORD
                                      for chord in chords):
                stats['empty_chord_progressions'].increment()
            else:
                lead_sheet = LeadSheet(melody, chords)
                if all_transpositions:
                    for amount in range(-6, 6):
                        transposed_lead_sheet = copy.deepcopy(lead_sheet)
                        transposed_lead_sheet.transpose(amount)
                        lead_sheets.append(transposed_lead_sheet)
                else:
                    lead_sheets.append(lead_sheet)
    return lead_sheets, list(stats.values()) + melody_stats + chord_stats
Exemplo n.º 36
0
def extract_lead_sheet_fragments(quantized_sequence,
                                 search_start_step=0,
                                 min_bars=7,
                                 max_steps_truncate=None,
                                 max_steps_discard=None,
                                 gap_bars=1.0,
                                 min_unique_pitches=5,
                                 ignore_polyphonic_notes=True,
                                 pad_end=False,
                                 filter_drums=True,
                                 require_chords=False,
                                 all_transpositions=False):
  """Extracts a list of lead sheet fragments from a quantized NoteSequence.

  This function first extracts melodies using melodies_lib.extract_melodies,
  then extracts the chords underlying each melody using
  chords_lib.extract_chords_for_melodies.

  Args:
    quantized_sequence: A quantized NoteSequence object.
    search_start_step: Start searching for a melody at this time step. Assumed
        to be the first step of a bar.
    min_bars: Minimum length of melodies in number of bars. Shorter melodies are
        discarded.
    max_steps_truncate: Maximum number of steps in extracted melodies. If
        defined, longer melodies are truncated to this threshold. If pad_end is
        also True, melodies will be truncated to the end of the last bar below
        this threshold.
    max_steps_discard: Maximum number of steps in extracted melodies. If
        defined, longer melodies are discarded.
    gap_bars: A melody comes to an end when this number of bars (measures) of
        silence is encountered.
    min_unique_pitches: Minimum number of unique notes with octave equivalence.
        Melodies with too few unique notes are discarded.
    ignore_polyphonic_notes: If True, melodies will be extracted from
        `quantized_sequence` tracks that contain polyphony (notes start at the
        same time). If False, tracks with polyphony will be ignored.
    pad_end: If True, the end of the melody will be padded with NO_EVENTs so
        that it will end at a bar boundary.
    filter_drums: If True, notes for which `is_drum` is True will be ignored.
    require_chords: If True, only return lead sheets that have at least one
        chord other than NO_CHORD. If False, lead sheets with only melody will
        also be returned.
    all_transpositions: If True, also transpose each lead sheet fragment into
        all 12 keys.

  Returns:
    A python list of LeadSheet instances.

  Raises:
    NonIntegerStepsPerBarException: If `quantized_sequence`'s bar length
        (derived from its time signature) is not an integer number of time
        steps.
  """
  sequences_lib.assert_is_quantized_sequence(quantized_sequence)
  stats = dict([('empty_chord_progressions',
                 statistics.Counter('empty_chord_progressions'))])
  melodies, melody_stats = melodies_lib.extract_melodies(
      quantized_sequence, search_start_step=search_start_step,
      min_bars=min_bars, max_steps_truncate=max_steps_truncate,
      max_steps_discard=max_steps_discard, gap_bars=gap_bars,
      min_unique_pitches=min_unique_pitches,
      ignore_polyphonic_notes=ignore_polyphonic_notes, pad_end=pad_end,
      filter_drums=filter_drums)
  chord_progressions, chord_stats = chords_lib.extract_chords_for_melodies(
      quantized_sequence, melodies)
  lead_sheets = []
  for melody, chords in zip(melodies, chord_progressions):
    # If `chords` is None, it's because a chord progression could not be
    # extracted for this particular melody.
    if chords is not None:
      if require_chords and all(chord == chords_lib.NO_CHORD
                                for chord in chords):
        stats['empty_chord_progressions'].increment()
      else:
        lead_sheet = LeadSheet(melody, chords)
        if all_transpositions:
          for amount in range(-6, 6):
            transposed_lead_sheet = copy.deepcopy(lead_sheet)
            transposed_lead_sheet.transpose(amount)
            lead_sheets.append(transposed_lead_sheet)
        else:
          lead_sheets.append(lead_sheet)
  return lead_sheets, stats.values() + melody_stats + chord_stats