コード例 #1
0
ファイル: sequences_lib.py プロジェクト: Alice-ren/magenta
def infer_dense_chords_for_sequence(
    sequence, instrument=None, min_notes_per_chord=3):
  """Infers chords for a NoteSequence and adds them as TextAnnotations.

  For each set of simultaneously-active notes in a NoteSequence (optionally for
  only one instrument), infers a chord symbol and adds it to NoteSequence as a
  TextAnnotation. Every change in the set of active notes will result in a new
  chord symbol unless the new set is smaller than `min_notes_per_chord`.

  If `sequence` is quantized, simultaneity will be determined by quantized steps
  instead of time.

  Not to be confused with the chord inference in magenta.music.chord_inference
  that attempts to infer a more natural chord sequence with changes at regular
  metric intervals.

  Args:
    sequence: The NoteSequence for which chords will be inferred. Will be
        modified in place.
    instrument: The instrument number whose notes will be used for chord
        inference. If None, all instruments will be used.
    min_notes_per_chord: The minimum number of simultaneous notes for which to
        infer a chord.

  Raises:
    ChordSymbolException: If a chord cannot be determined for a set of
    simultaneous notes in `sequence`.
  """
  notes = [note for note in sequence.notes
           if not note.is_drum and (instrument is None or
                                    note.instrument == instrument)]
  sorted_notes = sorted(notes, key=lambda note: note.start_time)

  # If the sequence is quantized, use quantized steps instead of time.
  if is_quantized_sequence(sequence):
    note_start = lambda note: note.quantized_start_step
    note_end = lambda note: note.quantized_end_step
  else:
    note_start = lambda note: note.start_time
    note_end = lambda note: note.end_time

  # Sort all note start and end events.
  onsets = [(note_start(note), idx, False)
            for idx, note in enumerate(sorted_notes)]
  offsets = [(note_end(note), idx, True)
             for idx, note in enumerate(sorted_notes)]
  events = sorted(onsets + offsets)

  current_time = 0
  current_figure = constants.NO_CHORD
  active_notes = set()

  for time, idx, is_offset in events:
    if time > current_time:
      active_pitches = set(sorted_notes[idx].pitch for idx in active_notes)
      if len(active_pitches) >= min_notes_per_chord:
        # Infer a chord symbol for the active pitches.
        figure = chord_symbols_lib.pitches_to_chord_symbol(active_pitches)

        if figure != current_figure:
          # Add a text annotation to the sequence.
          text_annotation = sequence.text_annotations.add()
          text_annotation.text = figure
          text_annotation.annotation_type = CHORD_SYMBOL
          if is_quantized_sequence(sequence):
            text_annotation.time = (
                current_time * sequence.quantization_info.steps_per_quarter)
            text_annotation.quantized_step = current_time
          else:
            text_annotation.time = current_time

        current_figure = figure

    current_time = time
    if is_offset:
      active_notes.remove(idx)
    else:
      active_notes.add(idx)

  assert not active_notes
コード例 #2
0
    def testPitchesToChordSymbol(self):
        # Test basic triads.
        figure = chord_symbols_lib.pitches_to_chord_symbol([60, 64, 67])
        self.assertEqual('C', figure)
        figure = chord_symbols_lib.pitches_to_chord_symbol([45, 48, 52])
        self.assertEqual('Am', figure)
        figure = chord_symbols_lib.pitches_to_chord_symbol([63, 66, 69])
        self.assertEqual('Ebo', figure)
        figure = chord_symbols_lib.pitches_to_chord_symbol([71, 75, 79])
        self.assertEqual('B+', figure)

        # Test basic inversions.
        figure = chord_symbols_lib.pitches_to_chord_symbol([59, 62, 67])
        self.assertEqual('G/B', figure)
        figure = chord_symbols_lib.pitches_to_chord_symbol([65, 70, 73])
        self.assertEqual('Bbm/F', figure)

        # Test suspended chords.
        figure = chord_symbols_lib.pitches_to_chord_symbol([62, 67, 69])
        self.assertEqual('Dsus', figure)
        figure = chord_symbols_lib.pitches_to_chord_symbol([55, 60, 62, 65])
        self.assertEqual('Gsus7', figure)
        figure = chord_symbols_lib.pitches_to_chord_symbol([67, 69, 74])
        self.assertEqual('Gsus2', figure)

        # Test more complex chords.
        figure = chord_symbols_lib.pitches_to_chord_symbol([45, 46, 50, 53])
        self.assertEqual('Bbmaj7/A', figure)
        figure = chord_symbols_lib.pitches_to_chord_symbol(
            [63, 67, 70, 72, 74])
        self.assertEqual('Cm9/Eb', figure)
        figure = chord_symbols_lib.pitches_to_chord_symbol(
            [53, 60, 64, 67, 70])
        self.assertEqual('C7/F', figure)

        # Test chords with modifications.
        figure = chord_symbols_lib.pitches_to_chord_symbol(
            [67, 71, 72, 74, 77])
        self.assertEqual('G7(add4)', figure)
        figure = chord_symbols_lib.pitches_to_chord_symbol(
            [64, 68, 71, 74, 79])
        self.assertEqual('E7(#9)', figure)
        figure = chord_symbols_lib.pitches_to_chord_symbol([60, 62, 64, 67])
        self.assertEqual('C(add2)', figure)
        figure = chord_symbols_lib.pitches_to_chord_symbol(
            [60, 64, 68, 70, 75])
        self.assertEqual('C+7(#9)', figure)

        # Test invalid chord.
        with self.assertRaises(chord_symbols_lib.ChordSymbolError):
            chord_symbols_lib.pitches_to_chord_symbol(
                [60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71])
コード例 #3
0
ファイル: sequences_lib.py プロジェクト: xiangyuwei/magenta
def infer_chords_for_sequence(sequence,
                              instrument=None,
                              min_notes_per_chord=3):
    """Infers chords for a NoteSequence and adds them as TextAnnotations.

  For each set of simultaneously-active notes in a NoteSequence (optionally for
  only one instrument), infers a chord symbol and adds it to NoteSequence as a
  TextAnnotation. Every change in the set of active notes will result in a new
  chord symbol unless the new set is smaller than `min_notes_per_chord`.

  If `sequence` is quantized, simultaneity will be determined by quantized steps
  instead of time.

  Args:
    sequence: The NoteSequence for which chords will be inferred. Will be
        modified in place.
    instrument: The instrument number whose notes will be used for chord
        inference. If None, all instruments will be used.
    min_notes_per_chord: The minimum number of simultaneous notes for which to
        infer a chord.

  Raises:
    ChordSymbolException: If a chord cannot be determined for a set of
    simultaneous notes in `sequence`.
  """
    notes = [
        note for note in sequence.notes if not note.is_drum and (
            instrument is None or note.instrument == instrument)
    ]
    sorted_notes = sorted(notes, key=lambda note: note.start_time)

    # If the sequence is quantized, use quantized steps instead of time.
    if is_quantized_sequence(sequence):
        note_start = lambda note: note.quantized_start_step
        note_end = lambda note: note.quantized_end_step
    else:
        note_start = lambda note: note.start_time
        note_end = lambda note: note.end_time

    # Sort all note start and end events.
    onsets = [(note_start(note), idx, False)
              for idx, note in enumerate(sorted_notes)]
    offsets = [(note_end(note), idx, True)
               for idx, note in enumerate(sorted_notes)]
    events = sorted(onsets + offsets)

    current_time = 0
    current_figure = constants.NO_CHORD
    active_notes = set()

    for time, idx, is_offset in events:
        if time > current_time:
            active_pitches = set(sorted_notes[idx].pitch
                                 for idx in active_notes)
            if len(active_pitches) >= min_notes_per_chord:
                # Infer a chord symbol for the active pitches.
                figure = chord_symbols_lib.pitches_to_chord_symbol(
                    active_pitches)

                if figure != current_figure:
                    # Add a text annotation to the sequence.
                    text_annotation = sequence.text_annotations.add()
                    text_annotation.text = figure
                    text_annotation.annotation_type = CHORD_SYMBOL
                    if is_quantized_sequence(sequence):
                        text_annotation.time = (
                            current_time *
                            sequence.quantization_info.steps_per_quarter)
                        text_annotation.quantized_step = current_time
                    else:
                        text_annotation.time = current_time

                current_figure = figure

        current_time = time
        if is_offset:
            active_notes.remove(idx)
        else:
            active_notes.add(idx)

    assert not active_notes
コード例 #4
0
  def testPitchesToChordSymbol(self):
    # Test basic triads.
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [60, 64, 67])
    self.assertEqual('C', figure)
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [45, 48, 52])
    self.assertEqual('Am', figure)
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [63, 66, 69])
    self.assertEqual('Ebo', figure)
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [71, 75, 79])
    self.assertEqual('B+', figure)

    # Test basic inversions.
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [59, 62, 67])
    self.assertEqual('G/B', figure)
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [65, 70, 73])
    self.assertEqual('Bbm/F', figure)

    # Test suspended chords.
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [62, 67, 69])
    self.assertEqual('Dsus', figure)
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [55, 60, 62, 65])
    self.assertEqual('Gsus7', figure)
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [67, 69, 74])
    self.assertEqual('Gsus2', figure)

    # Test more complex chords.
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [45, 46, 50, 53])
    self.assertEqual('Bbmaj7/A', figure)
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [63, 67, 70, 72, 74])
    self.assertEqual('Cm9/Eb', figure)
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [53, 60, 64, 67, 70])
    self.assertEqual('C7/F', figure)

    # Test chords with modifications.
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [67, 71, 72, 74, 77])
    self.assertEqual('G7(add4)', figure)
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [64, 68, 71, 74, 79])
    self.assertEqual('E7(#9)', figure)
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [60, 62, 64, 67])
    self.assertEqual('C(add2)', figure)
    figure = chord_symbols_lib.pitches_to_chord_symbol(
        [60, 64, 68, 70, 75])
    self.assertEqual('C+7(#9)', figure)

    # Test invalid chord.
    with self.assertRaises(chord_symbols_lib.ChordSymbolException):
      chord_symbols_lib.pitches_to_chord_symbol(
          [60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71])