def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.set_defaults(func=main)
    parser.add_argument('input_file',
                        type=argparse.FileType('rb'),
                        metavar='FILE')
    parser.add_argument('output_dir', type=str, metavar='OUTPUTDIR')
    parser.add_argument('-i', '--instrument', type=str, default='')
    parser.add_argument('--drums', action='store_true')
    parser.add_argument('-p', '--program', type=int)
    parser.add_argument('--stretch', type=str)
    parser.add_argument('--tempo', type=float)
    parser.add_argument('--time-signature',
                        type=lambda s: tuple(int(x) for x in s.split('/')),
                        default=(4, 4))
    parser.add_argument('--resolution', type=int, default=480)
    parser.add_argument(
        '--range',
        type=lambda r: [None if x == '' else int(x) for x in r.split(':')])
    parser.add_argument('--group-by-name', action='store_true')
    parser.add_argument('--time-unit', type=float)
    args = parser.parse_args()

    if args.program is None:
        if args.instrument:
            args.program = pretty_midi.instrument_name_to_program(
                args.instrument)
        else:
            args.program = 0

    tempo = 60.
    if args.stretch:
        # Calculate the time stretch ratio
        if ':' in args.stretch:
            a, b = args.stretch.split(':')
            args.stretch = float(a) / float(b)
            tempo = float(b)
        else:
            args.stretch = float(args.stretch)
            tempo = tempo / args.stretch
    if args.tempo:
        tempo = args.tempo

    data = pickle.load(args.input_file)
    fill_length = len(str(len(data) - 1))

    if args.range:
        data = data[slice(*args.range)]

    if args.group_by_name:
        grouped = collections.defaultdict(list)
        for (name, start, end), notes in data:
            start, end = start * args.time_unit, end * args.time_unit
            grouped[name].extend(
                _shift_and_clip(note, start, end) for note in notes
                if note.start + start < end and note.end > 0.)
        data = list(grouped.items())

    for i, segment in enumerate(data):
        midi = pretty_midi.PrettyMIDI(initial_tempo=tempo,
                                      resolution=args.resolution)

        if args.range and args.range[0]:
            i += args.range[0]
        index = str(i).zfill(fill_length)
        if isinstance(segment, list):
            notes = segment
            fname = f'{index}.mid'
        elif isinstance(segment, tuple) and len(segment) == 2:
            segment_id, notes = segment
            if not isinstance(segment_id, str):
                segment_id = '_'.join(str(x) for x in segment_id)
            fname = f'{index}_{segment_id}.mid'
        else:
            raise RuntimeError(f'Cannot parse segment: {segment}')

        if args.stretch is not None:
            for note in notes:
                note.start *= args.stretch
                note.end *= args.stretch

        # Remove notes with length below the MIDI resolution
        notes = [
            note for note in notes
            if midi.time_to_tick(note.start) < midi.time_to_tick(note.end)
        ]

        # Some notes might be overlapping, we need to split them between multiple tracks.
        # TODO: This calls for a more efficient implementation.
        tracks = [[]]
        for note in notes:
            for track in tracks:
                # Find the first track without an overlapping note.
                if not any(note2.pitch == note.pitch and note2.start < note.end
                           and note2.end > note.start for note2 in track):
                    track.append(note)
                    break

            # Always keep the last track empty (we delete it afterwards)
            if tracks[-1]:
                tracks.append([])
        del tracks[-1]

        midi.time_signature_changes[:] = [
            pretty_midi.TimeSignature(*args.time_signature, 0.)
        ]

        for track in tracks:
            instrument = pretty_midi.Instrument(name=args.instrument,
                                                program=args.program,
                                                is_drum=args.drums)
            instrument.notes[:] = track
            midi.instruments.append(instrument)

        midi.write(os.path.join(args.output_dir, fname))
Example #2
0
def sequence_proto_to_pretty_midi(sequence):
    """Convert tensorflow.magenta.NoteSequence proto to a PrettyMIDI.

  Time is stored in the NoteSequence in absolute values (seconds) as opposed to
  relative values (MIDI ticks). When the NoteSequence is translated back to
  PrettyMIDI the absolute time is retained. The tempo map is also recreated.

  Args:
    sequence: A tensorfow.magenta.NoteSequence proto.

  Returns:
    A pretty_midi.PrettyMIDI object or None if sequence could not be decoded.
  """

    kwargs = {}
    if sequence.tempos and sequence.tempos[0].time == 0:
        kwargs['initial_tempo'] = sequence.tempos[0].bpm
    pm = pretty_midi.PrettyMIDI(resolution=sequence.ticks_per_beat, **kwargs)

    # Create an empty instrument to contain time and key signatures.
    instrument = pretty_midi.Instrument(0)
    pm.instruments.append(instrument)

    # Populate time signatures.
    for seq_ts in sequence.time_signatures:
        time_signature = pretty_midi.containers.TimeSignature(
            seq_ts.numerator, seq_ts.denominator, seq_ts.time)
        pm.time_signature_changes.append(time_signature)

    # Populate key signatures.
    for seq_key in sequence.key_signatures:
        key_number = seq_key.key
        if seq_key.mode == seq_key.MINOR:
            key_number += _PRETTY_MIDI_MAJOR_TO_MINOR_OFFSET
        key_signature = pretty_midi.containers.KeySignature(
            key_number, seq_key.time)
        pm.key_signature_changes.append(key_signature)

    # Populate tempo. The first tempo change was done in PrettyMIDI constructor.
    # TODO(@douglaseck): Update this code if pretty_midi adds the ability to
    # write tempo.
    if len(sequence.tempos) > 1:
        for seq_tempo in sequence.tempos[1:]:
            tick_scale = 60.0 / (pm.resolution * seq_tempo.bpm)
            tick = pm.time_to_tick(seq_tempo.time)
            # pylint: disable=protected-access
            pm._PrettyMIDI__tick_scales.append((tick, tick_scale))
            # pylint: enable=protected-access

    # Populate instrument events by first gathering notes and other event types
    # in lists then write them sorted to the PrettyMidi object.
    instrument_events = defaultdict(lambda: defaultdict(list))
    for seq_note in sequence.notes:
        instrument_events[(seq_note.instrument,
                           seq_note.program)]['notes'].append(
                               pretty_midi.Note(seq_note.velocity,
                                                seq_note.pitch,
                                                seq_note.start_time,
                                                seq_note.end_time))
    for seq_bend in sequence.pitch_bends:
        instrument_events[(seq_bend.instrument,
                           seq_bend.program)]['bends'].append(
                               pretty_midi.PitchBend(seq_bend.bend,
                                                     seq_bend.time))
    for seq_cc in sequence.control_changes:
        instrument_events[(seq_cc.instrument,
                           seq_cc.program)]['controls'].append(
                               pretty_midi.ControlChange(
                                   seq_cc.control_number, seq_cc.control_value,
                                   seq_cc.time))

    for (instr_id, prog_id) in sorted(instrument_events.keys()):
        # For instr_id 0 append to the instrument created above.
        if instr_id > 0:
            instrument = pretty_midi.Instrument(prog_id,
                                                is_drum=(instr_id == 9))
            pm.instruments.append(instrument)
        instrument.program = prog_id
        instrument.notes = instrument_events[(instr_id, prog_id)]['notes']
        instrument.pitch_bends = instrument_events[(instr_id,
                                                    prog_id)]['bends']
        instrument.control_changes = instrument_events[(instr_id,
                                                        prog_id)]['controls']

    return pm
Example #3
0
def test_get_piano_roll_and_get_chroma():
    pm = pretty_midi.PrettyMIDI()
    assert pm.get_piano_roll().shape == (128, 0)
    # Currently just a rudimentary test since it's hard to test things like
    # pitch bends correctly
    inst = pretty_midi.Instrument(0)
    pm.instruments.append(inst)
    inst.notes.append(
        pretty_midi.Note(pitch=40, velocity=100, start=0.05, end=0.45))
    inst = pretty_midi.Instrument(0)
    pm.instruments.append(inst)
    inst.notes.append(
        pretty_midi.Note(pitch=40, velocity=50, start=0.35, end=0.5))
    inst.notes.append(
        pretty_midi.Note(pitch=45, velocity=100, start=0.1, end=0.2))

    inst = pretty_midi.Instrument(0)
    pm.instruments.append(inst)
    inst.control_changes.append(
        pretty_midi.ControlChange(number=64, value=65, time=0.12))
    inst.control_changes.append(
        pretty_midi.ControlChange(number=64, value=63, time=0.5))
    inst.notes.append(
        pretty_midi.Note(pitch=50, velocity=50, start=0.35, end=0.4))
    inst.notes.append(
        pretty_midi.Note(pitch=55, velocity=20, start=0.1, end=0.15))
    inst.notes.append(
        pretty_midi.Note(pitch=55, velocity=10, start=0.2, end=0.25))
    inst.notes.append(
        pretty_midi.Note(pitch=55, velocity=50, start=0.3, end=0.42))

    expected_piano_roll = np.zeros((128, 50))
    expected_piano_roll[40, 5:35] = 100
    expected_piano_roll[40, 35:45] = 150
    expected_piano_roll[40, 45:] = 50
    expected_piano_roll[45, 10:20] = 100
    expected_piano_roll[50, 35:40] = 50
    expected_piano_roll[55, 10:15] = 20
    expected_piano_roll[55, 20:25] = 10
    expected_piano_roll[55, 30:42] = 50
    assert np.allclose(pm.get_piano_roll(pedal_threshold=None),
                       expected_piano_roll)

    expected_piano_roll[50, 35:50] = 50
    expected_piano_roll[55, 10:30] = 20
    expected_piano_roll[55, 30:50] = 50
    assert np.allclose(pm.get_piano_roll(), expected_piano_roll)

    expected_chroma = np.zeros((12, 50))
    expected_chroma[4, 5:35] = 100
    expected_chroma[4, 35:45] = 150
    expected_chroma[4, 45:] = 50
    expected_chroma[9, 10:20] = 100
    expected_chroma[2, 35:40] = 50
    expected_chroma[7, 10:15] = 20
    expected_chroma[7, 20:25] = 10
    expected_chroma[7, 30:42] = 50
    assert np.allclose(pm.get_chroma(pedal_threshold=None), expected_chroma)

    expected_chroma[2, 35:50] = 50
    expected_chroma[7, 10:30] = 20
    expected_chroma[7, 30:50] = 50
    assert np.allclose(pm.get_chroma(), expected_chroma)
Example #4
0
def tx1_to_midi(tx1):
  import pretty_midi

  tx1 = tx1.strip().splitlines()
  nsamps = sum([int(x.split('_')[1]) for x in tx1 if x[:2] == 'WT'])

  # Create MIDI instruments
  p1_prog = pretty_midi.instrument_name_to_program('Lead 1 (square)')
  p2_prog = pretty_midi.instrument_name_to_program('Lead 2 (sawtooth)')
  tr_prog = pretty_midi.instrument_name_to_program('Synth Bass 1')
  no_prog = pretty_midi.instrument_name_to_program('Breath Noise')
  p1 = pretty_midi.Instrument(program=p1_prog, name='p1', is_drum=False)
  p2 = pretty_midi.Instrument(program=p2_prog, name='p2', is_drum=False)
  tr = pretty_midi.Instrument(program=tr_prog, name='tr', is_drum=False)
  no = pretty_midi.Instrument(program=no_prog, name='no', is_drum=True)

  name_to_ins = {'P1': p1, 'P2': p2, 'TR': tr, 'NO': no}
  name_to_pitch = {'P1': None, 'P2': None, 'TR': None, 'NO': None}
  name_to_start = {'P1': None, 'P2': None, 'TR': None, 'NO': None}
  name_to_max_velocity = {'P1': 15, 'P2': 15, 'TR': 1, 'NO': 15}

  samp = 0
  for event in tx1:
    if event[:2] == 'WT':
      samp += int(event[3:])
    else:
      tokens = event.split('_')
      name = tokens[0]
      ins = name_to_ins[tokens[0]]

      old_pitch = name_to_pitch[name]
      if tokens[1] == 'NOTEON':
        if old_pitch is not None:
          ins.notes.append(pretty_midi.Note(
              velocity=name_to_max_velocity[name],
              pitch=old_pitch,
              start=name_to_start[name] / 44100.,
              end=samp / 44100.))
        name_to_pitch[name] = int(tokens[2])
        name_to_start[name] = samp
      else:
        if old_pitch is not None:
          ins.notes.append(pretty_midi.Note(
              velocity=name_to_max_velocity[name],
              pitch=name_to_pitch[name],
              start=name_to_start[name] / 44100.,
              end=samp / 44100.))

        name_to_pitch[name] = None
        name_to_start[name] = None

  # Deactivating this for generated files
  #for name, pitch in name_to_pitch.items():
  #  assert pitch is None

  # Create MIDI and add instruments
  midi = pretty_midi.PrettyMIDI(initial_tempo=120, resolution=22050)
  midi.instruments.extend([p1, p2, tr, no])

  # Create indicator for end of song
  eos = pretty_midi.TimeSignature(1, 1, nsamps / 44100.)
  midi.time_signature_changes.append(eos)

  with tempfile.NamedTemporaryFile('rb') as mf:
    midi.write(mf.name)
    midi_str = mf.read()

  return midi, midi_str
Example #5
0
def sequence_proto_to_pretty_midi(sequence,
                                  drop_events_n_seconds_after_last_note=None):
    """Convert tensorflow.magenta.NoteSequence proto to a PrettyMIDI.

  Time is stored in the NoteSequence in absolute values (seconds) as opposed to
  relative values (MIDI ticks). When the NoteSequence is translated back to
  PrettyMIDI the absolute time is retained. The tempo map is also recreated.

  Args:
    sequence: A tensorfow.magenta.NoteSequence proto.
    drop_events_n_seconds_after_last_note: Events (e.g., time signature changes)
        that occur this many seconds after the last note will be dropped. If
        None, then no events will be dropped.

  Returns:
    A pretty_midi.PrettyMIDI object or None if sequence could not be decoded.
  """

    ticks_per_quarter = (sequence.ticks_per_quarter
                         if sequence.ticks_per_quarter else
                         constants.STANDARD_PPQ)

    max_event_time = None
    if drop_events_n_seconds_after_last_note is not None:
        max_event_time = (max([n.end_time for n in sequence.notes] or [0]) +
                          drop_events_n_seconds_after_last_note)

    # Try to find a tempo at time zero. The list is not guaranteed to be in order.
    initial_seq_tempo = None
    for seq_tempo in sequence.tempos:
        if seq_tempo.time == 0:
            initial_seq_tempo = seq_tempo
            break

    kwargs = {}
    kwargs['initial_tempo'] = (initial_seq_tempo.qpm if initial_seq_tempo else
                               constants.DEFAULT_QUARTERS_PER_MINUTE)
    pm = pretty_midi.PrettyMIDI(resolution=ticks_per_quarter, **kwargs)

    # Create an empty instrument to contain time and key signatures.
    instrument = pretty_midi.Instrument(0)
    pm.instruments.append(instrument)

    # Populate time signatures.
    for seq_ts in sequence.time_signatures:
        if max_event_time and seq_ts.time > max_event_time:
            continue
        time_signature = pretty_midi.containers.TimeSignature(
            seq_ts.numerator, seq_ts.denominator, seq_ts.time)
        pm.time_signature_changes.append(time_signature)

    # Populate key signatures.
    for seq_key in sequence.key_signatures:
        if max_event_time and seq_key.time > max_event_time:
            continue
        key_number = seq_key.key
        if seq_key.mode == seq_key.MINOR:
            key_number += _PRETTY_MIDI_MAJOR_TO_MINOR_OFFSET
        key_signature = pretty_midi.containers.KeySignature(
            key_number, seq_key.time)
        pm.key_signature_changes.append(key_signature)

    # Populate tempos.
    # TODO(douglaseck): Update this code if pretty_midi adds the ability to
    # write tempo.
    for seq_tempo in sequence.tempos:
        # Skip if this tempo was added in the PrettyMIDI constructor.
        if seq_tempo == initial_seq_tempo:
            continue
        if max_event_time and seq_tempo.time > max_event_time:
            continue
        tick_scale = 60.0 / (pm.resolution * seq_tempo.qpm)
        tick = pm.time_to_tick(seq_tempo.time)
        # pylint: disable=protected-access
        pm._tick_scales.append((tick, tick_scale))
        pm._update_tick_to_time(0)
        # pylint: enable=protected-access

    # Populate instrument events by first gathering notes and other event types
    # in lists then write them sorted to the PrettyMidi object.
    instrument_events = defaultdict(lambda: defaultdict(list))
    for seq_note in sequence.notes:
        instrument_events[(seq_note.instrument, seq_note.program,
                           seq_note.is_drum)]['notes'].append(
                               pretty_midi.Note(seq_note.velocity,
                                                seq_note.pitch,
                                                seq_note.start_time,
                                                seq_note.end_time))
    for seq_bend in sequence.pitch_bends:
        if max_event_time and seq_bend.time > max_event_time:
            continue
        instrument_events[(seq_bend.instrument, seq_bend.program,
                           seq_bend.is_drum)]['bends'].append(
                               pretty_midi.PitchBend(seq_bend.bend,
                                                     seq_bend.time))
    for seq_cc in sequence.control_changes:
        if max_event_time and seq_cc.time > max_event_time:
            continue
        instrument_events[(seq_cc.instrument, seq_cc.program,
                           seq_cc.is_drum)]['controls'].append(
                               pretty_midi.ControlChange(
                                   seq_cc.control_number, seq_cc.control_value,
                                   seq_cc.time))

    for (instr_id, prog_id, is_drum) in sorted(instrument_events.keys()):
        # For instr_id 0 append to the instrument created above.
        if instr_id > 0:
            instrument = pretty_midi.Instrument(prog_id, is_drum)
            pm.instruments.append(instrument)
        instrument.program = prog_id
        instrument.notes = instrument_events[(instr_id, prog_id,
                                              is_drum)]['notes']
        instrument.pitch_bends = instrument_events[(instr_id, prog_id,
                                                    is_drum)]['bends']
        instrument.control_changes = instrument_events[(instr_id, prog_id,
                                                        is_drum)]['controls']

    return pm
Example #6
0
import glob, os
import pretty_midi

out_midis, out_names = ([], [])

os.chdir("../midi/piano_midi")
for file in glob.glob("*.mid"):
    pm = pretty_midi.PrettyMIDI(file)
    filename = file.split('.mid')[0]
    print("Working on %s..." % filename)

    piano_midi = pretty_midi.PrettyMIDI(
    )  # Create the new monophonic midi file
    piano_program = pretty_midi.instrument_name_to_program(
        'Acoustic Grand Piano')
    piano = pretty_midi.Instrument(
        program=piano_program)  # Create a piano instrument

    pitch, onset, offset = (-1, -1, -1)
    pm.instruments[0].notes.sort(key=lambda x: x.start, reverse=False)
    for note in pm.instruments[
            0].notes:  # Append the notes to the piano instrument
        if (note.start == onset):  # If two notes start at the same time
            if (note.pitch > pitch):
                piano.notes[len(piano.notes) -
                            1] = note  # Select the note with the higher pitch
            else:
                continue
        else:
            if (len(piano.notes) > 0
                    and note.start < offset):  # If the previous note remains,
                piano.notes[len(piano.notes) -
Example #7
0
def interpolation(args, model, dataset, fs=25, program=0):
    x_a, x_b = dataset[random.randint(
        0,
        len(dataset) - 1)], dataset[random.randint(0,
                                                   len(dataset) - 1)]
    x_a, x_b = x_a.to(args.device), x_b.to(args.device)
    # Encode samples to the latent space
    z_a, z_b = model.encode(x_a.unsqueeze(0)), model.encode(x_b.unsqueeze(0))
    # Run through alpha values
    interp = []
    alpha_values = np.linspace(0, 1, args.n_steps)
    for alpha in alpha_values:
        z_interp = (1 - alpha) * z_a[0] + alpha * z_b[0]
        interp.append(model.decode(z_interp))
    # Draw interpolation step by step
    i = 0
    stack_interp = []
    for step in interp:
        if args.num_classes > 1:
            step = torch.argmax(step[0], dim=0)
        stack_interp.append(step)
        # plt.matshow(step.cpu().detach(), alpha=1)
        # plt.title("Interpolation " + str(i))
        # plt.savefig(args.figures_path + "interpolation" + str(i) + ".png")
        # plt.close()
        i += 1
    stack_interp = torch.cat(stack_interp, dim=1)
    # Draw stacked interpolation
    plt.figure()
    plt.matshow(stack_interp.cpu(), alpha=1)
    plt.title("Interpolation")
    plt.savefig(args.figures_path + "interpolation.png")
    plt.close()
    # Generate MIDI from interpolation
    pm = pretty_midi.PrettyMIDI()
    notes, frames = stack_interp.shape
    instrument = pretty_midi.Instrument(program=program)
    # Pad 1 column of zeros to acknowledge initial and ending events
    piano_roll = np.pad(stack_interp.cpu().detach(), [(0, 0), (1, 1)],
                        'constant')
    # Use changes in velocities to find note on/note off events
    velocity_changes = np.nonzero(np.diff(piano_roll).T)
    # Keep track on velocities and note on times
    prev_velocities = np.zeros(notes, dtype=int)
    note_on_time = np.zeros(notes)
    for time, note in zip(*velocity_changes):
        # Use time + 1s because of padding above
        velocity = piano_roll[note, time + 1]
        time = time / fs
        if velocity > 0:
            if prev_velocities[note] == 0:
                note_on_time[note] = time
                prev_velocities[note] = 75
        else:
            pm_note = pretty_midi.Note(velocity=prev_velocities[note],
                                       pitch=note + args.min_pitch,
                                       start=note_on_time[note],
                                       end=time)
            instrument.notes.append(pm_note)
            prev_velocities[note] = 0
    pm.instruments.append(instrument)
    # Write out the MIDI data
    pm.write(args.midi_results_path + "interpolation.mid")
Example #8
0
except IOError:
    print("Could not open file ", est_file_name)
    exit()

print("Transcription: Generating MIDI to ", out_file_name)

est = np.loadtxt(est_file_name)
t1 = est[:, 0].reshape((est.shape[0], ))
t2 = est[:, 1].reshape((est.shape[0], ))
f = est[:, 2].reshape((est.shape[0], ))

# Create a PrettyMIDI object
piano_chord = pretty_midi.PrettyMIDI()
# Create an Instrument instance for a piano instrument
piano_program = pretty_midi.instrument_name_to_program('Acoustic Grand Piano')
piano = pretty_midi.Instrument(program=piano_program)
# Iterate over note names, which will be converted to note number later
for f_idx in range(f.shape[0]):
    # Retrieve the MIDI note number for this note name
    note_pitch = int(round(pretty_midi.hz_to_note_number(f[f_idx])))
    if note_pitch > 127 or note_pitch < 0:
        print(note_pitch)
        input("OMG !!")
        note_pitch = 0 if note_pitch < 0 else 127
    #note_number = pretty_midi.note_name_to_number(note_name)
    # Create a Note instance, starting at 0s and ending at .5s
    note = pretty_midi.Note(velocity=100,
                            pitch=note_pitch,
                            start=t1[f_idx],
                            end=t2[f_idx])
    # Add it to our cello instrument
Example #9
0
        sp = s[-2:]
        fixed_flats.append(sp)
    flat_free_tone_row = [s for s in tone_row if not ("/" in s)]
    flatty_tone_row = fixed_flats + flat_free_tone_row
    random_tone_row = random.sample(flatty_tone_row, len(flatty_tone_row))
    main_list += random_tone_row

numbered_list = [s + str(random.randint(0, 8)) for s in main_list]

print(numbered_list)

compo = pretty_midi.PrettyMIDI()

compo_program = pretty_midi.instrument_name_to_program('Cello')

compo_c = pretty_midi.Instrument(program=compo_program)

start = 0
end = .5

for note_name in numbered_list:
    note_number = pretty_midi.note_name_to_number(note_name)
    note = pretty_midi.Note(velocity=random.randint(0, 100),
                            pitch=note_number,
                            start=start,
                            end=end)
    compo_c.notes.append(note)
    start = random.randint(0, 1000) * 0.1
    end = random.randint(1, 20) * 0.1

compo.instruments.append(compo_c)
Example #10
0
def mainFunction():
    tempo = randint(80, 160)
    beatLength = 60 / tempo
    print("Tempo: " + str(tempo) + " BPM")

    # randomly chooses key and scale
    scaleType = generateScale.scales[randrange(len(generateScale.scales))]
    keyChoice = generateScale.notes[randrange(len(generateScale.notes))]
    print("Key: " + keyChoice + " " + scaleType + "\n")

    # determines notes based on key and scale
    if scaleType == "Minor":
        scaleNotes = generateScale.minorScale(keyChoice)
    elif scaleType == "Major":
        scaleNotes = generateScale.majorScale(keyChoice)

    # creates the pretty_midi object
    pianoChords = pretty_midi.PrettyMIDI(initial_tempo=tempo)

    # sets the name based on MIDI standards
    piano_program = pretty_midi.instrument_name_to_program(
        "Acoustic Grand Piano")
    piano = pretty_midi.Instrument(program=piano_program)

    startTime = 0
    previousNoteNumber = 0

    chordProgressionRoots = []
    for x in range(1, 5):
        chordProgressionRoots.append(scaleNotes[randrange(1, 7)])
    chordDict = chordMaker.buildChord(chordProgressionRoots, scaleNotes)

    startTime = 0
    for key, value in chordDict.items():
        for note_name in value:
            nameWithoutOct = note_name
            lowestOctave = randint(3, 4)
            for x in range(lowestOctave,
                           6):  # plays the notes in multiple octaves
                note_name = nameWithoutOct + str(x)
                note_number = pretty_midi.note_name_to_number(note_name)
                note = pretty_midi.note_name_to_number(note_name)
                velocity = randint(105, 127)
                delay = round(
                    uniform(0, 0.05), 3
                )  # generates a random amount of delay to make it sound more natural/realistic
                note = pretty_midi.Note(velocity=velocity,
                                        pitch=note_number,
                                        start=(startTime + delay),
                                        end=startTime + (4 * beatLength))
                piano.notes.append(note)
        startTime += 4 * beatLength  # each chord plays for 4 beats, which is equal to 1 measure since it's in 4/4

    pianoChords.instruments.append(piano)
    pianoChords.write("chords.mid")

    # creates the pretty_midi object
    pianoMelody = pretty_midi.PrettyMIDI(initial_tempo=tempo)

    # sets the name based on MIDI standards
    piano_program = pretty_midi.instrument_name_to_program(
        "Acoustic Grand Piano")
    piano = pretty_midi.Instrument(program=piano_program)

    for x in range(0, 4):
        startTime = beatLength / 2 + (beatLength * x * 4
                                      )  # makes it start at the next measure
        # ensures that it doesn't play after the new chord starts until supposed to:
        while startTime < (beatLength * 4 * (x + 1)):
            noteIndex = randrange(len(scaleNotes))
            note_name = scaleNotes[noteIndex] + "5"
            note_number = pretty_midi.note_name_to_number(note_name)
            note = pretty_midi.note_name_to_number(note_name)
            velocity = randint(105, 127)
            delay = round(
                uniform(0, 0.05), 3
            )  # generates a random amount of delay to make it sound more natural/realistic
            length = (beatLength / 2) * (randint(1, 4))
            note = pretty_midi.Note(velocity=velocity,
                                    pitch=note_number,
                                    start=(startTime + delay),
                                    end=(startTime + length))
            piano.notes.append(note)
            startTime += length

    pianoMelody.instruments.append(piano)
    pianoMelody.write("melody.mid")

    # synthesizes the MIDI using the soundfont
    system("fluidsynth -ni %s chords.mid -F chords.wav -r 44100 2>/dev/null" %
           chordSfDir)
    system("fluidsynth -ni %s melody.mid -F melody.wav -r 44100 2>/dev/null" %
           melodySfDir)
    chords = AudioSegment.from_wav("chords.wav")
    melody = AudioSegment.from_wav("melody.wav")
    mixed = chords.overlay(melody)
    return mixed
def arpeggiate_instrument(instrument, arpeggio_time):
    '''
    Arpeggiate the notes of an instrument.

    Parameters
    ----------
    inst : pretty_midi.Instrument
        Instrument object.
    arpeggio_time : float
        Time, in seconds, of each note in the arpeggio

    Returns
    -------
    inst_arpeggiated : pretty_midi.Instrument
        Instrument with the notes arpeggiated.
    '''
    # Make a copy of the instrument
    inst_arpeggiated = pretty_midi.Instrument(program=instrument.program,
                                              is_drum=instrument.is_drum)
    for bend in instrument.pitch_bends:
        inst_arpeggiated.pitch_bends.append(bend)
    n = 0
    while n < len(instrument.notes):
        # Collect notes which are in this chord
        chord_notes = [(instrument.notes[n].pitch,
                        instrument.notes[n].velocity)]
        m = n + 1
        while m < len(instrument.notes):
            # It's in the chord if it starts before the current note ends
            if instrument.notes[m].start < instrument.notes[n].end:
                # Add in the pitch and velocity
                chord_notes.append(
                    (instrument.notes[m].pitch, instrument.notes[m].velocity))
                # Move the start time of the note up so it gets used next time
                if instrument.notes[m].end > instrument.notes[n].end:
                    instrument.notes[m].start = instrument.notes[n].end
            m += 1
        # Arpeggiate the collected notes
        time = instrument.notes[n].start
        pitch_index = 0
        if len(chord_notes) > 2:
            while time < instrument.notes[n].end:
                # Get the pitch and velocity of this note, but mod the index
                # to circulate
                pitch, velocity = chord_notes[pitch_index % len(chord_notes)]
                # Add this note to the new instrument
                inst_arpeggiated.notes.append(
                    pretty_midi.Note(velocity, pitch, time,
                                     time + arpeggio_time))
                # Next pitch next time
                pitch_index += 1
                # Move forward by the supplied amount
                time += arpeggio_time
        else:
            inst_arpeggiated.notes.append(instrument.notes[n])
            time = instrument.notes[n].end
        n += 1
        # Find the next chord
        while (n < len(instrument.notes)
               and instrument.notes[n].start + arpeggio_time <= time):
            n += 1
    return inst_arpeggiated
Example #12
0
def swap():
    print(request.form)

    chord = json.loads(request.form['chd'])
    midi_in = request.form['midi_in']
    chord_in = request.form['chd_in']
    for c in chord:
        c[0] = int(c[0])
        c[2] = int(c[2])
        for i in range(len(c[1])):
            c[1][i] = (int(c[1][i]) + c[0]) % 12
    chord = simpleChd_to_chd(chord)
    chd_mat_swapped = chord.tolist()
    chord_out = chd_to_str(chord)
    chord_in = chord_in[1:-1].replace("'", '').split(',')
    data = np.load('static/' + midi_in[:-3] + 'npz')
    pr_mat = data['pr_mat']
    c_out = data['chord']
    pr_mat = torch.from_numpy(pr_mat).float().to(device)
    chord = torch.from_numpy(chord).float().unsqueeze(0).to(device)
    c = torch.from_numpy(c_out).float().unsqueeze(0).to(device)
    print(pr_mat.shape, c.shape)
    for i in range(SAMPLE_LEN // 8):
        pr_mat_i = pr_mat[:, 32 * i:32 * i + 32, :]
        c_i = c[:, 8 * i:8 * i + 8, :]
        chord_i = chord[:, 8 * i:8 * i + 8, :]
        try:
            ptree_out_i = model.swap(pr_mat_i,
                                     pr_mat_i,
                                     c_i,
                                     chord_i,
                                     fix_rhy=True,
                                     fix_chd=False)
            pr_out_i, notes_out_i = model.decoder.grid_to_pr_and_notes(
                ptree_out_i.squeeze(0))
            pr_out = np.concatenate((pr_out, pr_out_i), axis=0)
            for note in notes_out_i:
                notes_out.append(
                    pretty_midi.Note(note.velocity, note.pitch,
                                     note.start + 8 * i,
                                     min([note.end + 8 * i, SAMPLE_LEN])))
        except:
            ptree_out_i = model.swap(pr_mat_i,
                                     pr_mat_i,
                                     c_i,
                                     chord_i,
                                     fix_rhy=True,
                                     fix_chd=False)
            pr_out, notes_out = model.decoder.grid_to_pr_and_notes(
                ptree_out_i.squeeze(0))

    for i in range(SAMPLE_LEN):
        notes_out.append(pretty_midi.Note(1, 30, i, i + 1))
    out_midi = pretty_midi.PrettyMIDI()
    out_midi.instruments = [pretty_midi.Instrument(0)]
    out_midi.instruments[0].notes = notes_out
    midi_out = 'static/' + midi_in[:-4] + str(
        datetime.datetime.today()).replace("-", "").replace(" ", "").replace(
            ":", "").replace(".", "") + ".mid"

    out_midi.write(midi_out)
    return {"midi_out": midi_out, "chd_mat_swapped": chd_mat_swapped}
Example #13
0
def output_midi_file_from_note_list(
    note_list,
    output_file_path,
    note_numerizer,
    sampling_frequency=common_config.SAMPLING_FREQUENCY_OUTPUT,
    start_idx=common_config.SLIDING_WINDOW_SIZE -
    2,  # start from the last note of the seed
    n_note_generate=common_config.N_NOTE_GENERATE):
    note_string_list = [
        note_numerizer.note_string_by_number[num] for num in note_list
    ]
    # 0 at the start + last note of the seed + n_note_generate generated notes
    piano_roll = np.zeros((128, n_note_generate + 2), dtype=np.int8)

    # create the piano roll
    print('Create the piano roll')
    for time_idx, note_string in enumerate(note_string_list[start_idx:]):
        if note_string == common_config.SILENT_CHAR:
            continue

        splitted_note = note_string.split(',')
        for i in splitted_note:
            piano_roll[int(i)][time_idx] = 1

    # create pretty_midi object from piano roll
    n_notes, n_time_frames = piano_roll.shape
    pretty_midi_obj = pretty_midi.PrettyMIDI()
    # channel 0 for piano
    instrument = pretty_midi.Instrument(program=0)

    piano_roll = np.pad(piano_roll, [(0, 0), (1, 1)], 'constant')
    velocity_changes = np.nonzero(np.diff(piano_roll).T)

    # keep track of velocity and note start time
    velocity_by_note = np.zeros(n_notes, dtype=int)
    start_time_by_note = np.zeros(n_notes)

    print('Finalizing MIDI data')
    for time, note in zip(*velocity_changes):
        # use time + 1 because we did some padding above
        velocity = piano_roll[note][time + 1]
        time = time / sampling_frequency
        if velocity > 0:
            if velocity_by_note[note] == 0:
                start_time_by_note[note] = time
                velocity_by_note[note] = velocity
        else:
            prerry_midi_note = pretty_midi.Note(
                velocity=velocity_by_note[note],
                pitch=note,
                start=start_time_by_note[note],
                end=time)
            instrument.notes.append(prerry_midi_note)
            velocity_by_note[note] = 0
    pretty_midi_obj.instruments.append(instrument)

    for note in pretty_midi_obj.instruments[0].notes:
        #-should be ~ forte
        note.velocity = 100

    # write to file
    print('Writing to file')
    pretty_midi_obj.write(output_file_path)
Example #14
0
def convertMethodBDataToMidi(data, tokens, model_name, timestep_resolution):
    print("Converting raw notes to MIDI")
    mid = pretty_midi.PrettyMIDI()
    inst = pretty_midi.Instrument(0)
    timestepCounter = 0
    # what notes are currently being played
    current_notes = {}
    # unnormalize the data at each step
    for d in data:
        for timestep in d:
            # for all notes in this timestep
            rounded_timestep = [round(x) for x in timestep]
            for msg in rounded_timestep:
                # if we encounter a new note start counting its duration
                if msg not in current_notes:
                    current_notes[msg] = []
                    current_notes[msg].append(timestepCounter)
                    current_notes[msg].append(1)
                else:
                    current_notes[msg][1] = current_notes[msg][1] + 1
            # if any of the currently playing notes are not
            # being played at this timestep, remove it from current notes7
            notesToRemove = []
            for note, timing in current_notes.items():
                if note not in rounded_timestep:
                    # print("Logic is sound, this is being called :) ")
                    currentToken = abs(int(note))
                    if note >= 1:
                        pitch, velocity = tokens[currentToken]
                        if pitch > 127:
                            pitch = np.uint8(127)
                        if velocity > 127:
                            velocity = np.uint8(127)
                        start = timing[0] / timestep_resolution
                        duration = timing[1] / timestep_resolution
                        # print("Note start time = %d, note duration = %d" % (start, duration))
                        new_note = pretty_midi.Note(velocity, pitch, start,
                                                    start + duration)
                        inst.notes.append(new_note)
                        notesToRemove.append(note)

            for note in notesToRemove:
                current_notes.pop(note)

            timestepCounter += 1

    if bool(current_notes) == True:
        for note, timing in current_notes.items():
            currentToken = abs(int(note))
            if currentToken != 0:
                pitch, velocity = tokens[currentToken]
                if pitch > 127:
                    pitch = np.uint8(127)
                if velocity > 127:
                    velocity = np.uint8(127)
                start = timing[0] / timestep_resolution
                duration = timing[1] / timestep_resolution
                # print("Note start time = %d, note duration = %d" % (start, duration))
                new_note = pretty_midi.Note(velocity, pitch, start,
                                            start + duration)
                inst.notes.append(new_note)

    del current_notes
    print("total number of notes = %d" % len(inst.notes))
    mid.instruments.append(inst)
    cleanMidiB(mid)
    mid.write(getMidiRunName(model_name))
def create_midi_from_piece(
        piece: Piece,
        midi_path: str,
        measure_in_seconds: float,
        instruments: List[int],
        velocity: int,
        opening_silence_in_seconds: int = 1,
        trailing_silence_in_seconds: int = 1
) -> None:
    """
    Create MIDI file from a piece created by this package.

    :param piece:
        musical piece
    :param midi_path:
        path where resulting MIDI file is going to be saved
    :param measure_in_seconds:
        duration of one measure in seconds
    :param instruments:
        IDs of instruments (according to General MIDI specification)
        that play corresponding melodic lines
    :param velocity:
        one common velocity for all notes
    :param opening_silence_in_seconds:
        number of seconds with silence to add at the start of the composition
    :param trailing_silence_in_seconds:
        number of seconds with silence to add at the end of the composition
    :return:
        None
    """
    numeration_shift = pretty_midi.note_name_to_number('A0')
    pretty_midi_instruments = []
    for melodic_line, instrument in zip(piece.melodic_lines, instruments):
        pretty_midi_instrument = pretty_midi.Instrument(program=instrument)
        for element in melodic_line:
            start_time = element.start_time * measure_in_seconds
            start_time += opening_silence_in_seconds
            end_time = start_time + element.duration * measure_in_seconds
            pitch = element.position_in_semitones + numeration_shift
            note = pretty_midi.Note(
                start=start_time,
                end=end_time,
                pitch=pitch,
                velocity=velocity
            )
            pretty_midi_instrument.notes.append(note)
        pretty_midi_instrument.notes.sort(key=lambda x: (x.start, x.pitch))
        pretty_midi_instruments.append(pretty_midi_instrument)

    trailing_silence_start = piece.n_measures * measure_in_seconds
    trailing_silence_start += opening_silence_in_seconds
    note = pretty_midi.Note(
        velocity=0,
        pitch=1,  # Arbitrary value that affects nothing.
        start=trailing_silence_start,
        end=trailing_silence_start + trailing_silence_in_seconds
    )
    pretty_midi_instruments[0].notes.append(note)

    composition = pretty_midi.PrettyMIDI()
    for pretty_midi_instrument in pretty_midi_instruments:
        composition.instruments.append(pretty_midi_instrument)
    composition.write(midi_path)
Example #16
0
import pretty_midi
# Create a PrettyMIDI object
cello_c_chord = pretty_midi.PrettyMIDI()
# Create an Instrument instance for a cello instrument
cello_program = pretty_midi.instrument_name_to_program('Cello')
cello = pretty_midi.Instrument(program=cello_program)
# Iterate over note names, which will be converted to note number later
for note_name in ['C5', 'E5', 'G5']:
    # Retrieve the MIDI note number for this note name
    note_number = pretty_midi.note_name_to_number(note_name)
    # Create a Note instance, starting at 0s and ending at .5s
    note = pretty_midi.Note(velocity=100, pitch=note_number, start=0, end=.5)
    # Add it to our cello instrument
    cello.notes.append(note)
# Add the cello instrument to the PrettyMIDI object
cello_c_chord.instruments.append(cello)
# Write out the MIDI data
print(cello.notes)
cello_c_chord.write('cello-C-chord.mid')
Example #17
0
import os
import sys
import math
import shutil
import pretty_midi
import numpy as np
import pandas as pd
from tqdm import tqdm
# Making a file using pretty_midi instead of MIDO for easier npy file generation
pretty_mid = pretty_midi.PrettyMIDI()
piano = pretty_midi.Instrument(program=1)
note = pretty_midi.Note(velocity=64, pitch=60, start=0.0, end=1.0)
piano.notes.append(note)
note = pretty_midi.Note(velocity=65, pitch=65, start=1.0, end=2.0)
piano.notes.append(note)
note = pretty_midi.Note(velocity=66, pitch=66, start=2.0, end=2.2)
piano.notes.append(note)
note = pretty_midi.Note(velocity=69, pitch=69, start=2.0, end=2.5)
piano.notes.append(note)
pretty_mid.instruments.append(piano)
savedir = '/Users/sorensabet/Desktop/MSC/CSC2506_Project/data/Generated MIDI'
pretty_mid.write(savedir + '/' + 'PRETTYMIDI_TEST.mid')
print('Generated pretty_midi file!')

Example #18
0
def emit_nesmdb_midi_examples(
    midi_fp,
    output_dir,
    min_num_instruments=1,
    filter_mid_len_below_seconds=5.,
    filter_mid_len_above_seconds=600.,
    filter_mid_bad_times=True,
    filter_ins_max_below=21,
    filter_ins_min_above=108,
    filter_ins_duplicate=True,
    output_include_drums=True,
    output_max_num=16,
    output_max_num_seconds=180.):
  midi_name = os.path.split(midi_fp)[1].split('.')[0]

  if min_num_instruments <= 0:
    raise ValueError()

  # Ignore unusually large MIDI files (only ~25 of these in the dataset)
  if os.path.getsize(midi_fp) > (512 * 1024): #512K
    return

  try:
    midi = pretty_midi.PrettyMIDI(midi_fp)
  except:
    return

  # Filter MIDIs with extreme length
  midi_len = midi.get_end_time()
  if midi_len < filter_mid_len_below_seconds or midi_len > filter_mid_len_above_seconds:
    return

  # Filter out negative times and quantize to audio samples
  for ins in midi.instruments:
    for n in ins.notes:
      if filter_mid_bad_times:
        if n.start < 0 or n.end < 0 or n.end < n.start:
          return
      n.start = round(n.start * 44100.) / 44100.
      n.end = round(n.end * 44100.) / 44100.

  instruments = midi.instruments

  # Filter out drum instruments
  drums = [i for i in instruments if i.is_drum]
  instruments = [i for i in instruments if not i.is_drum]

  # Filter out instruments with bizarre ranges
  instruments_normal_range = []
  for ins in instruments:
    pitches = [n.pitch for n in ins.notes]
    min_pitch = min(pitches)
    max_pitch = max(pitches)
    if max_pitch >= filter_ins_max_below and min_pitch <= filter_ins_min_above:
      instruments_normal_range.append(ins)
  instruments = instruments_normal_range
  if len(instruments) < min_num_instruments:
    return

  # Sort notes for polyphonic filtering and proper saving
  for ins in instruments:
    ins.notes = sorted(ins.notes, key=lambda x: x.start)
  if output_include_drums:
    for ins in drums:
      ins.notes = sorted(ins.notes, key=lambda x: x.start)

  # Filter out polyphonic instruments
  instruments = [i for i in instruments if instrument_is_monophonic(i)]
  if len(instruments) < min_num_instruments:
    return

  # Filter out duplicate instruments
  if filter_ins_duplicate:
    uniques = set()
    instruments_unique = []
    for ins in instruments:
      pitches = ','.join(['{}:{:.1f}'.format(str(n.pitch), n.start) for n in ins.notes])
      if pitches not in uniques:
        instruments_unique.append(ins)
        uniques.add(pitches)
    instruments = instruments_unique
    if len(instruments) < min_num_instruments:
      return

  # TODO: Find instruments that have a substantial fraction of the number of total notes
  """
  min_notes_frac = num_instruments_to_min_notes_frac(num_instruments)
  total_num_notes = sum([len(i.notes) for i in instruments])
  instruments = [i for i in instruments if (len(i.notes) / float(total_num_notes)) >= min_notes_frac]
  num_instruments = len(instruments)
  if num_instruments < min_num_instruments:
    return
  """

  # TODO: ensure tempo and other metadata is alright

  # TODO: ensure number of notes is alright

  # Create assignments of MIDI instruments to NES instruments
  num_instruments = len(instruments)
  if num_instruments == 1:
    instrument_perms = [(0, -1, -1), (-1, 0, -1), (-1, -1, 0)]
  elif num_instruments == 2:
    instrument_perms = [(-1, 0, 1), (-1, 1, 0), (0, -1, 1), (0, 1, -1), (1, -1, 0), (1, 0, -1)]
  elif num_instruments > 32:
    instrument_perms = list(itertools.permutations(random.sample(range(num_instruments), 32), 3))
  else:
    instrument_perms = list(itertools.permutations(range(num_instruments), 3))

  if len(instrument_perms) > output_max_num:
    instrument_perms = random.sample(instrument_perms, output_max_num)

  num_drums = len(drums) if output_include_drums else 0
  instrument_perms_plus_drums = []
  for perm in instrument_perms:
    selection = -1 if num_drums == 0 else random.choice(range(num_drums))
    instrument_perms_plus_drums.append(perm + (selection,))
  instrument_perms = instrument_perms_plus_drums

  # Emit midi files
  for i, perm in enumerate(instrument_perms):
    # Create MIDI instruments
    p1_prog = pretty_midi.instrument_name_to_program('Lead 1 (square)')
    p2_prog = pretty_midi.instrument_name_to_program('Lead 2 (sawtooth)')
    tr_prog = pretty_midi.instrument_name_to_program('Synth Bass 1')
    no_prog = pretty_midi.instrument_name_to_program('Breath Noise')
    p1 = pretty_midi.Instrument(program=p1_prog, name='p1', is_drum=False)
    p2 = pretty_midi.Instrument(program=p2_prog, name='p2', is_drum=False)
    tr = pretty_midi.Instrument(program=tr_prog, name='tr', is_drum=False)
    no = pretty_midi.Instrument(program=no_prog, name='no', is_drum=True)

    # Filter out invalid notes
    perm_mid_ins_notes = []
    for mid_ins_id, nes_ins_name in zip(perm, ['p1', 'p2', 'tr', 'no']):
      if mid_ins_id < 0:
        perm_mid_ins_notes.append(None)
      else:
        if nes_ins_name == 'no':
          mid_ins = drums[mid_ins_id]
          mid_ins_notes_valid = mid_ins.notes
        else:
          mid_ins = instruments[mid_ins_id]
          mid_ins_notes_valid = [n for n in mid_ins.notes if n.pitch >= nes_ins_name_to_min_pitch[nes_ins_name] and n.pitch <= nes_ins_name_to_max_pitch[nes_ins_name]]
        perm_mid_ins_notes.append(mid_ins_notes_valid)
    assert len(perm_mid_ins_notes) == 4

    # Calculate length of this ensemble
    start = None
    end = None
    for notes in perm_mid_ins_notes:
      if notes is None or len(notes) == 0:
        continue
      ins_start = min([n.start for n in notes])
      ins_end = max([n.end for n in notes])
      if start is None or ins_start < start:
        start = ins_start
      if end is None or ins_end > end:
        end = ins_end
    if start is None or end is None:
      continue

    # Clip if needed
    if (end - start) > output_max_num_seconds:
      end = start + output_max_num_seconds

    # Create notes
    for mid_ins_notes, nes_ins_name, nes_ins in zip(perm_mid_ins_notes, ['p1', 'p2', 'tr', 'no'], [p1, p2, tr, no]):
      if mid_ins_notes is None:
        continue

      if nes_ins_name == 'no':
        random_noise_mapping = [random.randint(1, 16) for _ in range(128)]

      last_nend = -1
      for ni, n in enumerate(mid_ins_notes):
        nvelocity = n.velocity
        npitch = n.pitch
        nstart = n.start
        nend = n.end

        # Drums are not necessarily monophonic so we need to filter
        if nes_ins_name == 'no' and nstart < last_nend:
          continue
        last_nend = nend

        assert nstart >= start
        if nend > end:
          continue
        assert nend <= end

        nvelocity = 1 if nes_ins_name == 'tr' else int(round(1. + (14. * nvelocity / 127.)))
        assert nvelocity > 0
        if nes_ins_name == 'no':
          npitch = random_noise_mapping[npitch]
        nstart = nstart - start
        nend = nend - start

        nes_ins.notes.append(pretty_midi.Note(nvelocity, npitch, nstart, nend))

    # Add instruments to MIDI file
    midi = pretty_midi.PrettyMIDI(initial_tempo=120, resolution=22050)
    midi.instruments.extend([p1, p2, tr, no])

    # Create indicator for end of song
    eos = pretty_midi.TimeSignature(1, 1, end - start)
    midi.time_signature_changes.append(eos)

    # Save MIDI file
    out_fp = '{}_{}.mid'.format(midi_name, str(i).zfill(3))
    out_fp = os.path.join(output_dir, out_fp)
    midi.write(out_fp)
Example #19
0
def infer_midi(interval, agg_f0, t_unit=0.02):
    """Inference the given interval and aggregated F0 to MIDI file.

    Parameters
    ----------
    interval: list[tuple[float, float]]
        The return value of ``infer_interval`` function. List of onset/offset pairs in seconds.
    agg_f0: list[dict]
        Aggregated f0 information. Each elements in the list should contain three columns:
        *start_time*, *end_time*, and *frequency*. Time units should be in seonds, and pitch
        should be Hz.
    t_unit: float
        Time unit of each frame.

    Returns
    -------
    midi: pretty_midi.PrettyMIDI
        The inferred MIDI object.
    """
    fs = round(1 / t_unit)
    max_secs = max(record["end_time"] for record in agg_f0)
    total_frames = round(max_secs) * fs + 10
    flat_f0 = np.zeros(total_frames)
    for record in agg_f0:
        start_idx = int(round(record["start_time"] * fs))
        end_idx = int(round(record["end_time"] * fs))
        flat_f0[start_idx:end_idx] = record["frequency"]

    notes = []
    drum_notes = []
    skip_num = 0
    for onset, offset in interval:
        start_idx = int(round(onset * fs))
        end_idx = int(round(offset * fs))
        freqs = flat_f0[start_idx:end_idx]
        avg_hz = _conclude_freq(freqs)
        if avg_hz < 1e-6:
            skip_num += 1
            note = pretty_midi.Note(velocity=80,
                                    pitch=77,
                                    start=onset,
                                    end=offset)
            drum_notes.append(note)
            continue

        note_num = int(round(pretty_midi.hz_to_note_number(avg_hz)))
        if not (0 <= note_num <= 127):
            logger.warning(
                "Caught invalid note number: %d (should be in range 0~127). Skipping.",
                note_num)
            skip_num += 1
            continue
        note = pretty_midi.Note(velocity=80,
                                pitch=note_num,
                                start=onset,
                                end=offset)
        notes.append(note)

    if skip_num > 0:
        logger.warning(
            "A total of %d notes are skipped due to lack of corressponding pitch information.",
            skip_num)

    inst = pretty_midi.Instrument(program=0)
    inst.notes += notes
    drum_inst = pretty_midi.Instrument(program=1,
                                       is_drum=True,
                                       name="Missing Notes")
    drum_inst.notes += drum_notes
    midi = pretty_midi.PrettyMIDI()
    midi.instruments.append(inst)
    midi.instruments.append(drum_inst)
    return midi
def _get_chroma(notes, sampling_rate):
    midi = pretty_midi.Instrument(0)
    midi.notes[:] = notes
    return midi.get_chroma(fs=sampling_rate)
Example #21
0
def interpolation(args,
                  model,
                  dataset,
                  x_a=None,
                  x_b=None,
                  output='output/',
                  fs=25,
                  program=0):
    if (x_a is None):
        x_a, x_b = dataset[random.randint(
            0,
            len(dataset) - 1)], dataset[random.randint(0,
                                                       len(dataset) - 1)]
        x_a, x_b = x_a.to(args.device), x_b.to(args.device)
    # Encode samples to the latent space
    z_a, z_b = model.encode(x_a.unsqueeze(0)), model.encode(x_b.unsqueeze(0))
    # Run through alpha values
    interp = []
    alpha_values = np.linspace(0, 1, args.n_steps)
    for alpha in alpha_values:
        z_interp = (1 - alpha) * z_a[0] + alpha * z_b[0]
        interp.append(model.decode(z_interp))
    # Draw interpolation step by step
    i = 0
    stack_interp = []
    for step in interp:
        if args.num_classes > 1:
            step = torch.argmax(step[0], dim=0)
        stack_interp.append(step)
        # plt.matshow(step.cpu().detach(), alpha=1)
        # plt.title("Interpolation " + str(i))
        # plt.savefig(args.figures_path + "interpolation" + str(i) + ".png")
        # plt.close()
        i += 1
    stack_interp = torch.cat(stack_interp, dim=1)
    # Draw stacked interpolation
    plt.figure()
    plt.matshow(stack_interp.cpu(), alpha=1)
    plt.title("Interpolation")
    plt.savefig(output + "_interpolation.png")
    plt.close()
    # Generate MIDI from interpolation
    pm = pretty_midi.PrettyMIDI()
    notes, frames = stack_interp.shape
    instrument = pretty_midi.Instrument(program=program)
    # Pad 1 column of zeros to acknowledge initial and ending events
    piano_roll = np.pad(stack_interp.cpu().detach(), [(0, 0), (1, 1)],
                        'constant')
    # Use changes in velocities to find note on/note off events
    velocity_changes = np.nonzero(np.diff(piano_roll).T)
    # Keep track on velocities and note on times
    prev_velocities = np.zeros(notes, dtype=int)
    note_on_time = np.zeros(notes)
    # Do prettier representation
    fig = plt.figure(figsize=(18, 4), dpi=80)
    ax = plt.subplot(1, 1, 1)
    min_pitch = np.inf
    max_pitch = 0
    cmap = plt.get_cmap('inferno', args.n_steps + 3)
    for time, note in zip(*velocity_changes):
        # Use time + 1s because of padding above
        velocity = piano_roll[note, time + 1]
        time = time / fs
        if velocity > 0:
            if prev_velocities[note] == 0:
                note_on_time[note] = time
                prev_velocities[note] = 75
        else:
            pm_note = pretty_midi.Note(velocity=prev_velocities[note],
                                       pitch=note + args.min_pitch,
                                       start=note_on_time[note],
                                       end=time)
            instrument.notes.append(pm_note)
            prev_velocities[note] = 0
            rect = patches.Rectangle(
                (note_on_time[note] * fs, note + args.min_pitch - 0.5),
                (time - note_on_time[note]) * fs,
                1,
                linewidth=1.5,
                edgecolor='k',
                facecolor=cmap(int(note_on_time[note] * fs / 64)),
                alpha=0.8)
            min_pitch = min(min_pitch, note + args.min_pitch)
            max_pitch = max(max_pitch, note + args.min_pitch)
            ax.add_patch(rect)
    ax.set_ylim([min_pitch - 5, max_pitch + 5])
    ax.set_xticks(np.arange(64, 64 * args.n_steps, 64))
    ax.set_xticklabels(np.arange(1, args.n_steps, 1))
    ax.set_xlim([0, time * fs])
    ax.set_xlabel('Interpolated measures')
    ax.set_ylabel('Pitch')
    ax.grid()
    plt.tight_layout()
    plt.savefig(output + "_interpolation.pdf")
    pm.instruments.append(instrument)
    # Write out the MIDI data
    pm.write(output + "_interpolation.mid")
Example #22
0
  def run(self):
    sequence = music_pb2.NoteSequence()
    player = self._midi_hub.start_playback(sequence, allow_updates=True)
    player._channel = self._midi_channel

    pretty_midi = pm.PrettyMIDI()
    pretty_midi.instruments.append(pm.Instrument(0))

    # Wait for the dreamer and store the time with the delta
    wall_start_time = time.time()
    self._bar_start_event.wait()

    bar_count = 0
    while not self._stop_signal:
      # Number of seconds we should be at the beginning of this loop
      expected_start_time = self._timing.get_expected_start_time(bar_count)
      # Number of actual seconds since we started this thread from wall clock,
      # which is smaller then the expected start time
      # The difference is between: the actual wakeup time and the expected
      # (calculated) start time. By keeping this we can adjust the sequence
      # according to the drift.
      diff_time = self._timing.get_diff_time(wall_start_time, bar_count)

      tf.logging.debug("Playing " + str(self._timing.get_timing_args(
        wall_start_time, bar_count)))

      # Player
      sequence_adjusted = music_pb2.NoteSequence()
      sequence_adjusted.CopyFrom(sequence)
      sequence_adjusted = adjust_sequence_times(sequence_adjusted,
                                                wall_start_time - diff_time)
      player.update_sequence(sequence_adjusted, start_time=expected_start_time)

      # Plotter
      pretty_midi = mm.midi_io.note_sequence_to_pretty_midi(sequence)
      self._plotter.save(pretty_midi, self._output_plot)
      pretty_midi.write(self._output_midi)

      # Sets timing
      seconds_per_bar = self._timing.get_seconds_per_bar()
      seconds_per_loop = self._bar_per_loop * seconds_per_bar
      loop_start_time = expected_start_time
      loop_end_time = loop_start_time + seconds_per_loop
      generation_start_time = loop_end_time
      generation_end_time = generation_start_time + seconds_per_loop

      action = self._action_server.context.get(self.name, None)

      tf.logging.debug(str(action) + " " + str([
        ("expected_start_time", expected_start_time),
        ("loop_start_time", loop_start_time),
        ("loop_end_time", loop_end_time),
        ("generation_start_time", generation_start_time),
        ("generation_end_time", generation_end_time)]))

      if not action:
        pass
      elif action is ActionType.LOOP:
        sequence = sequences.loop(sequence,
                                  loop_start_time,
                                  loop_end_time,
                                  seconds_per_loop)
      elif action is ActionType.GENERATE:
        sequence = sequences.generate(sequence,
                                      self.name,
                                      self._bundle_filename,
                                      self._config_name,
                                      generation_start_time,
                                      generation_end_time)
      elif action is ActionType.GENERATE_ONCE:
        sequence = sequences.generate(sequence,
                                      self.name,
                                      self._bundle_filename,
                                      self._config_name,
                                      generation_start_time,
                                      generation_end_time)
        self._action_server.context[self.name] = ActionType.LOOP
      elif action is ActionType.RESET_ONCE:
        sequence = sequences.reset(sequence,
                                   loop_start_time,
                                   loop_end_time,
                                   seconds_per_loop)
        self._action_server.context[self.name] = ActionType.LOOP
      elif action is ActionType.RESET_GENERATE:
        sequence = sequences.reset(sequence,
                                   loop_start_time,
                                   loop_end_time,
                                   seconds_per_loop)
        self._action_server.context[self.name] = ActionType.GENERATE_ONCE
      else:
        raise Exception(f"Unknown action {action}")

      while True:
        # Unlock at the start of the bar
        self._bar_start_event.wait()
        bar_count += 1
        if bar_count % self._bar_per_loop == 0:
          break
Example #23
0
import pretty_midi

extracted_drum = pretty_midi.PrettyMIDI()
generated_drum = pretty_midi.Instrument(program=1)
generated_drum.is_drum = False

for i in range(10):
    new_note = pretty_midi.Note(velocity=110,
                                pitch=35,
                                start=i * 2,
                                end=i * 2 + .3)
    generated_drum.notes.append(new_note)
extracted_drum.instruments.append(generated_drum)
extracted_drum.write('pitch_test.mid')

# 25 ~ 85
Example #24
0
def write_MIDI(name, loop):
    GMKeymap = {
        "kick": [35, 36],
        "snare": [37, 38, 40],
        "closed hihat": [42, 44],
        "open hihat": [46],
        "low tom": [41, 43, 45]
    }

    #LSTM = load_model("JAKI_Encoder_Decoder_14-6-20_2")
    #oneHotGrooves = np.load("One-Hot-Drum-Loops.npy")
    #oneBarGrooves = oneHotGrooves[:,0:16,:]

    midiloop = pretty_midi.PrettyMIDI()

    #loop = convertOneHotToList(oneHotGrooves[2,:,:])

    drumkit_program = pretty_midi.instrument_name_to_program('Cello')
    drumkit = pretty_midi.Instrument(program=drumkit_program)

    time = 0.0
    for i in range(len(loop)):
        if 'k' in loop[i]:
            note = pretty_midi.Note(velocity=100,
                                    pitch=35,
                                    start=time,
                                    end=time + 0.125)
            drumkit.notes.append(note)
        if 'c' in loop[i]:
            note = pretty_midi.Note(velocity=100,
                                    pitch=42,
                                    start=time,
                                    end=time + 0.125)
            drumkit.notes.append(note)
        if 'o' in loop[i]:
            note = pretty_midi.Note(velocity=100,
                                    pitch=46,
                                    start=time,
                                    end=time + 0.125)
            drumkit.notes.append(note)
        if 't' in loop[i]:
            note = pretty_midi.Note(velocity=100,
                                    pitch=43,
                                    start=time,
                                    end=time + 0.125)
            drumkit.notes.append(note)
        if 's' in loop[i]:
            note = pretty_midi.Note(velocity=100,
                                    pitch=37,
                                    start=time,
                                    end=time + 0.125)
            drumkit.notes.append(note)
        try:
            drumkit.notes.append(note)
        except:
            pass
        time += 0.125  # semiquaver length at 120bpm

    midiloop.instruments.append(drumkit)

    midiloop.write(name)
Example #25
0
def note_sequence_to_pretty_midi(sequence,
                                 drop_events_n_seconds_after_last_note=None):
    """Convert NoteSequence to a PrettyMIDI.

  Time is stored in the NoteSequence in absolute values (seconds) as opposed to
  relative values (MIDI ticks). When the NoteSequence is translated back to
  PrettyMIDI the absolute time is retained. The tempo map is also recreated.

  Args:
    sequence: A NoteSequence.
    drop_events_n_seconds_after_last_note: Events (e.g., time signature changes)
        that occur this many seconds after the last note will be dropped. If
        None, then no events will be dropped.

  Returns:
    A pretty_midi.PrettyMIDI object or None if sequence could not be decoded.
  """
    ticks_per_quarter = sequence.ticks_per_quarter or constants.STANDARD_PPQ

    max_event_time = None
    if drop_events_n_seconds_after_last_note is not None:
        max_event_time = (max([n.end_time for n in sequence.notes] or [0]) +
                          drop_events_n_seconds_after_last_note)

    # Try to find a tempo at time zero. The list is not guaranteed to be in order.
    initial_seq_tempo = None
    for seq_tempo in sequence.tempos:
        if seq_tempo.time == 0:
            initial_seq_tempo = seq_tempo
            break

    kwargs = {}
    if initial_seq_tempo:
        kwargs['initial_tempo'] = initial_seq_tempo.qpm
    else:
        kwargs['initial_tempo'] = constants.DEFAULT_QUARTERS_PER_MINUTE

    pm = pretty_midi.PrettyMIDI(resolution=ticks_per_quarter, **kwargs)

    # Create an empty instrument to contain time and key signatures.
    instrument = pretty_midi.Instrument(0)
    pm.instruments.append(instrument)

    # Populate time signatures.
    for seq_ts in sequence.time_signatures:
        if max_event_time and seq_ts.time > max_event_time:
            continue
        time_signature = pretty_midi.containers.TimeSignature(
            seq_ts.numerator, seq_ts.denominator, seq_ts.time)
        pm.time_signature_changes.append(time_signature)

    # Populate key signatures.
    for seq_key in sequence.key_signatures:
        if max_event_time and seq_key.time > max_event_time:
            continue
        key_number = seq_key.key
        if seq_key.mode == seq_key.MINOR:
            key_number += _PRETTY_MIDI_MAJOR_TO_MINOR_OFFSET
        key_signature = pretty_midi.containers.KeySignature(
            key_number, seq_key.time)
        pm.key_signature_changes.append(key_signature)

    # Populate tempos.
    # TODO(douglaseck): Update this code if pretty_midi adds the ability to
    # write tempo.
    for seq_tempo in sequence.tempos:
        # Skip if this tempo was added in the PrettyMIDI constructor.
        if seq_tempo == initial_seq_tempo:
            continue
        if max_event_time and seq_tempo.time > max_event_time:
            continue
        tick_scale = 60.0 / (pm.resolution * seq_tempo.qpm)
        tick = pm.time_to_tick(seq_tempo.time)
        # pylint: disable=protected-access
        pm._tick_scales.append((tick, tick_scale))
        pm._update_tick_to_time(0)
        # pylint: enable=protected-access

    # Populate instrument names by first creating an instrument map between
    # instrument index and name.
    # Then, going over this map in the instrument event for loop
    inst_infos = {}
    for inst_info in sequence.instrument_infos:
        inst_infos[inst_info.instrument] = inst_info.name

    # Populate instrument events by first gathering notes and other event types
    # in lists then write them sorted to the PrettyMidi object.
    instrument_events = collections.defaultdict(
        lambda: collections.defaultdict(list))
    for seq_note in sequence.notes:
        instrument_events[(seq_note.instrument, seq_note.program,
                           seq_note.is_drum)]['notes'].append(
                               pretty_midi.Note(seq_note.velocity,
                                                seq_note.pitch,
                                                seq_note.start_time,
                                                seq_note.end_time))
    for seq_bend in sequence.pitch_bends:
        if max_event_time and seq_bend.time > max_event_time:
            continue
        instrument_events[(seq_bend.instrument, seq_bend.program,
                           seq_bend.is_drum)]['bends'].append(
                               pretty_midi.PitchBend(seq_bend.bend,
                                                     seq_bend.time))
    for seq_cc in sequence.control_changes:
        if max_event_time and seq_cc.time > max_event_time:
            continue
        instrument_events[(seq_cc.instrument, seq_cc.program,
                           seq_cc.is_drum)]['controls'].append(
                               pretty_midi.ControlChange(
                                   seq_cc.control_number, seq_cc.control_value,
                                   seq_cc.time))
    for ta in sequence.text_annotations:
        from magenta.music.chords_lib import CHORD_SYMBOL
        if ta.annotation_type == CHORD_SYMBOL and ta.text != constants.NO_CHORD:
            pm.lyrics.append(pretty_midi.Lyric(ta.text, ta.time))
        # timing_track.append(mido.MetaMessage(
        #   'end_of_track', time=timing_track[-1].time + 1))

    for (instr_id, prog_id, is_drum) in sorted(instrument_events.keys()):
        # For instr_id 0 append to the instrument created above.
        if instr_id > 0:
            instrument = pretty_midi.Instrument(prog_id, is_drum)
            pm.instruments.append(instrument)
        else:
            instrument.is_drum = is_drum
        # propagate instrument name to the midi file
        instrument.program = prog_id
        if instr_id in inst_infos:
            instrument.name = inst_infos[instr_id]
        instrument.notes = instrument_events[(instr_id, prog_id,
                                              is_drum)]['notes']
        instrument.pitch_bends = instrument_events[(instr_id, prog_id,
                                                    is_drum)]['bends']
        instrument.control_changes = instrument_events[(instr_id, prog_id,
                                                        is_drum)]['controls']

    return pm
def fami_to_mid(input_txt_file, output_mid_file):
    """
    Returns the duration of the track
    """
    f = open(input_txt_file, 'r')
    d = f.read()
    f.close()
    d = d.replace('\t', '')
    channels = d.split('Channel Type')

    channels_list = []
    instances_list = []
    for i, channel in enumerate(channels):
        patterns = channel.split('Pattern Name')
        patterns_list = []
        instances = {}
        for j, pattern in enumerate(patterns):
            pattern_list = []
            notes = pattern.split('\n')
            for note in notes:
                if note.startswith('Note ') or note.startswith(
                        'PatternInstance '):
                    if note.startswith('Note '):
                        params_raw = note.split('Note ')[1] + '\n'
                    else:
                        params_raw = note.split('PatternInstance ')[1] + '\n'
                    open_value = False
                    temp = ''
                    params = []
                    for c in params_raw:
                        if c == '"':
                            if open_value:
                                open_value = False
                            else:
                                open_value = True
                        if c in [' ', '\n'] and not open_value:
                            params.append(temp)
                            temp = ''
                        else:
                            temp += c
                    if note.startswith('Note '):
                        notes_values = []
                        for param in params:
                            key, value = param.split('=')
                            value = value[1:-1]
                            notes_values.append((key, value))
                        pattern_list.append((pattern_name, notes_values))
                    else:
                        instance = {}
                        for param in params:
                            key, value = param.split('=')
                            value = value[1:-1]
                            instance[key] = value
                        instances[instance['Pattern']] = instance
                else:
                    if note.startswith('="Pattern '):
                        pattern_name = note[2:-1]
            patterns_list.append(pattern_list)
        channels_list.append(patterns_list)
        instances_list.append(instances)

    values_table = {
        'C': 0,
        'C#': 1,
        'D': 2,
        'D#': 3,
        'E': 4,
        'F': 5,
        'F#': 6,
        'G': 7,
        'G#': 8,
        'A': 9,
        'A#': 10,
        'B': 11
    }

    notes_times = []
    for c in channels_list:
        for p in c:
            for name, n in p:
                time = None
                for k, v in n:
                    if k == 'Time':
                        time = v
                    if k == 'Value':
                        notes_times.append(time)

    # Average Volumes
    notes_volumes = []
    current_volume = 11
    was_stop = True
    num_events = 0
    volume = 0
    for c in channels_list:
        for p in c:
            for name, n in p:
                # create dict from list of key values
                d = {}
                for k, v in n:
                    d[k] = v

                # end of note
                if 'Value' in d:
                    # TWO AGGREGATION METHODS:
                    prev_volume = None if was_stop else int(volume)
                    # prev_volume = None if was_stop else int(volume / num_events)

                    notes_volumes.append(prev_volume)
                    volume = 0
                    num_events = 0
                    if not d['Value'] == 'Stop':
                        was_stop = False

                # means it's not a Stop or other: aggregate
                if 'Volume' in d:
                    v = int(d['Volume'])
                    # TWO AGGREGATION METHODS:
                    volume = max(v, volume)
                    # volume += v
                    current_volume = v
                    num_events += 1
                else:

                    if ('Value' in d):
                        # if it's a true note, but without volume change or indication
                        if (not d['Value'] == 'Stop'):
                            # TWO AGGREGATION METHODS:
                            volume = max(current_volume, volume)
                            # volume += current_volume
                            num_events += 1
                            was_stop = False
                        else:
                            was_stop = True

    # Write midi

    # Constants:
    channel_index_to_prog = {1: 80, 2: 81, 3: 38, 4: 121}
    prog_to_instrument_name = {80: 'p1', 81: 'p2', 38: 'tr', 121: 'no'}
    # Midi
    midi = pretty_midi.PrettyMIDI(initial_tempo=120, resolution=22050)
    current_note = 0
    max_end = 0
    for channel_index, c in enumerate(channels_list):

        if channel_index not in channel_index_to_prog:
            continue
        # Instrument
        prog = channel_index_to_prog[channel_index]
        instrument_name = prog_to_instrument_name[prog]
        instrument_notes = []
        instrument = pretty_midi.Instrument(program=prog,
                                            name=instrument_name,
                                            is_drum=(prog >= 112))

        insts = instances_list[channel_index]
        for i, p in enumerate(c):
            for note_index, (name, n) in enumerate(p):
                inst = insts[name]
                inst_time = int(inst['Time']) * 256

                time = 0
                value = None

                # create dict from list of key values
                d = {}
                for k, v in n:
                    d[k] = v

                if 'Time' in d:
                    v = d['Time']
                    time = int(v) + inst_time
                    try:
                        time_end = int(
                            notes_times[current_note + 1]) + inst_time
                        length = time_end - time
                        if length < 0:
                            length = time_end - (time - 256)
                    except:
                        length = 1
                    try:
                        volume = notes_volumes[current_note + 1]
                        if volume is not None:
                            last_volume = volume
                    except:
                        # TODO pb with the last event
                        # print('Should only be the last character')
                        volume = last_volume

                if 'Value' in d:
                    current_note += 1
                    v = d['Value']
                    if v == 'Stop':
                        value = None
                    else:
                        value = values_table[v[0:-1]] + 12 * (int(v[-1]) + 1)
                # TODO never used
                # elif k == 'FinePitch':
                #     pitch = -(int(v) / 128) * 100 * 12
                if (not value is None):
                    time = float(time) / 256 * 4
                    length = float(length) / 256 * 4
                    note = pretty_midi.Note(velocity=volume,
                                            start=time,
                                            end=time + length,
                                            pitch=value)

                    instrument_notes.append(note)
                    if time + length > max_end:
                        max_end = time + length

        instrument.notes = instrument_notes
        midi.instruments.append(instrument)

    ts = pretty_midi.TimeSignature(4, 4, 0)
    eos = pretty_midi.TimeSignature(1, 1, max_end)
    midi.time_signature_changes.extend([ts, eos])

    midi.write(output_mid_file)
    return max_end
Example #27
0
# wiki
# http://craffel.github.io/pretty-midi/#pretty-midi-prettymidi

import pretty_midi

pm = pretty_midi.PrettyMIDI(resolution=960,
                            initial_tempo=120)  #pretty_midiオブジェクトを作ります
instrument = pretty_midi.Instrument(0)  #instrumentはトラックみたいなものです。
instrument2 = pretty_midi.Instrument(1)  #instrumentはトラックみたいなものです。

note_number = pretty_midi.note_name_to_number('G4')
note = pretty_midi.Note(velocity=100, pitch=note_number, start=0,
                        end=1)  #noteはNoteOnEventとNoteOffEventに相当します。

instrument.notes.append(note)
pm.instruments.append(instrument)
pm.write('making/test.mid')

################################################################
#
# MIDIファイルの解析、操作、および合成の使用例:
#
################################################################

#midiをロード
midi_data = pretty_midi.PrettyMIDI('making/test.mid')
# Print an empirical estimate of its global tempo
#速さを出力する
print midi_data.estimate_tempo()

# Compute the relative amount of each semitone across the entire song,
Example #28
0
    def to_pretty_midi(self, constant_tempo=None, constant_velocity=100):
        """
        Convert to a :class:`pretty_midi.PrettyMIDI` instance.

        Notes
        -----
        - Only constant tempo is supported by now.
        - The velocities of the converted pianorolls are clipped to [0, 127],
          i.e. values below 0 and values beyond 127 are replaced by 127 and 0,
          respectively.
        - Adjacent nonzero values of the same pitch will be considered a single
          note with their mean as its velocity.

        Parameters
        ----------
        constant_tempo : int
            The constant tempo value of the output object. Defaults to use the
            first element of `tempo`.
        constant_velocity : int
            The constant velocity to be assigned to binarized tracks. Defaults
            to 100.

        Returns
        -------
        pm : `pretty_midi.PrettyMIDI` object
            The converted :class:`pretty_midi.PrettyMIDI` instance.

        """
        self.check_validity()
        pm = pretty_midi.PrettyMIDI(initial_tempo=self.tempo[0])

        # TODO: Add downbeat support -> time signature change events
        # TODO: Add tempo support -> tempo change events
        if constant_tempo is None:
            constant_tempo = self.tempo[0]
        time_step_size = 60.0 / constant_tempo / self.beat_resolution

        for track in self.tracks:
            instrument = pretty_midi.Instrument(program=track.program,
                                                is_drum=track.is_drum,
                                                name=track.name)
            copied = track.copy()
            if copied.is_binarized():
                copied.assign_constant(constant_velocity)
            copied.clip()
            clipped = copied.pianoroll.astype(np.uint8)
            binarized = clipped > 0
            padded = np.pad(binarized, ((1, 1), (0, 0)), "constant")
            diff = np.diff(padded.astype(np.int8), axis=0)

            positives = np.nonzero((diff > 0).T)
            pitches = positives[0]
            note_ons = positives[1]
            note_on_times = time_step_size * note_ons
            note_offs = np.nonzero((diff < 0).T)[1]
            note_off_times = time_step_size * note_offs

            for idx, pitch in enumerate(pitches):
                velocity = np.mean(clipped[note_ons[idx]:note_offs[idx],
                                           pitch])
                note = pretty_midi.Note(
                    velocity=int(velocity),
                    pitch=pitch,
                    start=note_on_times[idx],
                    end=note_off_times[idx],
                )
                instrument.notes.append(note)

            instrument.notes.sort(key=lambda x: x.start)
            pm.instruments.append(instrument)

        return pm
Example #29
0
def test_get_beats():
    pm = pretty_midi.PrettyMIDI()
    # Add a note to force get_end_time() to be non-zero
    i = pretty_midi.Instrument(0)
    i.notes.append(pretty_midi.Note(100, 100, 0.3, 10.4))
    pm.instruments.append(i)
    # pretty_midi assumes 120 bpm unless otherwise specified
    assert np.allclose(pm.get_beats(),
                       np.arange(0, pm.get_end_time(), 60. / 120.))
    # Testing starting from a different beat time
    assert np.allclose(pm.get_beats(.2),
                       np.arange(0, pm.get_end_time(), 60. / 120.) + .2)
    # Testing a tempo change
    change_bpm = 93.
    change_time = 4.4
    pm._tick_scales.append(
        (pm.time_to_tick(change_time), 60. / (change_bpm * pm.resolution)))
    pm._update_tick_to_time(pm.time_to_tick(pm.get_end_time()))
    # Track at 120 bpm up to the tempo change time
    expected_beats = np.arange(0, change_time, 60. / 120.)
    # BPM switches (4.5 - 4.4)/(60./120.) of the way through
    expected_beats = np.append(
        expected_beats,
        change_time + (4.5 - change_time) / (60. / 120.) * 60. / change_bpm)
    # From there, use the new bpm
    expected_beats = np.append(
        expected_beats,
        np.arange(expected_beats[-1] + 60. / change_bpm, pm.get_end_time(),
                  60. / change_bpm))
    assert np.allclose(pm.get_beats(), expected_beats)
    # When requesting a start_time after the tempo change, make sure we just
    # track as normal
    assert np.allclose(
        pm.get_beats(change_time + .1),
        np.arange(change_time + .1, pm.get_end_time(), 60. / change_bpm))
    # Add a time signature change, which forces beat tracking to restart
    pm.time_signature_changes.append(pretty_midi.TimeSignature(3, 4, 2.1))
    # Track at 120 bpm up to time signature change
    expected_beats = np.arange(0, 2.1, 60. / 120.)
    # Now track, restarting from time signature change time
    expected_beats = np.append(expected_beats,
                               np.arange(2.1, change_time, 60. / 120.))
    # BPM switches (4.6 - 4.4)/(60./120.) of the way through
    expected_beats = np.append(
        expected_beats,
        change_time + (4.6 - change_time) / (60. / 120.) * 60. / change_bpm)
    # From there, use the new bpm
    expected_beats = np.append(
        expected_beats,
        np.arange(expected_beats[-1] + 60. / change_bpm, pm.get_end_time(),
                  60. / change_bpm))
    assert np.allclose(pm.get_beats(), expected_beats)
    # When there are two time signature changes, make sure both get included
    pm.time_signature_changes.append(pretty_midi.TimeSignature(5, 4, 1.9))
    expected_beats[expected_beats == 2.] = 1.9
    assert np.allclose(pm.get_beats(), expected_beats)
    # Request a start time after time time signature change
    expected_beats = np.arange(2.2, change_time, 60. / 120.)
    expected_beats = np.append(
        expected_beats,
        change_time + (4.7 - change_time) / (60. / 120.) * 60. / change_bpm)
    expected_beats = np.append(
        expected_beats,
        np.arange(expected_beats[-1] + 60. / change_bpm, pm.get_end_time(),
                  60. / change_bpm))
    assert np.allclose(pm.get_beats(2.2), expected_beats)
Example #30
0
# -*- coding: utf-8 -*-

import pretty_midi
from common import *

initial_tempo = 76.0
melody_c_melody = pretty_midi.PrettyMIDI(initial_tempo=initial_tempo)

###################################################### melody
melody_program = pretty_midi.instrument_name_to_program('Guitar harmonics')
melody = pretty_midi.Instrument(program=melody_program)

# 心跳乱了节奏
add_instrument_note(instrument=melody, note_name='C3', range=2)
add_instrument_note(instrument=melody, note_name='C2', range=1)
add_instrument_note(instrument=melody, note_name='D2', range=1)
add_instrument_note(instrument=melody, note_name='E2', range=2)
add_instrument_note(instrument=melody, note_name='A2', range=2)
add_instrument_note(instrument=melody, note_name='G2', range=8)

# 梦也不自由
add_instrument_note(instrument=melody, note_name='F2', range=2)
add_instrument_note(instrument=melody, note_name='E2', range=1)
add_instrument_note(instrument=melody, note_name='C2', range=2)
add_instrument_note(instrument=melody, note_name='E2', range=2)
add_instrument_note(instrument=melody, note_name='D2', range=9)

# 爱是个绝对承诺不
add_instrument_note(instrument=melody, note_name='C3', range=2)
add_instrument_note(instrument=melody, note_name='C2', range=1)
add_instrument_note(instrument=melody, note_name='D2', range=1)