def transformToEnding(motif, cord = [0,2,4], cord2 = [4,6,8], true_end = False):
    if type(motif) is list:     #because of a bug which was causing motif to be wrapped in a list itself
        motif = motif[0]
    #keep the same first half
    first_half_durs = []
    first_half_pitches = []
    first_half_durs.extend(motif.l1d[0])
    first_half_pitches.extend(motif.l1p[0])
    if sum(first_half_durs) < 2.0:
        first_half_durs.extend(motif.l1d[1])
        first_half_pitches.extend(motif.l1p[1])
    if true_end: #if this is the end of a major movement, need a half note of the tonic 
        first_half_durs.append(2.0)
        first_half_pitches.append(pth.getClosestPCDegree(first_half_pitches[-1], 0))
        return Motif(first_half_pitches, first_half_durs)
    else:
        what_end = random.uniform(0,1)
        #end with either a quarter note quarter rest, quarter note eighth rest eighth note, or half note
        if what_end < 0.3:
            first_half_durs.extend([1.0,-1.0])
            first_half_pitches.extend([sc.closestNoteDegreeInChord(first_half_pitches[-1], cord), -1])
            #rest, beat
        elif what_end < 0.7:
            #quarternote, eight rest, eighth note
            first_half_durs.extend([1.0,-0.5, 0.5])
            first_half_pitches.extend([sc.closestNoteDegreeInChord(first_half_pitches[-1], cord), -1, sc.closestNoteDegreeInChord(first_half_pitches[-1], cord2)])
        else:
            #half note
            first_half_durs.extend([2.0])
            first_half_pitches.append(sc.closestNoteDegreeInChord(first_half_pitches[-1], cord))
    return Motif(first_half_pitches, first_half_durs)
def genCounter(main_passage, prev_note = 0):
    new_cells = []
    for main_cell in main_passage.cells: #loop through main cells
        if main_cell.chord == None or main_cell.chord == []:
            new_pits = []
            for pit in main_cell.pits:
                new_pits.append(pth.getClosestPCDegree(prev_note, pit, low = -5, high = 14))
                prev_note = new_pits[-1]
            new_cells.append(Chunk(pits = new_pits, durs = main_cell.durs, key=main_cell.key))
        else:
            durs = []
            pits = []

            #use random number to choose what durs
            ran = random.uniform(0,1)
            if ran < 0.2:
                durs = [1.0,1.0]
            elif ran < 0.5:
                durs = [1.5,0.5]
            else:
                durs = [2.0]

            for i in range(0, len(durs)):
                pits.append(sc.closestNoteDegreeInChord(prev_note, main_cell.chord, same=False, low = -3, high = 14))
                prev_note = pits[-1]
            new_cells.append(Chunk(pits=pits, durs=durs, key = main_cell.key, chord=main_cell.chord))
    return new_cells
def genBass(main_passage, low = -4, high = 7):
    prev_note = 4
    main_cells = main_passage.cells
    bass_cells = []
    for main_cell in main_cells:
        if main_cell.chord == [] or main_cell.chord == None:
            bass_cells.append(gc.genBlankCell(2.0))
            prev_note = 4
        else:
            main_pits = main_cell.beat_pits
            pits = []
            pits.append(pth.getClosestPCDegree(prev_note, main_pits[0][0], low = low, high = high))


            if len(main_pits) == 2:
                if hm.inChord(main_pits[1][0], main_cell.chord):
                    pits.append(sc.closestNoteDegreeInChord(note=pits[-1], chord=main_cell.chord, same=False, low = low, high = high))
                    durs = [1.0,1.0]
                    bass_cells.append(Chunk(pits = pits, durs=durs, chord=main_cell.chord, key = main_cell.key))
                else:
                    durs = [2.0]
                    bass_cells.append(Chunk(pits = pits, durs = durs, chord=main_cell.chord, key = main_cell.key))
            else: #if it's a 1.5, 0.5 or 1.5, 0.25,0.25
                durs = [2.0]
                bass_cells.append(Chunk(pits = pits, durs = durs, chord=main_cell.chord, key = main_cell.key))
            prev_note = pits[-1]
    return bass_cells
def genEnding(prev_note, chord = [0,2,4], authentic = True, elided = False, real_end = False):
    if real_end:
        return Chunk(pits=[pth.getClosestPCDegree(prev_note, 0)], durs=[2.0])
    dur = random.choice([0,1, 2,3,4]) if elided else random.choice([0,3,4])
    durs = []
    pitches = []
    if chord == [0,2,4]:
        if authentic:
            last_note = 0
        else:
            last_note = sc.closestNoteDegreeInChord(note = prev_note, chord=[2,4])
    else:
        last_note = random.choice([4,8])
    if dur == 0:
        durs = [0.5,0.5,1.0]
        if prev_note - pth.getClosestPCDegree(prev_note, last_note) == 0:
            pitches = random.choice([[prev_note - 1, prev_note + 1, prev_note], [prev_note + 1, prev_note - 1, prev_note]])
        elif pth.getClosestPCDegree(prev_note, last_note) - prev_note == 1:
            pitches = [prev_note + 1, prev_note + 2, prev_note + 1]
        elif pth.getClosestPCDegree(prev_note, last_note) - prev_note == -1:
            pitches = [prev_note - 1, prev_note - 2, prev_note - 1]
        else:
            pitches = [sc.closestNoteDegreeInChord(prev_note, chord, False)]
            pitches.append(sc.closestNoteDegreeInChord(pth.getClosestPCDegree(prev_note, last_note), chord, False))
            pitches.append(pth.getClosestPCDegree(prev_note, last_note))
    elif dur == 1:
        durs = [1.0,1.0]
        pitches = [pth.getClosestPCDegree(prev_note, last_note)]
        pitches.append(random.randint(3,7))
    elif dur == 2:
        durs = [1.0, -0.5, 0.5]
        pitches = [pth.getClosestPCDegree(prev_note, last_note)]
        pitches.append(-36)
        pitches.append(random.randint(3,7))
    elif dur == 3:
        durs = [1.0, -1.0]
        pitches = [pth.getClosestPCDegree(prev_note, last_note), -36]
    elif dur == 4:
        durs = [2.0]
        pitches = [pth.getClosestPCDegree(prev_note, last_note)]
    return Chunk(pitches, durs)
def genAlbertiEighths(main_cells, leading_eighths = True):
    prev_note = 0
    cells = []
    for k in range(0, len(main_cells)): #loop through all cells
        main_cell = main_cells[k]
        if main_cell.chord == None or main_cell.chord == []:
            if leading_eighths == False: #if we are coming to a close
                new_pits = []
                for pit in main_cell.pits:
                    new_pits.append(pth.getClosestPCDegree(prev_note, pit, low = -5, high = 14))
                    prev_note = new_pits[-1]
                cells.append(Chunk(pits = new_pits, durs = main_cell.durs, key=main_cell.key))
            else: #if we want eighths
                main_pitches = main_cell.pits
                main_durs = main_cell.durs
                pits = []
                tot_durs = [sum(main_durs[:i]) for i in range(0, len(main_durs))]
                eighths = []
                for i in range(0, 4):
                    found = False
                    for j in range(0, len(tot_durs)):
                        if tot_durs[j] == i/2.0:
                            eighths.append(main_pitches[j])
                            found = True
                    if found == False:
                        eighths.append(None)
                if eighths[1] == None and eighths[2] == None and eighths[3] == None:
                    if main_pitches[0] % 7 == 1 or main_pitches[0] % 7 == 6: #if we're dealing with a dominant chord
                        first_note = (pth.getClosestPC(prev_note, 4))
                    else:
                        first_note = (pth.getClosestPC(prev_note, 0))
                    pat = random.choice([[0,-1,-2,-3], [0,-1,-2,-1]])
                    pits = [first_note + i for i in pat]
                else:
                    if hm.matches(eighths[0], 0):
                        pits.append(pth.getClosestPCDegree(prev_note, 0))
                    elif hm.matches(eighths[0], 4):
                        pits.append(pth.getClosestPCDegree(prev_note, 7))
                    else:
                        print('error')
                    prev_note = pits[-1]
                    for note in eighths[1:]: #run through all of the possibilities of the notes
                        if hm.inChord(note, [0,2,4]):
                            pits.append(sc.closestNoteDegreeInChord(prev_note, [0,2,4], same=False))
                        elif hm.inChord(note, [4,6,8]):
                            pits.append(sc.closestNoteDegreeInChord(prev_note, [4,8], same=False))
                        elif note == None:
                            pits.append(prev_note + random.choice([-1,1]))
                        else:
                            pits.append(pth.getClosestPCDegree(prev_note, note))
                            prev_note = pits[-1]
                cells.append(Chunk(pits=pits, durs=[0.5,0.5,0.5,0.5], key = main_cell.key))
        else: #if there is a chord
            inversion = False
            chord = main_cell.chord
            if chord == [1,3,5] or chord == [-2,0,2] or chord == [5,7,9]:
                inversion = True
            if k > 0:
                if main_cells[k - 1].chord == [0,2,4] and chord == [0,2,4]:
                    inversion = True
            '''if diff(main_cell.beat_pits[0], chord[1] == octave and diff(cells[-1].pits[-1], main_cells[k].beat_pits[0] == octave:
                inversion = False
            '''
            eighths = getAlbertiEighths(chord, main_cell.pits, main_cell.durs, inversion=inversion)
            #if isDiminished(eighths[0],cells[-1].pits[-1]:
            #   choose different end for cells[-1]
            closest_eighths = []
            for i in range(0, len(eighths)):
                closest_eighths.append(pth.getClosestPC(prev_note, eighths[i]))
                prev_note = closest_eighths[-1]
            cells.append(Chunk(pits = closest_eighths, durs = [0.5,0.5,0.5,0.5], chord=chord, key=main_cell.key))
    return cells
def smoothOut(pitches, durs, leading = True):
    new = [pitches[0]]
    for i in range(1, len(pitches)):
        new.append(pth.getClosestPCDegree(new[i-1], pitches[i]))
    return doubleSmooth(new, durs, leading)