Ejemplo n.º 1
0
def plot_interpolation_sotw_to_lick():
    interpolations = []
    for i in range(0, 10, 3):
        path = "Sampled/interpolation_examples/SotW_to_lick/1/interpolate_" + str(
            i) + ".midi"
        midi = ppr.parse(path, beat_resolution=4)  # get Multitrack object
        midi = midi.tracks[0]  # get first/only track
        midi.name = ""
        if i == 0:
            midi.name = "start sequence"
        if i == 10:
            midi.name = "end sequence"

        interpolations.append(midi)

    mt = ppr.Multitrack(tracks=interpolations, beat_resolution=4)
    p, _ = ppr.plot(mt,
                    yticklabel="off",
                    xtick='beat',
                    xticklabel=True,
                    grid="both")
    #p.set_size_inches((8, 8), forward=True)

    filename = "interpolation_SotW_to_lick.png"
    p.savefig(filename)
Ejemplo n.º 2
0
    def generate_pianoroll_music_corpus(self, max_length):
        '''
        Reads in MIDI files placed in dir self.path_to_music in a pianoroll format
        and generates a corpus array of shape (time steps x 88) or (max_length x 88).
        Corpus consists of pianorolls which are basically concatenated n-hot arrays.
        Like that, polyphonic music is allowed.

        Arguments:
        max_length -- maximum length of the corpus
        '''
        corpus = np.empty((0, 128)).astype(bool)
        for i in os.listdir(self.path_to_music):
            if i.endswith('.mid') or i.endswith('.midi'):
                multitrack = piano.parse(os.path.join(self.path_to_music, i))
                multitrack.trim_trailing_silence()
                multitrack.binarize()
                multitrack.downsample(
                    int(multitrack.beat_resolution / self.beat_resolution)
                )  # sample down to self.beat_resolution time steps per beat
                #multitrack.tempo = self.tempo
                #multitrack.beat_resolution = self.beat_resolution
                singletrack = multitrack.tracks[0]
                singletrack.program = self.instrument

                p_roll = singletrack.pianoroll
                corpus = np.append(corpus, p_roll, axis=0)
                if len(corpus) > max_length:
                    corpus = corpus[:max_length]
                    # stop reading in MIDIs if max corpus size is reached
                    break
        return corpus[:, 21:
                      109]  # only select MIDI indices that correspond to notes on a grand piano
Ejemplo n.º 3
0
def plot_pianoroll(path="Sampled/4bar_samples/sample_4_0.midi"):
    midi = ppr.parse(path, beat_resolution=4)  # get Multitrack object
    midi = midi.tracks[0]  # get first/only track
    pianoroll = midi.pianoroll
    print(pianoroll.shape)

    ppr.plot(midi, filename="testppr.png", beat_resolution=4)
Ejemplo n.º 4
0
def find_data_with_no_empty_tracks():
    root_dir = 'E:/merged_midi/'
    total = 0
    midi_collection = get_midi_collection()
    for midi in midi_collection.find({'NotEmptyTracksNum': {
            '$exists': False
    }}):
        instr_tracks = {
            'Drums': None,
            'Piano': None,
            'Guitar': None,
            'Bass': None,
            'Strings': None
        }
        num = 0
        try:
            path = root_dir + midi['Genre'] + '/' + midi['md5'] + '.mid'
            mult = pypianoroll.parse(path)
            for track in mult.tracks:
                num += 1
            midi_collection.update_one({'_id': midi['_id']},
                                       {'$set': {
                                           'NotEmptyTracksNum': num
                                       }})
            print('Progress: {:.2%}\n'.format(
                midi_collection.count({'NotEmptyTracksNum': {
                    '$exists': True
                }}) / midi_collection.count()))
        except:
            total += 1
            # midi_collection.delete_one({'_id': midi['_id']})
    print(total)
Ejemplo n.º 5
0
def process_data(name, beat_res=4, num_of_beats=4, max_tokens=100):
    '''
    Utility function for each data function to extract required data.
    '''
    data_lst = []
    rhythm_lst = []
    note_density_lst = []
    chroma_lst = []

    track = pypianoroll.parse(name, beat_resolution=beat_res).tracks

    if len(track) > 0:
        try:
            pm = pretty_midi.PrettyMIDI(name)
            beats = pm.get_beats()
            tempo = pm.get_tempo_changes()
            cur_idx, tempo_new = 0, []

        except Exception as e:
            print(e)

        pr = track[0].pianoroll

        # extract segment by segment
        for j in range(0, len(pr), beat_res * num_of_beats):
            start_idx = j
            end_idx = j + beat_res * num_of_beats

            if end_idx // beat_res < len(beats):
                new_pr = pr[start_idx:end_idx]
                new_pm = slice_midi(pm, beats, start_idx // beat_res,
                                    end_idx // beat_res)
                new_pm.write("tmp.mid")
                ms = np.argmax(new_pr, axis=-1)

                # ensure each segment is not empty and contain unique notes
                if len(new_pm.instruments[0].notes) > 0 and \
                    len(np.unique(ms)) > 2 and np.count_nonzero(ms) >= 0.75 * len(ms):

                    # get musical attributes
                    _, rhythm, note_density, chroma, \
                        velocity = get_music_attributes(new_pr, beat=beat_res)

                    # get midi encoding sequence
                    events = magenta_encode_midi("tmp.mid")
                    events.append(1)  # EOS token

                    # filter out segments that start with 0 and limit token length
                    if rhythm[0] == 1 and len(events) <= max_tokens:
                        chroma = get_harmony_vector(
                        )  # read from saved "tmp.mid" file

                        # aggregate data points
                        data_lst.append(torch.Tensor(events))
                        rhythm_lst.append(rhythm)
                        note_density_lst.append(note_density)
                        chroma_lst.append(chroma)

    return data_lst, rhythm_lst, note_density_lst, chroma_lst
Ejemplo n.º 6
0
def parse(a_file):
    pianoroll = pr.parse(a_file).tracks[0].pianoroll
    # retrieve 1000 timestamp from the middle.
    # and take [21, 109) range of pitches. https://usermanuals.finalemusic.com/Finale2012Mac/Content/Finale/MIDI_Note_to_Pitch_Table.htm
    matrix_x = ((pianoroll[1000:2000, :] > 0) * 1).reshape(
        1, num_timestamps, num_pitchs)
    matrix_y = pianoroll[1000:2000, :].reshape(1, num_timestamps, num_pitchs)
    return (matrix_x, matrix_y)
Ejemplo n.º 7
0
    def get_full_performance(self, index, beat_resolution=resolution_per_beat):
        infos = self.csv_data_frame.iloc[index]
        midi_filename = infos['midi_filename']
        path = "" + self.root_dir + "/" + midi_filename

        midi = ppr.parse(
            path, beat_resolution=beat_resolution)  # get Multitrack object
        midi = midi.tracks[0]  # get first/only track
        return midi
Ejemplo n.º 8
0
    def load_MIDI(self, path):
        multitrack = piano.parse(path)
        multitrack.trim_trailing_silence()
        multitrack.binarize()

        single_tracks = np.empty((0, 128))
        for i in range(len(multitrack.tracks)):
            singletrack = multitrack.tracks[i].pianoroll

            legal=True
            if self.type=='mono':
                # check if the shortest note is not shorter than our beat resolution
                count = 0
                for i in range(len(singletrack)-1):
                    if np.any(singletrack[i]) and not np.any(singletrack[i+1]) and count < int(multitrack.beat_resolution/self.beat_resolution):
                        legal = False
                        break
                    if np.any(singletrack[i]) and np.array_equal(singletrack[i],singletrack[i+1]) :
                        count+=1
                    else:
                        count = 0

            if legal: # shortest pitch in track is representable by our beat resolution
                downsampled_track = []
                for ts in range(0,len(singletrack)):
                    if ts%int(multitrack.beat_resolution/self.beat_resolution)==0 or not np.any(singletrack[ts]):
                        downsampled_track.append(singletrack[ts])

                '''
                # we have to find the silent time steps between two consecutive same pitches
                ts_zeros = np.squeeze(np.where(~singletrack.any(axis=1)))
                # do not consider first or last time step
                ts_zeros = ts_zeros[(ts_zeros!=0) & (ts_zeros!=len(singletrack))]
                for j in range(len(ts_zeros)):
                    # if pitch before and after silence is the same and this time step will be swallowed by downsampling
                    if np.array_equal(singletrack[ts_zeros[j]-1,:],singletrack[ts_zeros[j]+1,:]) and ts_zeros[j]%int(multitrack.beat_resolution/self.beat_resolution) and not np.any(singletrack[ts_zeros[j]]):
                        # insert silence at the corresponding position such that in downsampled array silence will occur
                        singletrack = np.insert(singletrack, int(np.round(ts_zeros[j]/int(multitrack.beat_resolution/self.beat_resolution),0)), np.zeros(128), axis=1)
                        ts_zeros+=1

                # now we downsample
                singletrack = singletrack[::int(multitrack.beat_resolution/self.beat_resolution)]
                single_tracks = np.append(single_tracks, singletrack, axis=0)
                '''
                single_tracks = np.append(single_tracks, np.array(downsampled_track), axis=0)

        #multitrack.downsample(int(multitrack.beat_resolution/self.beat_resolution)) # sample down to self_beat_resolution time steps per beat
        #multitrack.tempo = self.tempo

        #for i in range(len(multitrack.tracks)):
        #    singletrack = multitrack.tracks[i]
        #    single_tracks = np.append(single_tracks, singletrack.pianoroll, axis=0)

        # singletrack = multitrack.tracks[0]
        # return singletrack.pianoroll
        return single_tracks
def encode_midi(fname, beat=24, is_pr=False):
    if not is_pr:
        track = pypianoroll.parse(fname, beat_resolution=beat)
        pr = track.get_merged_pianoroll()[:beat * 8]
    else:
        pr = fname
    pitch_lst, velocity_lst = convert_pr_to_pitch_lst(pr)
    rhythm = pitch_lst_to_rhythm(pitch_lst)
    events = pr_to_events(pitch_lst, velocity_lst)
    return events, pitch_lst, velocity_lst, pr, rhythm
Ejemplo n.º 10
0
def import_one(filename, beat_resolution, binarize=0):
    """Import one file and generate a piano roll."""
    pr = pypianoroll.parse(filename, beat_resolution)

    if binarize:
        pr = pypianoroll.binarize(pr)

    merged = pr.get_merged_pianoroll()

    return merged
Ejemplo n.º 11
0
def midi_to_small_one_hot_pianoroll(path, beat_resolution=4):
    midi = ppr.parse(path,
                     beat_resolution=beat_resolution)  # get Multitrack object
    midi = midi.tracks[0]
    midi = ppr.binarize(midi)
    midi = midi.pianoroll
    midi = full_to_small_pianoroll(midi)
    midi = pianoroll_to_mono_pianoroll(midi)
    midi = pianoroll_to_one_hot_pianoroll(midi)
    midi = torch.from_numpy(midi).float()
    return midi
Ejemplo n.º 12
0
def parse_midis():
    midis = []

    for midi in os.listdir('./' + directory):
        print('Parsing ' + midi)
        a_midi = parse('./' + directory + '/' + midi,
                       beat_resolution=beat_resolution)
        midis.append(a_midi)

    print('SONGS LOADED')

    return midis
Ejemplo n.º 13
0
def midi2pianoroll(file_path, max_beats=GLOBAL_VAR.MAX_BEATS):

    multitrack = pypianoroll.parse(file_path)
    pianoroll = multitrack.get_merged_pianoroll()

    pianorolls = []
    start = 0
    while len(pianoroll) - start >= max_beats:
        pianoroll_piece = pianoroll[start:(start + max_beats)]
        pianorolls.append(pianoroll_piece)
        start += max_beats
        break
    return pianorolls
Ejemplo n.º 14
0
    def generate_MIDIindex_music_corpus(self, max_length):
        '''
        Reads in MIDI files placed in dir self.path_to_music in a pianoroll format.
        Generates a symbolic one-dimensional corpus array of length sum of time
        steps of all files or self.max_corpus_size and saves it in self.corpus.
        It is an array of MIDI indices, with -1 corresponding to silence

        Arguments:
        max_length -- maximum length of the corpus
        '''
        sym_sequence = np.array([]).astype(np.int8)
        for i in os.listdir(self.path_to_music):
            if i.endswith('.mid') or i.endswith('.midi'):
                # remove trailing silence and binarize (same loudness)
                multitrack = piano.parse(os.path.join(self.path_to_music, i))
                multitrack.trim_trailing_silence()
                multitrack.binarize()
                multitrack.downsample(
                    int(multitrack.beat_resolution / self.beat_resolution)
                )  # sample down to self_beat_resolution time steps per beat
                #multitrack.tempo = self.tempo
                #multitrack.beat_resolution = self.beat_resolution

                singletrack = multitrack.tracks[0]
                singletrack.program = self.instrument

                p_roll = singletrack.pianoroll
                if piano.metrics.polyphonic_rate(
                        p_roll
                ) > 0:  # we only work with monophonic input when we have symbolic alphabet
                    pass
                else:
                    temp = np.full(
                        p_roll.shape[0],
                        -1)  # make a sequence of -1 (stands for silence)
                    indices_non_zero = p_roll.nonzero(
                    )  # find all time steps where a tone is played
                    temp[indices_non_zero[0]] = indices_non_zero[
                        1]  # set non_zero time steps with the current index for pitch played
                    sym_sequence = np.append(sym_sequence, temp)
                    if len(sym_sequence) > max_length:
                        break

        corpus = np.array(sym_sequence).flatten().astype(np.int8)
        if len(corpus) > max_length:
            corpus = corpus[:max_length]
        return corpus
    def _convert_to_tfrecords(self, mode, filename_list):
        filename = self.DATA_PATH + "/" + mode + ".tfrecords"
        if check_path_exists(filename):
            return

        logging.info("Writing {}".format(filename))
        with tf.python_io.TFRecordWriter(filename) as writer:
            for filename in tqdm(filename_list):
                if filename.endswith(".mid") or filename.endswith(".midi"):
                    multi_track = ppr.parse(filename)
                else:
                    multi_track = ppr.load(filename)

                TOTAL_STEPS = self._choose_total_steps(multi_track)
                if TOTAL_STEPS == 1e8:
                    continue
                RANGE = self.INPUT_SIZE
                FINAL_STEPS = math.ceil(TOTAL_STEPS / 24)
                multi_data = np.zeros((FINAL_STEPS, RANGE))

                for track in multi_track.tracks:
                    if not self._is_valid_track(track):
                        continue
                    data = track.pianoroll.astype(int)
                    data = self._sampling(data)
                    multi_data = np.add(multi_data, data)
                multi_data = np.clip(multi_data, 0, 1).astype(int)

                RANGE = self._split_into_segments(multi_data, 1)
                length = self.MAX_LEN

                for start in RANGE:
                    end = start + length
                    if end >= FINAL_STEPS:
                        break
                    example = tf.train.Example(
                        features=tf.train.Features(
                            feature={
                                "pianoroll":
                                self._int64_list_feature(
                                    multi_data[start:end + 1].flatten())
                            }))
                    writer.write(example.SerializeToString())
Ejemplo n.º 16
0
def plot_interpolation_pianorolls(bars=16):
    interpolations = []
    for i in range(0, 6, 2):
        path = "Sampled/" + str(bars) + "bar_interpolation/interpolate_" + str(
            i) + ".midi"

        midi = ppr.parse(path, beat_resolution=4)  # get Multitrack object
        midi = midi.tracks[0]  # get first/only track
        midi.name = ""
        if i == 0:
            midi.name = "start sequence"
        if i == 4:
            midi.name = "end sequence"
        pr = midi.pianoroll

        # padding to full length in case MIDI file ends earlier
        if pr.shape[0] != bars * 16:
            padding = np.zeros((bars * 16 - pr.shape[0], pr.shape[1]))
            pr = np.concatenate((pr, padding), axis=0)
            midi.pianoroll = pr
        interpolations.append(midi)

    mt = ppr.Multitrack(tracks=interpolations, beat_resolution=4)

    if bars == 16:
        p, _ = ppr.plot(mt,
                        yticklabel="number",
                        xtick='beat',
                        xticklabel=False,
                        grid="off")
        # there seems to be a bug in ppr, despite xticklabel=False, the plot still has the labels for each x-axis value
    else:
        p, _ = ppr.plot(mt,
                        yticklabel="number",
                        xtick='beat',
                        xticklabel=True,
                        grid="both")
    p.set_size_inches((8, 8), forward=True)

    filename = str(bars) + "bar_interpolation.png"
    p.savefig(filename)
Ejemplo n.º 17
0
def parse_multiple_dynamic(a_file):
    pianoroll = pr.parse(a_file).tracks[0].pianoroll
    shape = pianoroll.shape
    print(shape)

    matrix_x = []
    matrix_y = []

    total_timestamps = shape[0]
    t = 0
    while t + 1000 <= total_timestamps:
        matrix_t = ((pianoroll[t:t + 1000, :] > 0) * 1).reshape(
            1, num_timestamps, num_pitchs)
        matrix_t = pianoroll[t:t + 1000, :].reshape(1, num_timestamps,
                                                    num_pitchs)
        matrix_x.append(matrix_t)
        matrix_y.append(matrix_t)
        t += 1000

    print("done parsing {} dynamically into {} segments of 1000 timestamps".
          format(a_file, len(matrix_x)))
    return (matrix_x, matrix_y)
Ejemplo n.º 18
0
def parse_multiple(a_file):
    print("parsing ", a_file)
    pianoroll = pr.parse(a_file).tracks[0].pianoroll
    print(pianoroll.shape)
    # retrieve 1000 timestamp from the 3 segments.
    # for each take [21, 109) range of pitches. https://usermanuals.finalemusic.com/Finale2012Mac/Content/Finale/MIDI_Note_to_Pitch_Table.htm
    # stripped out xtracrispy.mid qhich is too short.
    matrix_x_1 = ((pianoroll[0:1000, :] > 0) * 1).reshape(
        1, num_timestamps, num_pitchs)
    matrix_y_1 = pianoroll[0:1000, :].reshape(1, num_timestamps, num_pitchs)
    matrix_x_2 = ((pianoroll[1000:2000, :] > 0) * 1).reshape(
        1, num_timestamps, num_pitchs)
    matrix_y_2 = pianoroll[1000:2000, :].reshape(1, num_timestamps, num_pitchs)
    matrix_x_3 = ((pianoroll[2000:3000, :] > 0) * 1).reshape(
        1, num_timestamps, num_pitchs)
    matrix_y_3 = pianoroll[2000:3000, :].reshape(1, num_timestamps, num_pitchs)
    matrix_x_4 = ((pianoroll[3000:4000, :] > 0) * 1).reshape(
        1, num_timestamps, num_pitchs)
    matrix_y_4 = pianoroll[3000:4000, :].reshape(1, num_timestamps, num_pitchs)

    return ((matrix_x_1, matrix_x_2, matrix_x_3, matrix_x_4),
            (matrix_y_1, matrix_y_2, matrix_y_3, matrix_y_4))
Ejemplo n.º 19
0
def get_track(midi_filename, voice, beat_resolution, transpose=True):
    '''
    Convert midi file to track object
    :midi_filename: midi file to convert
    :voice: voice to select in the midi file (soprano, alto, tenor, bass)
    :beat_resolution: number of time steps per quarter notes
    :transpose: True if transpose to C Major
    :return: track object for the selected voice
    '''

    csv_text = midi_utils.load_to_csv(midi_filename)
    # get semitones to C major
    semitones, _ = get_semitones_to_C(csv_text)
    # get multitrack object from midi
    multitrack = pypianoroll.parse(midi_filename,
                                   beat_resolution=beat_resolution)
    # get the voice track
    if transpose:
        track = pypianoroll.transpose(multitrack.tracks[voice], -semitones)
    else:
        track = multitrack.tracks[voice]
    return track
Ejemplo n.º 20
0
def main():
    """Main function: Converts selected MIDI files to pianoroll."""
    args = parse_arguments()

    songs = get_long_songs()

    if args.use_muspy:
        final_path = os.path.join(args.data_path, 'results', 'midi_files')
        if not os.path.exists(final_path):
            os.mkdir(final_path)

        for song in songs:
            midifile = midi_path(song)
            midi_class = pretty_midi.PrettyMIDI(midifile)

            final_midi_path = os.path.join(final_path, song)
            if not os.path.exists(os.path.join(final_midi_path, '.mid')):
                try:
                    midi_class.write(final_midi_path + '.mid')
                except (IOError, IndexError) as e:
                    pass

    else:
        final_path = os.path.join(args.data_path, 'results', 'npz_files')
        if not os.path.exists(final_path):
            os.mkdir(final_path)

        for song in songs:
            midifile = midi_path(song)
            npz_path = os.path.join(final_path, song)

            if not os.path.exists(os.path.join(npz_path, '.npz')):
                try:
                    parsed = pypianoroll.parse(midifile)
                    pypianoroll.save(npz_path, parsed)
                except (IOError, IndexError) as e:
                    pass
Ejemplo n.º 21
0
def list_melodies(midi_path, out_dirname=None):
    """Lists extracted melodies of midi file given by path.
    Shows melody idx, length and optionally path to melody plot"""
    melodies = extract_melodies(midi_path)

    pp_multitrack = pp.parse(midi_path)

    for i, melody in enumerate(melodies):
        fig = plt.figure(figsize=(15, 10))
        ax = fig.add_subplot(211)

        pianoroll = melody_lib.melody_to_pianoroll(melody["events"])
        pp.plot_pianoroll(ax, pianoroll)

        ticks = np.arange(0, pianoroll.shape[0], STEPS_PER_BAR * 2)
        ax.set_xticks(ticks)
        ax.set_xticklabels(np.arange(0, len(ticks)) * 2)
        ax.grid(True, axis='x')
        plt.title('Extracted melody')

        ax = fig.add_subplot(212)
        pp.plot_pianoroll(ax,
                          pp_multitrack.tracks[melody["instrument"]].pianoroll)
        plt.title('Original midi track')

        plot_basename = ""
        if out_dirname is not None:
            plot_basename = "lst_{}_{}.png".format(Path(midi_path).stem, i)
            fig.savefig(str(out_dirname / plot_basename))
        plt.show()
        plt.close()

        print("idx: {:2d},\tlength: {:3d}{}".format(
            i,
            len(melody["events"]) // 16,
            "" if out_dirname is None else ",\t" + plot_basename))
    # Used for observing distribution and mapping of MIDI instruments to classes
    melodyNumber = [0] * num_of_files
    stringsNumber = [0] * num_of_files
    chordsNumber = [0] * num_of_files
    vocalsNumber = [0] * num_of_files
    windsNumber = [0] * num_of_files
    percussionNumber = [0] * num_of_files
    bassNumber = [0] * num_of_files
    unclassifiedTracks = dict()

    for file in os.listdir(midi_folder):
        filename = os.fsdecode(file)
        print(str(j) + ' - ' + filename)
        j += 1

        pr = pypianoroll.parse(midi_folder + filename)
        pm_song = pretty_midi.PrettyMIDI(midi_folder + filename)

        if (pm_song.resolution == tpqn
            ):  # need the file resolution to be constant

            tracklist = pr.tracks
            for t, track in enumerate(tracklist):
                instrument_class = utils.readLabels(track.program, track.name,
                                                    track.is_drum)

                if (t == 0):  # do it for first track only as an initialization

                    # Initialize every entry with an empty pianoroll
                    percussion_pianorolls[i] = np.zeros(np.shape(
                        track.pianoroll[:, note_shift:(note_shift +
Ejemplo n.º 23
0
    def pooled_process_file(self, args):
        def check_four_fourth(time_sign):
            return time_sign.numerator == 4 and time_sign.denominator == 4

        idx, filepath = args
        fetch_meta = {
        }  # in this dict I will store the id of the corresponding metadata file

        store_meta = False
        pbc = 1
        yeah = 0
        max_bar_silence = 0

        processed_folder = os.path.join(self.data_path, "pianorolls/")
        path, file = os.path.split(filepath)

        artist = path.split(path_sep)[-1]
        filename = file.split(".")[0]

        # test 0: check keysignature = 4/4 always.
        try:
            pm_song = pm.PrettyMIDI(filepath)
        except Exception:
            # print(f'{idx} Not Pretty MIDI  {filepath}')
            return pbc, yeah, fetch_meta

        if not all(
            [check_four_fourth(tmp)
             for tmp in pm_song.time_signature_changes]):
            return pbc, yeah, fetch_meta

        del pm_song  # don't need pretty midi object anymore, now i need pianorolls

        try:
            base_song = pproll.parse(filepath, beat_resolution=4)
        except Exception:
            return pbc, yeah, fetch_meta

        # find a guitar, a bass and a drum instrument
        guitar_tracks, bass_tracks, drums_tracks, string_tracks = self.get_guitar_bass_drums(
            base_song)

        try:
            assert (string_tracks)
        except AssertionError:
            return pbc, yeah, fetch_meta

        # if string_tracks:
        base_song.merge_tracks(string_tracks,
                               mode="max",
                               program=48,
                               name="Strings",
                               remove_merged=True)

        # merging tracks change order of them, need to re-find the new index of Trio track
        guitar_tracks, bass_tracks, drums_tracks, string_tracks = self.get_guitar_bass_drums(
            base_song)

        # take all possible combination of guitar, bass and drums
        for guitar_track in guitar_tracks:
            for bass_track in bass_tracks:
                for drums_track in drums_tracks:
                    # select only trio tracks (and strings)
                    current_tracks = [
                        drums_track, bass_track, guitar_track, -1
                    ]
                    names = ["Drums", "Bass", "Guitar", "Strings"]

                    # create temporary song with only that tracks
                    song = pproll.Multitrack()
                    song.remove_empty_tracks()

                    for i, current_track in enumerate(current_tracks):
                        song.append_track(
                            pianoroll=base_song.tracks[current_track].
                            pianoroll,
                            program=base_song.tracks[current_track].program,
                            is_drum=base_song.tracks[current_track].is_drum,
                            name=names[i])

                    song.beat_resolution = base_song.beat_resolution
                    song.tempo = base_song.tempo

                    song.binarize()
                    song.assign_constant(1)

                    # Test 1: check whether a track is silent during all the song
                    if song.get_empty_tracks():
                        continue

                    pianoroll = song.get_stacked_pianoroll()

                    i = 0
                    while i + self.phrase_size <= pianoroll.shape[0]:
                        window = pianoroll[i:i + self.phrase_size, :, :]
                        # print("window from", i, "to", i+self.phrase_size)

                        # keep only the phrases that have at most one bar of consecutive silence
                        # for each track
                        bar_of_silences = np.array([0] * self.n_tracks)
                        for track in range(self.n_tracks):
                            j = 0
                            while j + self.bar_size <= window.shape[0]:
                                if window[j:j + self.bar_size, :,
                                          track].sum() == 0:
                                    bar_of_silences[track] += 1

                                j += 1  # self.bar_size

                        # if the phrase is good, let's store it
                        if not any(bar_of_silences > max_bar_silence):
                            # data augmentation, random transpose bar
                            for shift in np.random.choice(
                                [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6],
                                    1,
                                    replace=False):
                                tmp = pproll.Multitrack()
                                tmp.remove_empty_tracks()
                                for track in range(self.n_tracks):
                                    tmp.append_track(
                                        pianoroll=window[:, :, track],
                                        program=song.tracks[track].program,
                                        name=config.instrument_names[
                                            song.tracks[track].program],
                                        is_drum=song.tracks[track].is_drum)

                                tmp.beat_resolution = 4
                                tmp.tempo = song.tempo
                                # tmp.name = str(yeah)
                                tmp.name = f"{idx}_{yeah}"

                                # breakpoint()
                                tmp.transpose(shift)
                                tmp.check_validity()
                                # print(os.path.join(processed_folder, f"{idx}_{yeah}" + ".npz"))
                                # tmp.save(os.path.join(processed_folder, f"{idx}_{yeah}" + ".npz"))
                                del tmp
                                store_meta = True
                                # adding link to corresponding metadata file
                                fetch_meta[f"{idx}_{yeah}"] = {
                                    "artist": artist,
                                    "song": filename
                                }
                                yeah += 1

                        i += self.bar_size
                    del song

        del base_song
        return pbc, yeah, fetch_meta
Ejemplo n.º 24
0
    def load_MIDI(self, path):
        multitrack = piano.parse(path)
        multitrack.trim_trailing_silence()
        multitrack.binarize()
        single_tracks = np.empty((0, 128))

        if self.type == 'mono':
            for i in range(len(multitrack.tracks)):
                singletrack = multitrack.tracks[i].pianoroll

                if multitrack.beat_resolution != self.beat_resolution:  # we downsample
                    # check if the shortest note is not shorter than our beat resolution
                    count = 0
                    legal = True
                    for i in range(len(singletrack) - 1):
                        if np.any(singletrack[i]) and not np.any(
                                singletrack[i + 1]) and count < int(
                                    multitrack.beat_resolution /
                                    self.beat_resolution):
                            legal = False
                            break
                        if np.any(singletrack[i]) and np.array_equal(
                                singletrack[i], singletrack[i + 1]):
                            count += 1
                        else:
                            count = 0

                    if legal:  # shortest pitch in track is representable by our beat resolution
                        downsampled_track = []
                        downsampled_track.append(
                            singletrack[0])  # first time step always in
                        for ts in range(1, len(singletrack) - 1):
                            if ts % int(
                                    multitrack.beat_resolution /
                                    self.beat_resolution) == 0 or not np.any(
                                        singletrack[ts]) and np.any(
                                            singletrack[ts - 1]) and np.any(
                                                singletrack[ts + 1]):
                                downsampled_track.append(singletrack[ts])
                        if (len(singletrack) - 1) % int(
                                multitrack.beat_resolution /
                                self.beat_resolution) == 0:
                            downsampled_track.append(
                                singletrack[len(singletrack) -
                                            1])  # also consider last time step

                        single_tracks = np.append(single_tracks,
                                                  np.array(downsampled_track),
                                                  axis=0)
                    else:
                        print(
                            'skip track that is not representable by desired beat resolution',
                            self.beat_resolution)

                elif self.beat_resolution == multitrack.beat_resolution:
                    # we don't downsample because beat resolution is the same as the track
                    single_tracks = np.append(single_tracks,
                                              np.array(singletrack),
                                              axis=0)

        if self.type == 'poly':
            # merge the tracks of the same instrument
            instruments = {}
            instrument = -1
            for i in range(len(multitrack.tracks)):
                if instrument != multitrack.tracks[i].program:
                    instruments[multitrack.tracks[i].program] = [
                        i
                    ]  # append track IDs to instrument
                    instrument = multitrack.tracks[i].program
                elif instrument == multitrack.tracks[i].program:
                    instruments[instrument].append(i)

            merged_tracks_per_instrument = []

            for instrument in instruments:
                merged_tracks_per_instrument.append(
                    multitrack[instruments[instrument]].get_merged_pianoroll())

            if multitrack.beat_resolution != self.beat_resolution:
                # we want to find out if we can downsample the track
                # we need to know the shortest and longest note
                merged = multitrack.get_merged_pianoroll(
                )  # all tracks merged together

                # make a list of all possible notes
                indices_non_zero = np.where(merged)
                alphabet = list(np.arange(21, 109))
                indices_per_note = {}
                min_per_note = {}
                max_per_note = {}

                # get indices in track where each note is played
                for note in alphabet:
                    indices_per_note[note] = indices_non_zero[0][np.where(
                        indices_non_zero[1] == note)]
                    if indices_per_note[
                            note].size > 0:  # else the note does not appear (length 0)
                        min_per_note[note] = len(indices_per_note)
                        max_per_note[note] = 1
                        count = 1
                        for i in range(len(indices_per_note[note]) - 1):
                            if indices_per_note[note][
                                    i + 1] == indices_per_note[note][i] + 1:
                                count += 1
                            else:
                                if count < min_per_note[note]:
                                    min_per_note[note] = count
                                if count > max_per_note[note]:
                                    max_per_note[note] = count
                                count = 1

                shortest_note = int(min(min_per_note.values()))
                longest_note = int(max(max_per_note.values()))

                # get shortest possible beat resolution
                #for i in reversed(range(shortest_note)):
                #    if beat_resolution%(i+1) == 0:
                #        beat_resolution = int(beat_resolution/(i+1))
                #        break

                # is shortest note a divisor of beat_resolution?
                if shortest_note >= int(
                        multitrack.beat_resolution / self.beat_resolution):
                    #self.beat_resolution%shortest_note ==0 and shortest_note!=1:
                    # then we down-sample
                    for track in merged_tracks_per_instrument:
                        downsampled_track = []
                        downsampled_track.append(
                            track[0])  # first time step always in
                        for ts in range(1, len(track) - 1):
                            if ts % int(
                                    multitrack.beat_resolution /
                                    self.beat_resolution) == 0 or not np.any(
                                        track[ts]) and np.any(
                                            track[ts - 1]) and np.any(
                                                track[ts + 1]):
                                downsampled_track.append(track[ts])
                        if (len(track) - 1) % int(multitrack.beat_resolution /
                                                  self.beat_resolution) == 0:
                            downsampled_track.append(
                                track[len(track) -
                                      1])  # also consider last time step

                        single_tracks = np.append(single_tracks,
                                                  np.array(downsampled_track),
                                                  axis=0)

            if multitrack.beat_resolution == self.beat_resolution:
                for track in merged_tracks_per_instrument:
                    single_tracks = np.append(single_tracks,
                                              np.array(track),
                                              axis=0)

            # else we ignore the track because it is not representable by the chosen beat resolution
        return single_tracks
Ejemplo n.º 25
0
# coding: utf-8

# In[1]:

import os
import pypianoroll as pn

# In[3]:

os.chdir('./archive/new_songs/')

# In[8]:

subdir = [dI for dI in os.listdir('.') if os.path.isdir(os.path.join('.', dI))]
ko = 0
po = 0
for i in subdir:
    po += 1
    os.chdir(i)
    a = pn.parse('all.mid')
    b = pn.parse('melody.mid')
    if (a.get_active_length() >= b.get_active_length()):
        ko += 1
    os.chdir("..")

print ko * 100.0 / po
Ejemplo n.º 26
0
def proc_midi_to_pianoroll(filename, beats_in_measure):
    piano_roll = pypianoroll.parse(filename)
    piano_roll.downbeat[0::piano_roll.beat_resolution*beats_in_measure] = True
    return piano_roll
Ejemplo n.º 27
0
    return b


def trunc_sequences(x_train):
    windows = []
    for j in range(len(x_train)):
        temp_x = np.array(
            np.array_split(pad_along_axis(x_train[j], seq_len),
                           np.ceil(len(x_train[j]) / seq_len)))
        windows.append(temp_x)
    return np.array(windows)


x = []
for i in range(1, len(sys.argv)):
    a = pn.parse(sys.argv[i])
    x.append(1 * np.sign(a.tracks[0].pianoroll))

x_final = np.array(x)
x_con = trunc_sequences(x_final)
for j in range(len(x_con)):
    bolo = []
    xo = np.expand_dims(x_con[j], axis=1)
    for k in range(len(x_con[j])):
        bolo.extend(model.predict_on_batch(xo[k]))
    model.reset_states()
    bolo = np.concatenate(np.array(bolo))
    result = pn.binarize(pn.Track(pianoroll=bolo * 100,
                                  program=0,
                                  is_drum=False,
                                  name='my awesome piano'),
Ejemplo n.º 28
0
    def extract_real_song_names(self, pianorolls_folder, metadata_folder,
                                early_exit):
        # helper functions
        def msd_id_to_dirs(msd_id):
            """Given an MSD ID, generate the path prefix.
			E.g. TRABCD12345678 -> A/B/C/TRABCD12345678"""
            return os.path.join(msd_id[2], msd_id[3], msd_id[4], msd_id)

        def msd_id_to_h5(h5):
            """Given an MSD ID, return the path to the corresponding h5"""
            return os.path.join(metadata_folder,
                                msd_id_to_dirs(msd_id) + '.h5')

        def check_four_fourth(time_sign):
            return time_sign.numerator == 4 and time_sign.denominator == 4

        # create necessary folders
        pianorolls_path = os.path.join(self.dataset_path, "pianorolls/")
        metadata_path = os.path.join(self.dataset_path, "metadata/")
        songs_path = os.path.join(self.dataset_path, "songs/")
        #instruments_path = os.path.join(self.dataset_path, "instruments/")
        dest_paths = [pianorolls_path, metadata_path,
                      songs_path]  #, instruments_path]
        for path in dest_paths:
            if not os.path.exists(path):
                os.makedirs(path)

        # count number of files of dataset (slow but ok)
        self.dataset_length = sum(
            [len(files) for _, _, files in os.walk(pianorolls_folder)])
        # assign unique id for each song of dataset
        print("Extracting real song names...")
        bar = progressbar.ProgressBar(max_value=self.dataset_length)
        pbc = 0
        yeah = 0
        fetch_meta = {
        }  # in this dict I will store the id of the corresponding metadata file
        max_bar_silence = 0

        with open(os.path.join(self.dataset_path, "song_names.txt"),
                  "a") as song_names_fp:
            for path, subdirs, files in os.walk(pianorolls_folder):
                for file in files:
                    store_meta = False
                    pbc += 1
                    msd_id = path.split("/")[-1]
                    filename = file.split(".")[0]

                    # early exit
                    if early_exit != None and pbc > early_exit:
                        return

                    # test 0: check keysignature = 4/4 always.
                    try:
                        pm_song = pm.PrettyMIDI(os.path.join(path, file))
                    except Exception:
                        continue

                    if not all([
                            check_four_fourth(tmp)
                            for tmp in pm_song.time_signature_changes
                    ]):
                        continue

                    del pm_song  # don't need pretty midi object anymore, now i need pianorolls

                    try:
                        base_song = pproll.parse(os.path.join(path, file),
                                                 beat_resolution=4)
                    except Exception:
                        continue

                    # trova uno strumento chitarra, uno basso e uno drums
                    guitar_tracks, bass_tracks, drums_tracks, string_tracks = self.get_guitar_bass_drums(
                        base_song)

                    try:
                        assert (string_tracks)
                    except AssertionError:
                        continue

                    #if string_tracks:
                    base_song.merge_tracks(string_tracks,
                                           mode="max",
                                           program=48,
                                           name="Strings",
                                           remove_merged=True)

                    # merging tracks change order of them, need to re-find the new index of Trio track
                    guitar_tracks, bass_tracks, drums_tracks, string_tracks = self.get_guitar_bass_drums(
                        base_song)

                    # take all possible combination of guitar, bass and drums
                    for guitar_track in guitar_tracks:
                        for bass_track in bass_tracks:
                            for drums_track in drums_tracks:
                                # select only trio tracks (and strings)
                                current_tracks = [
                                    drums_track, bass_track, guitar_track, -1
                                ]
                                names = ["Drums", "Bass", "Guitar", "Strings"]

                                # create temporary song with only that tracks
                                song = pproll.Multitrack()
                                song.remove_empty_tracks()

                                for i, current_track in enumerate(
                                        current_tracks):
                                    song.append_track(
                                        pianoroll=base_song.
                                        tracks[current_track].pianoroll,
                                        program=base_song.
                                        tracks[current_track].program,
                                        is_drum=base_song.
                                        tracks[current_track].is_drum,
                                        name=names[i])

                                song.beat_resolution = base_song.beat_resolution
                                song.tempo = base_song.tempo

                                # Test 1: check whether a track is silent during all the song
                                if song.get_empty_tracks():
                                    continue

                                pianoroll = song.get_stacked_pianoroll()

                                i = 0
                                while i + self.phrase_size <= pianoroll.shape[
                                        0]:
                                    window = pianoroll[i:i +
                                                       self.phrase_size, :, :]

                                    # keep only the phrases that have at most one bar of consecutive silence
                                    # for each track
                                    bar_of_silences = np.array([0] *
                                                               self.n_tracks)
                                    for track in range(self.n_tracks):
                                        j = 0
                                        while j + self.bar_size <= window.shape[
                                                0]:
                                            if window[j:j + self.bar_size, :,
                                                      track].sum() == 0:
                                                bar_of_silences[track] += 1

                                            j += 1  #self.bar_size

                                    # if the phrase is good, let's store it
                                    #print(bar_of_silences)
                                    if not any(
                                            bar_of_silences > max_bar_silence):
                                        store_meta = True
                                        # adding link to corresponding metadata file
                                        # yeah: pianorolls counter
                                        # pbc: song/metadata counter
                                        fetch_meta[str(yeah)] = pbc
                                        yeah += 1

                                    i += self.bar_size
                                del song

                    # finished with pianorolls, storing rest (if needed)
                    if store_meta:
                        # fetching corresponding metadata from Million song dataset
                        with tables.open_file(msd_id_to_h5(msd_id)) as h5:
                            title = str(h5.root.metadata.songs.cols.title[0],
                                        "utf-8")
                            artist = str(
                                h5.root.metadata.songs.cols.artist_name[0],
                                "utf-8")
                            album = str(h5.root.metadata.songs.cols.release[0],
                                        "utf-8")
                            genres = [
                                str(genre, "utf-8") for genre in list(
                                    h5.root.metadata.artist_terms[:])
                            ]

                        metadata = {
                            "title": title,
                            "artist": artist,
                            "album": album,
                            "genres": genres
                        }

                        song_names_fp.write(
                            str(pbc) + " -> " + artist + " - " + title + "\n")
                    del base_song

                    bar.update(pbc)
Ejemplo n.º 29
0
        else:
            X = np.r_[X,aux_X];
    return X;

def transform_pitch(mapping,pitch):
    new_pitch = np.zeros(pitch.shape);    
    for i in range(pitch.shape[0]):
        for j in range(128):
            n_o = j/12;
            n_j = 12*n_o + mapping[j%12];
            if n_j < 128:
                new_pitch[i,n_j] = pitch[i,j];
    return new_pitch;

#Get first 4 bars of Ode to Joy
SONG = pypianoroll.parse("ode_to_joy.mid");
SONG.tracks[0].transpose(-5);
SONG_br    = SONG.beat_resolution;
SONG_bpm   = SONG.tempo;
SONG_pitch = SONG.tracks[0].pianoroll;

MAX_LEN = int(0.25*SONG_bpm.shape[0]);
SONG_pitch = SONG_pitch[:MAX_LEN,:];
SONG_bpm   = SONG_bpm[:MAX_LEN];

SONG_audio = convert_to_wav(SONG_pitch,SONG_bpm,SONG_br);

#Make multiplicative inverse table for the multiplicative Z13 group
nnames = np.array(['C','C#','D','D#','E','F','F#','G','G#','A','A#','B']);

Z13 = np.zeros((12,12),dtype=int);
Ejemplo n.º 30
0
            )].beat_resolution  #stats[str(n)][str(exp_n[0])].beat_resolution
        else:
            assert max_corpus_size == params[str(
                exp
            )].max_corpus_size  #params[str(n)][str(exp_n[0])].max_corpus_size
            assert beat_resolution == stats[str(
                exp
            )].beat_resolution  #stats[str(n)][str(exp_n[0])].beat_resolution

# now we have to read in the corpus
path_to_music = os.path.join(os.getcwd(), '..', 'midis/')
sym_sequence = np.array([]).astype(np.int8)
for i in os.listdir(path_to_music):
    if i.endswith('.mid') or i.endswith('.midi'):
        # remove trailing silence and binarize (same loudness)
        multitrack = piano.parse(os.path.join(path_to_music, i))
        multitrack.trim_trailing_silence()
        multitrack.binarize()
        multitrack.downsample(
            int(multitrack.beat_resolution / beat_resolution
                ))  # sample down to self_beat_resolution time steps per beat
        singletrack = multitrack.tracks[0]

        p_roll = singletrack.pianoroll
        if piano.metrics.polyphonic_rate(
                p_roll
        ) > 0:  # we only work with monophonic input when we have symbolic alphabet
            pass
        else:
            temp = np.full(p_roll.shape[0],
                           -1)  # make a sequence of -1 (stands for silence)