def get_batch(leadsheets, with_sample=False):
    """
    Get a batch

    leadsheets should be a list of dataset lists of (chord, melody) tuples, or just a dataset list of tuples

    returns: chords, melodies
    """
    if not isinstance(leadsheets[0], list):
        leadsheets = [leadsheets]

    sample_datasets = [random.randrange(len(leadsheets)) for _ in range(BATCH_SIZE)]
    sample_fns = [random.choice(leadsheets[i]) for i in sample_datasets]
    loaded_samples = [leadsheet.parse_leadsheet(lsfn) for lsfn in sample_fns]
    sample_lengths = [leadsheet.get_leadsheet_length(c,m) for c,m in loaded_samples]

    starts = [(0 if l==SEGMENT_LEN else random.randrange(0,l-SEGMENT_LEN,SEGMENT_STEP)) for l in sample_lengths]
    sliced = [leadsheet.slice_leadsheet(c,m,s,s+SEGMENT_LEN) for (c,m),s in zip(loaded_samples, starts)]

    res = list(zip(*sliced))

    sample_sources = ["{}: starting at {} = bar {}".format(fn, start, start/(constants.WHOLE//constants.RESOLUTION_SCALAR)) for fn,start in zip(sample_fns, starts)]

    if with_sample:
        return res, sample_sources
    else:
        return res
def validate_generate(model, validation_leadsheets, generated_dir):
    for lsfn in validation_leadsheets:
        ch,mel = leadsheet.parse_leadsheet(lsfn)
        batch = ([ch],[mel]), [lsfn]
        curdir = os.path.join(generated_dir, os.path.splitext(os.path.basename(lsfn))[0])
        os.makedirs(curdir)
        generate(model, None, os.path.join(curdir, "generated"), with_vis=True, batch=batch)
Esempio n. 3
0
def main(file, split, output=None):
    c,m = leadsheet.parse_leadsheet(file)
    lslen = leadsheet.get_leadsheet_length(c,m)
    divwidth = int(split) * (constants.WHOLE//constants.RESOLUTION_SCALAR)
    slices = [leadsheet.slice_leadsheet(c,m,s,s+divwidth) for s in range(0,lslen,divwidth)]
    if output is None:
        output = file + "-split"
    for i, (chords, melody) in enumerate(slices):
        leadsheet.write_leadsheet(chords, melody, '{}_{}.ls'.format(output,i))
Esempio n. 4
0
def filter_leadsheets(leadsheets):
    new_leadsheets = []
    for lsfn in leadsheets:
        print("---- {} ----".format(lsfn))
        c, m = leadsheet.parse_leadsheet(lsfn, verbose=True)
        length = leadsheet.get_leadsheet_length(c, m)
        if length < SEGMENT_LEN:
            print("Leadsheet {} is too short! Skipping...".format(lsfn))
        else:
            new_leadsheets.append(lsfn)
    print("Found {} leadsheets.".format(len(leadsheets)))
    return new_leadsheets
Esempio n. 5
0
def validate_generate(model, validation_leadsheets, generated_dir):
    for lsfn in validation_leadsheets:
        ch, mel = leadsheet.parse_leadsheet(lsfn)
        batch = ([ch], [mel]), [lsfn]
        curdir = os.path.join(generated_dir,
                              os.path.splitext(os.path.basename(lsfn))[0])
        os.makedirs(curdir)
        generate(model,
                 None,
                 os.path.join(curdir, "generated"),
                 with_vis=True,
                 batch=batch)
Esempio n. 6
0
def main(file, split, output=None):
    c, m = leadsheet.parse_leadsheet(file)
    lslen = leadsheet.get_leadsheet_length(c, m)
    divwidth = int(split) * (constants.WHOLE // constants.RESOLUTION_SCALAR)
    slices = [
        leadsheet.slice_leadsheet(c, m, s, s + divwidth)
        for s in range(0, lslen, divwidth)
    ]
    if output is None:
        output = file + "-split"
    for i, (chords, melody) in enumerate(slices):
        leadsheet.write_leadsheet(chords, melody, '{}_{}.ls'.format(output, i))
Esempio n. 7
0
def main(files, output=None, verbose=False):
    melody = []
    chords = []
    for f in files:
        if verbose:
            print(f)
        nc,nm = leadsheet.parse_leadsheet(f, verbose)
        melody.extend(nm)
        chords.extend(nc)
    if output is None:
        output = files[0] + "-cat.ls"
    leadsheet.write_leadsheet(chords, melody, output)
def filter_leadsheets(leadsheets):
    new_leadsheets=[]
    for lsfn in leadsheets:
        print("---- {} ----".format(lsfn))
        c,m = leadsheet.parse_leadsheet(lsfn, verbose=True)
        length = leadsheet.get_leadsheet_length(c,m)
        if length < SEGMENT_LEN:
            print("Leadsheet {} is too short! Skipping...".format(lsfn))
        else:
            new_leadsheets.append(lsfn)
    print("Found {} leadsheets.".format(len(leadsheets)))
    return new_leadsheets
Esempio n. 9
0
def findMaxAndMin():
    maxMidi = 0
    minMidi = float('inf')

    for i in range(FIRSTLEADSHEET, LASTLEADSHEET + 1):
        path = os.path.join(DATADIR, "{:04}.ls".format(i))
        chords, melody = leadsheet.parse_leadsheet(path)
        for note in melody:
            if note[0] > maxMidi:
                maxMidi = note[0]
            if note[0] < minMidi and note[0] is not None:
                minMidi = note[0]

    return maxMidi, minMidi
Esempio n. 10
0
def main():
    trainingData = []
    for i in range(FIRSTLEADSHEET, LASTLEADSHEET + 1):
        path = os.path.join(DATADIR, "{:04}.ls".format(i))
        chords, melody = leadsheet.parse_leadsheet(path)
        currentSequence = []
        for j in range(int(len(chords) / 2)):
            chord = chords[j]
            chordSequence = leadsheet.rotate(chord[1], chord[0])
            currentSequence.append(chordSequence)

        currentSequencePoint = 0
        for j in range(len(melody)):
            if currentSequencePoint >= 96:
                break
            note = melody[j]
            for k in range(note[1]):
                if currentSequencePoint >= 96:
                    break
                if k == 0:
                    attackAndSustain = [1, 0]
                else:
                    attackAndSustain = [0, 1]

                # currentSequence[currentSequencePoint] += midiToOneHot(note[0]) + attackAndSustain
                # if note[0] == None:
                #     midi = 90
                # else:
                #     midi = note[0]
                currentSequence[currentSequencePoint] += midiToOneHot(
                    note[0]) + attackAndSustain
                currentSequencePoint += 1

        trainingData.append(currentSequence)

    # splitTrainingData = []
    # splitLabels = []
    # for i in range(len(trainingData)):
    #     for j in range(0, 192-50):
    #         splitTrainingData.append(trainingData[i][j:j+50])
    #         splitLabels.append(trainingData[i][j+50])

    npTrainingData = np.array(trainingData)
    print(npTrainingData.shape)
    print(npTrainingData[0])
    # npSplitTrainingData = np.array(splitTrainingData)
    # npSplitLabels = np.array(splitLabels)
    np.savez_compressed(SAVEFILE, data=npTrainingData)
Esempio n. 11
0
def get_batch(leadsheets, with_sample=False):
    """
    Get a batch

    leadsheets should be a list of dataset lists of (chord, melody) tuples, or just a dataset list of tuples

    returns: chords, melodies
    """
    if not isinstance(leadsheets[0], list):
        leadsheets = [leadsheets]

    sample_datasets = [
        random.randrange(len(leadsheets)) for _ in range(BATCH_SIZE)
    ]
    sample_fns = [random.choice(leadsheets[i]) for i in sample_datasets]
    loaded_samples = [leadsheet.parse_leadsheet(lsfn) for lsfn in sample_fns]
    sample_lengths = [
        leadsheet.get_leadsheet_length(c, m) for c, m in loaded_samples
    ]

    starts = [(0 if l == SEGMENT_LEN else random.randrange(
        0, l - SEGMENT_LEN, SEGMENT_STEP)) for l in sample_lengths]
    sliced = [
        leadsheet.slice_leadsheet(c, m, s, s + SEGMENT_LEN)
        for (c, m), s in zip(loaded_samples, starts)
    ]

    res = list(zip(*sliced))

    sample_sources = [
        "{}: starting at {} = bar {}".format(
            fn, start,
            start / (constants.WHOLE // constants.RESOLUTION_SCALAR))
        for fn, start in zip(sample_fns, starts)
    ]

    if with_sample:
        return res, sample_sources
    else:
        return res
def load_data(directory=TRAINING_DIR):
	chords = np.array([])
	melodies = np.array([])
	for file in listdir(directory):
		c, m = ls.parse_leadsheet(directory + "/" + file)
		for i in range(len(c)):
			c[i] = np.append(c[i][1], pitchduration_to_circleofthirds(c[i][0] + 60,1)[0]) # deal with the root of the chord
		if len(chords) == 0:
			chords = np.array([c])
		else:
			chords = np.append(chords, [c], axis=0)
		temp_melodies = np.array([])
		for note in m:
			if len(temp_melodies) == 0:
				temp_melodies = np.array(pitchduration_to_circleofthirds(note[0], note[1]))
			else:
				temp_melodies = np.append(temp_melodies, pitchduration_to_circleofthirds(note[0], note[1]), axis=0)
		if len(melodies) == 0:
			melodies = np.array([temp_melodies])
		else:
			melodies = np.append(melodies, [temp_melodies], axis=0)
	return chords, melodies
Esempio n. 13
0
def parseLeadsheets(ldir, verbose=False):
    """
    Parse a directory of leadsheets into a list of chords and melodies.

    Inputs:
        tdir: Path to directory containing leadsheets, i.e. "/transcriptions".
    """
    asserterror_count = 0
    keyerror_count = 0
    bigrest_count = 0
    numParsed = 0
    clist = []
    mlist = []
    poslist = []
    ckeylist = []
    namelist = []
    dlist = []
    splist = []
    alist = []
    mlist_noskip = []
    poslist_noskip = []
    tlist_skip = []
    tlist_noskip = []
    if not ldir.endswith("/"):
        ldir += "/"
    if PITCH_REP == PITCH_MIDI:
        print("PITCH: MIDI")
    elif PITCH_REP == PITCH_INTERVAL:
        print("PITCH: INTERVAL")
    elif PITCH_REP == PITCH_CHORD:
        print("PITCH: CHORD")

    ##################### Get roadmaps to get chords & bricks

    # Clear temp directories
    folder = './temp_leadsheets/'
    for the_file in os.listdir(folder):
        file_path = os.path.join(folder, the_file)
        try:
            if os.path.isfile(file_path):
                os.unlink(file_path)
            #elif os.path.isdir(file_path): shutil.rmtree(file_path)
        except Exception as e:
            print(e)

    # Generate roadmaps in temp directories
    max_length = 0  # For tracking purposes, usually 24 is good
    lowest_note = 200  # For tracking purposes
    highest_note = 0  # For tracking purposes
    roadmaps = roadmap_parser.generateRoadmaps(ldir,
                                               "./temp_leadsheets",
                                               doTranspose=False)

    ##################### Grab chords and durations from roadmaps
    # i (leadsheet index)
    # 0 ident (leadsheet), 1 roadmap for leadsheet
    # 0 ident (roadmap), 1 actual roadmap content
    # 0 blocks list
    # 0 ident (blocks), 1 actual blocks content
    # Chord durations are 480 for 1 measure
    rcdlist = []
    totalbrickdur = 0
    numChords = 0
    numBricks = 0
    possiblepitches = {}
    for j in range(len(roadmaps)):
        bricks = roadmaps[j][1][1][0][1]
        chordsdurs = []
        for brick in bricks:
            chordsdurs_brick = []
            chords = roadmap_parser.chordFinder(brick, durOn=True)
            numChords += len(chords)
            for i in range(len(chords)):
                #try:
                cval = leadsheet.parse_chord(chords[i][0])
                # except KeyError:
                #     print("KeyError at Roadmap ",j)
                #     print(os.listdir(ldir)[j])
                #     return
                dur = int(int(chords[i][1]) / constants.RESOLUTION_SCALAR)
                totalbrickdur += dur
                chordsdurs_brick.append([cval, dur])
            chordsdurs.append(chordsdurs_brick)
        rcdlist.append(chordsdurs)

    #################### Parse features for each leadsheet
    roadmap_counter = -1
    for filename in os.listdir(ldir):
        """
        Parsing strategy:

        Want these features: clist, mlist,poslist,ckeylist,namelist,dlist,splist
        1. clist: chords, 1 per note
        2. mlist: note pitches
        3. poslist: list of (low,high) relative pitch positions
        4. ckeylist: list of pitches in the chord
        5. namelist: list of filenames
        6. dlist: list of durations (or beat positions)
        7. splist: list of starting note tuples (pitch, duration, beat pos, chord key, other dur)
        8. alist: list of attacks

        Parsing strategy:
        1. Parse leadsheet (segmented into 48 timeslots) into c (chord keys and notes), m (notes).
        2. Calculate pos for each m
        3. 
        """
        roadmap_counter += 1
        chordsdurs = rcdlist[roadmap_counter]
        fdir = ldir + filename
        try:

            # Parse leadsheet
            c, m = leadsheet.parse_leadsheet(fdir)

        except KeyError:
            if verbose:
                print("KEY ERROR: " + filename)
            keyerror_count += 1
            continue
        except AssertionError:
            if verbose:
                print("ASSERT ERROR: " + filename)
            asserterror_count += 1
            continue
        try:
            totalnotedur = 0
            for note in m:
                totalnotedur += note[1]
            brick_durcount = 0
            actual_chordsdurs = []
            brick_index = 0
            while brick_durcount <= totalnotedur:
                chordsdurs_brick = chordsdurs[brick_index % len(chordsdurs)]
                brick_index += 1
                actual_chordsdurs_brick = []
                for j in range(len(chordsdurs_brick)):
                    chorddur = chordsdurs_brick[j]
                    brick_dur = int(chorddur[1])
                    brick_c = chorddur[0]
                    if brick_c != c[brick_durcount % len(c)]:
                        continue
                    brick_durcount += brick_dur
                    actual_chordsdurs_brick.append(chorddur)
                actual_chordsdurs.append(actual_chordsdurs_brick)

            # Segment sequences by brick endtimes
            brick_endtimes = []
            timecount = 0
            for chordsdurs_brick in actual_chordsdurs:
                brick_dur = 0
                for chorddur in chordsdurs_brick:
                    brick_dur += int(chorddur[1])
                    pass
                timecount += int(brick_dur)
                brick_endtimes.append(timecount)
                pass
            print("Num bricks: ", len(brick_endtimes))
            print("Last endtime: ", brick_endtimes[-1])
            brick_count = 0  # Tracks brick count across leadsheet

            # Repeat chords until they match the notes for each timestep
            beat_positions = []
            attacks = []
            pitches = []
            pitches_skip = []
            clen = len(c)
            totaldur = 0
            seq_noskip = []
            seq_skip = []
            seqs_noskip = []
            seqs_skip = []
            for note in m:
                #print(str(brick_count) + "     " + str(len(seqs_skip)))
                pitch = note[0] if note[0] != None else MIDI_MAX + 1
                pitch -= MIDI_MIN
                dur = note[1]
                totaldur += dur
                # Save general stats
                beat_positions.append(
                    totaldur %
                    int(constants.WHOLE / constants.RESOLUTION_SCALAR))
                attacks.append(1)
                pitches_skip.append(pitch)
                pitches.append(pitch)

                # Save segmented brick info
                endtime = brick_endtimes[brick_count]
                if totaldur > endtime:
                    # We need to break this note into subparts to fit the bricks
                    # End sequence at brick endtime
                    bp = endtime % int(
                        constants.WHOLE / constants.RESOLUTION_SCALAR)
                    if bp in [11, 17, 23, 29]:
                        print("WUT1", bp)
                    seq_skip.append([
                        pitch, endtime %
                        int(constants.WHOLE / constants.RESOLUTION_SCALAR),
                        totaldur - dur
                    ])
                    seq_noskip.append([pitch, 1, totaldur - dur])
                    for k in range(endtime - (totaldur - dur) - 1):
                        seq_noskip.append([pitch, 0, totaldur - dur + k + 1])
                    # Save sequences and resetm
                    seqs_skip.append(seq_skip)
                    seqs_noskip.append(seq_noskip)
                    if max_length < len(seq_skip):  # and len(seq_skip) < 30:
                        max_length = len(seq_skip)
                    seq_skip = []
                    seq_noskip = []
                    brick_count += 1
                    # Add leftovers
                    bp = (totaldur - endtime) % int(
                        constants.WHOLE / constants.RESOLUTION_SCALAR)
                    if bp in [11, 17, 23, 29]:
                        print("WUT2", bp)
                    seq_skip.append([
                        pitch, (totaldur - endtime) %
                        int(constants.WHOLE / constants.RESOLUTION_SCALAR),
                        endtime
                    ])
                    seq_noskip.append([pitch, 1, endtime])
                    for k in range(totaldur - endtime - 1):
                        seq_noskip.append([pitch, 0, endtime + k + 1])
                    # Update general attacks/pitches
                    for _ in range(endtime - (totaldur - dur) - 1):
                        attacks.append(0)
                        pitches.append(pitch)
                    attacks.append(1)
                    pitches.append(pitch)
                    for _ in range(totaldur - endtime - 1):
                        attacks.append(0)
                        pitches.append(pitch)

                else:
                    # Update sequences as normal
                    bp = totaldur % int(
                        constants.WHOLE / constants.RESOLUTION_SCALAR)
                    if bp in [11, 17, 23, 29]:
                        print("WUT3", bp)
                    seq_skip.append([
                        pitch, totaldur %
                        int(constants.WHOLE / constants.RESOLUTION_SCALAR),
                        totaldur - dur
                    ])
                    seq_noskip.append([pitch, 1, totaldur - dur])
                    for k in range(dur - 1):
                        seq_noskip.append([pitch, 0, totaldur - dur + k + 1])
                    # Update general attacks/pitches
                    for _ in range(dur - 1):
                        attacks.append(0)
                        pitches.append(pitch)

                if totaldur == endtime:
                    # Brick finished: Save current sequences and reset
                    seqs_skip.append(seq_skip)
                    seqs_noskip.append(seq_noskip)
                    if max_length < len(seq_skip):  # and len(seq_skip) < 30:
                        max_length = len(seq_skip)

                    seqdur = 0
                    if len(seq_skip) > 4:
                        prevbeatpos = seq_skip[4][1]
                        for pitch, beatpos, index in seq_skip[4:]:
                            seqdur += (beatpos - prevbeatpos + 48) % 48
                            prevbeatpos = beatpos
                    if len(seq_skip) > 4 and seqdur < 48 * 4:
                        for pitch, beatpos, index in seq_skip:
                            note = [pitch]
                            if note[0] != MIDI_MAX - MIDI_MIN + 1 and note[
                                    0] < lowest_note:
                                lowest_note = note[0]
                            if note[0] != MIDI_MAX - MIDI_MIN + 1 and note[
                                    0] > highest_note:
                                highest_note = note[0]

                    seq_skip = []
                    seq_noskip = []
                    brick_count += 1

            for i in range(totaldur - clen):
                c.append(c[i % clen])
            print("Last index: ", len(c))
            sps = []
            for i in range(4):
                note = m[i]
                noteval = MIDI_MAX + 1 - MIDI_MIN if note[
                    0] == None else note[0] - MIDI_MIN
                dur = note[1]
                spi = [noteval, beat_positions[i], dur, c[i][0], dur]
                if beat_positions[i] in [11, 17, 23, 29]:
                    print("WUT", beat_positions[i])
                sps.append(spi)

            # Transpose everything
            newc = []
            newpitches_skip = []
            newp_skip = []
            newckeys = []
            newfilenames = []
            newbeats = []
            newsps = []
            newattacks = []
            newpitches = []
            newp = []
            transposed_seqs_skip = []
            transposed_seqs_noskip = []
            for keydiff in range(12):
                holder = []
                for i in range(len(seqs_skip)):
                    seq_skip = copy.deepcopy(seqs_skip[i])
                    for j in range(len(seq_skip)):
                        note = seq_skip[j][0]
                        if note != MIDI_MAX - MIDI_MIN + 1:
                            seq_skip[j][0] = (note + keydiff if
                                              (note + keydiff <= MIDI_MAX -
                                               MIDI_MIN) else note + keydiff -
                                              12)
                        #if keydiff == 1:
                        if keydiff < 6:
                            if note not in possiblepitches.keys():
                                possiblepitches[note] = 0
                            possiblepitches[note] += 1
                    holder.append(seq_skip)
                transposed_seqs_skip.append(holder)
                holder = []
                for i in range(len(seqs_noskip)):
                    seq_noskip = copy.deepcopy(seqs_noskip[i])
                    for j in range(len(seq_noskip)):
                        note = seq_noskip[j][0]
                        if note != MIDI_MAX - MIDI_MIN + 1:
                            seq_noskip[j][0] = (note + keydiff if
                                                (note + keydiff <= MIDI_MAX -
                                                 MIDI_MIN) else note +
                                                keydiff - 12)
                    holder.append(seq_noskip)
                transposed_seqs_noskip.append(holder)
                newctemp = [((x[0] + keydiff) % 12, x[1]) for x in c]
                newc.append(newctemp)
                newckeys.append([ctuple[0] for ctuple in newctemp])
                newfilenames.append(filename)
                newbeats.append(beat_positions)
                newattacks.append(attacks)
                newpitches_skiptemp = [
                    ((note + keydiff if
                      (note + keydiff <= MIDI_MAX - MIDI_MIN) else note +
                      keydiff -
                      12) if note != MIDI_MAX - MIDI_MIN + 1 else note)
                    for note in pitches_skip
                ]
                newpitchestemp = [
                    ((note + keydiff if
                      (note + keydiff <= MIDI_MAX - MIDI_MIN) else note +
                      keydiff -
                      12) if note != MIDI_MAX - MIDI_MIN + 1 else note)
                    for note in pitches
                ]
                newpitches_skip.append(newpitches_skiptemp)
                newpitches.append(newpitchestemp)
                newp_skip.append([
                    ((0.0, 0.0) if (note == MIDI_MAX - MIDI_MIN + 1) else
                     (float(note / float(MIDI_MAX - MIDI_MIN)),
                      1.0 - float(note / float(MIDI_MAX - MIDI_MIN))))
                    for note in newpitches_skiptemp
                ])
                newp.append([((0.0, 0.0) if
                              (note == MIDI_MAX - MIDI_MIN + 1) else
                              (float(note / float(MIDI_MAX - MIDI_MIN)),
                               1.0 - float(note / float(MIDI_MAX - MIDI_MIN))))
                             for note in newpitchestemp])

                newspstemp = []
                for i in range(4):
                    newsp = sps[i]
                    if newsp[0] != MIDI_MAX - MIDI_MIN + 1:
                        newsp[0] = sps[i][0] + keydiff if (
                            sps[i][0] + keydiff <= MIDI_MAX -
                            MIDI_MIN) else sps[i][0] + keydiff - 12
                    newsp[3] = (sps[i][3] + keydiff) % 12
                    newspstemp.append(newsp)
                newsps.append(newspstemp)
            clist.append(newc)
            mlist.append(newpitches_skip)
            poslist.append(newp_skip)
            ckeylist.append([ctuple[0] for ctuple in newc])
            namelist.append(filename)
            for bp in beat_positions:
                if bp in [11, 17, 23, 29]:
                    print("WUT", bp)
            dlist.append(beat_positions)
            splist.append(newsps)
            alist.append(attacks)
            mlist_noskip.append(newpitches)
            poslist_noskip.append(newp)
            tlist_skip.append(transposed_seqs_skip)
            tlist_noskip.append(transposed_seqs_noskip)
            numParsed += len(seqs_skip)
        except KeyError:
            print(filename)
    if verbose:
        print("Num key errors: " + str(keyerror_count))
        print("Num assert errors: " + str(asserterror_count))
        #print("Num bad base phrases (short, long, error): " + str(bigrest_count))
        print("Num phrases successfully parsed: " + str(numParsed))
        print("Max length: " + str(max_length))
        print("Highest note: " + str(highest_note))
        print("Lowest note: " + str(lowest_note))
        keys = list(possiblepitches.keys())
        keys.sort()
        for key in keys:
            print(key, possiblepitches[key])

    # Thus far, we have parsed the leadsheets from transcriptions. We now parse the leadsheets from ii-V-Is.
    #TODO
    asserterror_count = 0
    keyerror_count = 0
    bigrest_count = 0
    numParsed = 0
    max_length = 0  # For tracking purposes, usually 24 is good
    lowest_note = 200  # For tracking purposes
    highest_note = 0  # For tracking purposes
    possiblepitches = {}
    for filename in os.listdir(iiVIldir):
        fdir = iiVIldir + filename
        try:
            # Parse leadsheet
            c, m = leadsheet.parse_leadsheet(fdir)

        except KeyError:
            if verbose:
                print("KEY ERROR: " + filename)
            keyerror_count += 1
            continue
        except AssertionError:
            if verbose:
                print("ASSERT ERROR: " + filename)
            asserterror_count += 1
            continue
        try:
            # Repeat chords until they match the notes for each timestep
            beat_positions = []
            attacks = []
            pitches = []
            pitches_skip = []
            clen = len(c)
            totaldur = 0
            seq_noskip = []
            seq_skip = []
            seqs_noskip = []
            seqs_skip = []
            for note in m:
                pitch = note[0] if note[0] != None else MIDI_MAX + 1
                pitch -= MIDI_MIN
                dur = note[1]
                totaldur += dur
                # Save general stats
                beat_positions.append(
                    totaldur %
                    int(constants.WHOLE / constants.RESOLUTION_SCALAR))
                attacks.append(1)
                pitches_skip.append(pitch)
                pitches.append(pitch)

                bp = totaldur % int(
                    constants.WHOLE / constants.RESOLUTION_SCALAR)
                if bp in [11, 17, 23, 29]:
                    print("WUT3", bp)
                seq_skip.append([
                    pitch, totaldur %
                    int(constants.WHOLE / constants.RESOLUTION_SCALAR),
                    totaldur - dur
                ])
                seq_noskip.append([pitch, 1, totaldur - dur])
                for k in range(dur - 1):
                    seq_noskip.append([pitch, 0, totaldur - dur + k + 1])
                # Update general attacks/pitches
                for _ in range(dur - 1):
                    attacks.append(0)
                    pitches.append(pitch)

            seqs_skip.append(seq_skip)
            seqs_noskip.append(seq_noskip)
            if max_length < len(seq_skip):  # and len(seq_skip) < 30:
                max_length = len(seq_skip)

            seqdur = 0
            if len(seq_skip) > 4:
                prevbeatpos = seq_skip[4][1]
                for pitch, beatpos, index in seq_skip[4:]:
                    seqdur += (beatpos - prevbeatpos + 48) % 48
                    prevbeatpos = beatpos
            if len(seq_skip) > 4 and seqdur < 48 * 4:
                for pitch, beatpos, index in seq_skip:
                    note = [pitch]
                    if note[0] != MIDI_MAX - MIDI_MIN + 1 and note[
                            0] < lowest_note:
                        lowest_note = note[0]
                    if note[0] != MIDI_MAX - MIDI_MIN + 1 and note[
                            0] > highest_note:
                        highest_note = note[0]

            for i in range(totaldur - clen):
                c.append(c[i % clen])
            print("Last index: ", len(c))
            sps = []
            for i in range(4):
                note = m[i]
                noteval = MIDI_MAX + 1 - MIDI_MIN if note[
                    0] == None else note[0] - MIDI_MIN
                dur = note[1]
                spi = [noteval, beat_positions[i], dur, c[i][0], dur]
                if beat_positions[i] in [11, 17, 23, 29]:
                    print("WUT", beat_positions[i])
                sps.append(spi)

            # Transpose everything
            newc = []
            newpitches_skip = []
            newp_skip = []
            newckeys = []
            newfilenames = []
            newbeats = []
            newsps = []
            newattacks = []
            newpitches = []
            newp = []
            transposed_seqs_skip = []
            transposed_seqs_noskip = []
            for keydiff in range(12):
                holder = []
                for i in range(len(seqs_skip)):
                    seq_skip = copy.deepcopy(seqs_skip[i])
                    for j in range(len(seq_skip)):
                        note = seq_skip[j][0]
                        if note != MIDI_MAX - MIDI_MIN + 1:
                            seq_skip[j][0] = (note + keydiff if
                                              (note + keydiff <= MIDI_MAX -
                                               MIDI_MIN) else note + keydiff -
                                              12)
                        #if keydiff == 1:
                        if keydiff < 6:
                            if note not in possiblepitches.keys():
                                possiblepitches[note] = 0
                            possiblepitches[note] += 1
                    holder.append(seq_skip)
                transposed_seqs_skip.append(holder)
                holder = []
                for i in range(len(seqs_noskip)):
                    seq_noskip = copy.deepcopy(seqs_noskip[i])
                    for j in range(len(seq_noskip)):
                        note = seq_noskip[j][0]
                        if note != MIDI_MAX - MIDI_MIN + 1:
                            seq_noskip[j][0] = (note + keydiff if
                                                (note + keydiff <= MIDI_MAX -
                                                 MIDI_MIN) else note +
                                                keydiff - 12)
                    holder.append(seq_noskip)
                transposed_seqs_noskip.append(holder)
                newctemp = [((x[0] + keydiff) % 12, x[1]) for x in c]
                newc.append(newctemp)
                newckeys.append([ctuple[0] for ctuple in newctemp])
                newfilenames.append(filename)
                newbeats.append(beat_positions)
                newattacks.append(attacks)
                newpitches_skiptemp = [
                    ((note + keydiff if
                      (note + keydiff <= MIDI_MAX - MIDI_MIN) else note +
                      keydiff -
                      12) if note != MIDI_MAX - MIDI_MIN + 1 else note)
                    for note in pitches_skip
                ]
                newpitchestemp = [
                    ((note + keydiff if
                      (note + keydiff <= MIDI_MAX - MIDI_MIN) else note +
                      keydiff -
                      12) if note != MIDI_MAX - MIDI_MIN + 1 else note)
                    for note in pitches
                ]
                newpitches_skip.append(newpitches_skiptemp)
                newpitches.append(newpitchestemp)
                newp_skip.append([
                    ((0.0, 0.0) if (note == MIDI_MAX - MIDI_MIN + 1) else
                     (float(note / float(MIDI_MAX - MIDI_MIN)),
                      1.0 - float(note / float(MIDI_MAX - MIDI_MIN))))
                    for note in newpitches_skiptemp
                ])
                newp.append([((0.0, 0.0) if
                              (note == MIDI_MAX - MIDI_MIN + 1) else
                              (float(note / float(MIDI_MAX - MIDI_MIN)),
                               1.0 - float(note / float(MIDI_MAX - MIDI_MIN))))
                             for note in newpitchestemp])

                newspstemp = []
                for i in range(4):
                    newsp = sps[i]
                    if newsp[0] != MIDI_MAX - MIDI_MIN + 1:
                        newsp[0] = sps[i][0] + keydiff if (
                            sps[i][0] + keydiff <= MIDI_MAX -
                            MIDI_MIN) else sps[i][0] + keydiff - 12
                    newsp[3] = (sps[i][3] + keydiff) % 12
                    newspstemp.append(newsp)
                newsps.append(newspstemp)
            clist.append(newc)
            mlist.append(newpitches_skip)
            poslist.append(newp_skip)
            ckeylist.append([ctuple[0] for ctuple in newc])
            namelist.append(filename)
            for bp in beat_positions:
                if bp in [11, 17, 23, 29]:
                    print("WUT", bp)
            dlist.append(beat_positions)
            splist.append(newsps)
            alist.append(attacks)
            mlist_noskip.append(newpitches)
            poslist_noskip.append(newp)
            tlist_skip.append(transposed_seqs_skip)
            tlist_noskip.append(transposed_seqs_noskip)
            numParsed += len(seqs_skip)
        except KeyError:
            print(filename)

    if verbose:
        print("Num key errors: " + str(keyerror_count))
        print("Num assert errors: " + str(asserterror_count))
        #print("Num bad base phrases (short, long, error): " + str(bigrest_count))
        print("Num phrases successfully parsed: " + str(numParsed))
        print("Max length: " + str(max_length))
        print("Highest note: " + str(highest_note))
        print("Lowest note: " + str(lowest_note))
        keys = list(possiblepitches.keys())
        keys.sort()
        for key in keys:
            print(key, possiblepitches[key])

    return {
        "full_chords": clist,
        "pitches_skip": mlist,
        "pos_skip": poslist,
        "chord_keys": ckeylist,
        "namelist": namelist,
        "durs": dlist,
        "starts": splist,
        "attacks": alist,
        "pitches_noskip": mlist_noskip,
        "pos_noskip": poslist_noskip,
        "transposed_seqs_skip": tlist_skip,
        "transposed_seqs_noskip": tlist_noskip
    }
Esempio n. 14
0
def parseLeadsheets(ldir, verbose=False):
    """
    Parse a directory of leadsheets into a list of chords and melodies.

    Inputs:
        tdir: Path to directory containing leadsheets, i.e. "/transcriptions".
    """
    asserterror_count = 0
    keyerror_count = 0
    bigrest_count = 0
    numParsed = 0
    clist = []
    mlist = []
    poslist = []
    ckeylist = []
    namelist = []
    if not ldir.endswith("/"):
        ldir += "/"
    if PITCH_REP == PITCH_MIDI:
        print("PITCH: MIDI")
    elif PITCH_REP == PITCH_INTERVAL:
        print("PITCH: INTERVAL")
    elif PITCH_REP == PITCH_CHORD:
        print("PITCH: CHORD")

    for filename in os.listdir(ldir):
        fdir = ldir + filename
        try:
            c, m = leadsheet.parse_leadsheet(fdir)
            mseq = []
            pseq = []
            cseq = []
            index_count = 0
            valid_leadsheet = True
            slot = 0
            if PITCH_REP == PITCH_MIDI:
                for note in m:
                    cseq.append(
                        c[index_count][0])  # get chord key for the slot
                    index_count += 1
                    if note[0] != None:
                        assert note[0] >= MIDI_MIN
                    restVal = MIDI_MAX + 1
                    isRest = note[0] == None
                    nval = restVal if isRest else note[0]
                    if isRest and note[1] > 12 or note[1] > 24:
                        valid_leadsheet = False
                        break
                    actNoteVal = nval - MIDI_MIN  # scale down to start at 0
                    pval_low = 0.0 if isRest else float(actNoteVal) / float(
                        MIDI_MAX - MIDI_MIN)
                    pval_high = 0.0 if isRest else 1 - pval_low
                    pseq.append((pval_high, pval_low))
                    mseq.append((actNoteVal, 0))  # attack new note
                    for _ in range(note[1] - 1):
                        pseq.append((pval_high, pval_low))
                        mseq.append(
                            (actNoteVal, 1))  # sustain for rest of duration
                        cseq.append(c[index_count][0])
                        index_count += 1
                    if index_count >= SEQ_LEN:
                        break
            elif PITCH_REP == PITCH_INTERVAL:
                isStart = True
                for note in m:
                    if isStart and note[0] != None:
                        prevVal = note[0] - 1
                        isStart = False
                    cseq.append(
                        c[index_count][0])  # get chord key for the slot
                    index_count += 1
                    restVal = MAX_INTERV + 1
                    isRest = note[0] == None
                    nval = restVal if isRest else note[0] - prevVal
                    nval = nval - MIN_INTERV
                    prevVal = prevVal if isRest else note[0]
                    if isRest and note[1] > 12 or note[1] > 24:
                        valid_leadsheet = False
                        break
                    midival = MIDI_MAX + 1 if isRest else note[0]
                    pval_low = 0.0 if isRest else float(
                        midival - MIDI_MIN) / float(MIDI_MAX - MIDI_MIN)
                    pval_high = 0.0 if isRest else 1 - pval_low
                    pseq.append((pval_high, pval_low))
                    mseq.append((nval, 0))
                    for _ in range(note[1] - 1):
                        pseq.append((pval_high, pval_low))
                        mseq.append((0 - MIN_INTERV, 1))  #sustain
                        cseq.append(c[index_count][0])
                        index_count += 1
                    if index_count >= SEQ_LEN:
                        break
            elif PITCH_REP == PITCH_CHORD:
                for note in m:
                    ckey = c[index_count][0]
                    cseq.append(ckey)  # get chord key for the slot
                    index_count += 1
                    restVal = 12  # pitches go 0-11
                    isRest = note[0] == None
                    nval = restVal if isRest else (note[0] - ckey) % 12
                    if isRest and note[1] > 12 or note[1] > 24:
                        valid_leadsheet = False
                        break
                    midival = MIDI_MAX + 1 if isRest else note[0]
                    pval_low = 0.0 if isRest else float(
                        midival - MIDI_MIN) / float(MIDI_MAX - MIDI_MIN)
                    pval_high = 0.0 if isRest else 1 - pval_low
                    pseq.append((pval_high, pval_low))
                    mseq.append((nval, 0))
                    for _ in range(note[1] - 1):
                        pseq.append((pval_high, pval_low))
                        mseq.append((nval, 1))
                        cseq.append(c[index_count][0])
                        index_count += 1
                    if index_count >= SEQ_LEN:
                        break

            if not valid_leadsheet:
                bigrest_count += 1
                continue
            numParsed += 1
            clist.append(c)
            mlist.append(mseq)
            poslist.append(pseq)
            ckeylist.append(cseq)
            namelist.append(filename)
        except KeyError:
            if verbose:
                print("KEY ERROR: " + filename)
            keyerror_count += 1
        except AssertionError:
            if verbose:
                print("ASSERT ERROR: " + filename)
            asserterror_count += 1
    if verbose:
        print("Num key errors: " + str(keyerror_count))
        print("Num assert errors: " + str(asserterror_count))
        print("Num leadsheets with too big rests: " + str(bigrest_count))
        print("Num leadsheets successfully parsed: " + str(numParsed))
    return [clist, mlist, poslist, ckeylist, namelist]
Esempio n. 15
0
def main(modeltype, batch_size, iterations, learning_rate, segment_len, segment_step, train_save_params, dataset=["dataset"], outputdir="output", validation=None, validation_generate_ct=1, resume=None, resume_auto=False, check_nan=False, generate=False, generate_over=None, auto_connectome_keys=None, **model_kwargs):
    generate = generate or (generate_over is not None)
    should_setup = not generate
    unroll_batch_num = None if generate else training.BATCH_SIZE

    for dataset_dir in dataset:
        if os.path.samefile(dataset_dir,outputdir):
            print("WARNING: Directory {} passed as both dataset and output directory!".format(outputdir))
            print("This may cause problems by adding generated samples to the dataset directory.")
            while True:
                result = input("Continue anyway? (y/n)")
                if result == "y":
                    break
                elif result == "n":
                    sys.exit(0)
                else:
                    print("Please type y or n")

    if generate_over is None:
        training.set_params(batch_size, segment_step, segment_len)
        leadsheets = [training.filter_leadsheets(training.find_leadsheets(d)) for d in dataset]
    else:
        # Don't bother loading leadsheets, we don't need them
        leadsheets = []

    if validation is not None:
        validation_leadsheets = training.filter_leadsheets(training.find_leadsheets(validation))
    else:
        validation_leadsheets = None

    m = builders[modeltype].build(should_setup, check_nan, unroll_batch_num, **model_kwargs)
    m.set_learning_rate(learning_rate)

    if resume_auto:
        paramfile = os.path.join(outputdir,'final_params.p')
        if os.path.isfile(paramfile):
            with open(os.path.join(outputdir,'data.csv'), 'r') as f:
                for line in f:
                    pass
                lastline = line
                start_idx = lastline.split(',')[0]
            print("Automatically resuming from {} after iteration {}.".format(paramfile, start_idx))
            resume = (start_idx, paramfile)
        else:
            print("Didn't find anything to resume. Starting from the beginning...")

    if resume is not None:
        start_idx, paramfile = resume
        start_idx = int(start_idx)
        m.params = pickle.load( open(paramfile, "rb" ) )
    else:
        start_idx = 0

    if not os.path.exists(outputdir):
        os.makedirs(outputdir)

    if generate:
        print("Setting up generation")
        m.setup_produce()
        print("Starting to generate")
        start_time = time.process_time()
        if generate_over is not None:
            source, divwidth = generate_over
            if divwidth == 'full':
                divwidth = 0
            elif divwidth == 'debug_firststep':
                divwidth = -1
            elif len(divwidth)>3 and divwidth[-3:] == 'bar':
                divwidth = int(divwidth[:-3])*(constants.WHOLE//constants.RESOLUTION_SCALAR)
            else:
                divwidth = int(divwidth)
            ch,mel = leadsheet.parse_leadsheet(source)
            lslen = leadsheet.get_leadsheet_length(ch,mel)
            if divwidth == 0:
                batch = ([ch],[mel]), [source]
            elif divwidth == -1:
                slices = [leadsheet.slice_leadsheet(ch,mel,0,1)]
                batch = list(zip(*slices)), [source]
            else:
                slices = [leadsheet.slice_leadsheet(ch,mel,s,s+divwidth) for s in range(0,lslen,divwidth)]
                batch = list(zip(*slices)), [source]
            training.generate(m, leadsheets, os.path.join(outputdir, "generated"), with_vis=True, batch=batch)
        else:
            training.generate(m, leadsheets, os.path.join(outputdir, "generated"), with_vis=True)
        end_time = time.process_time()
        print("Generation took {} seconds.".format(end_time-start_time))
    else:
        training.train(m, leadsheets, iterations, outputdir, start_idx, train_save_params, validation_leadsheets=validation_leadsheets, validation_generate_ct=validation_generate_ct, auto_connectome_keys=auto_connectome_keys)
        pickle.dump( m.params, open( os.path.join(outputdir, "final_params.p"), "wb" ) )