In [448]:
# song = list(open('有一天.txt', 'r').readlines())

def read_song(filename):
    import codecs
    song = codecs.open(filename, 'r', 'utf-8').readlines()
    key = ''
    modifier = ''
    title = None
    arrangement = []
    parts = dict()

    for line in song:
        
        # Parse the title
        if line[0:7] == '>>Title':
            title = line.split(': ')[1].strip('\n')
        
        # Parse the current key of the arrangement
        if line[0:5] == '>>Key':
            current_key = line.split(':')[1].strip('\n').strip(' ').split(';')
            key = current_key[0]
            if len(current_key) > 1:
                modifier = current_key[1]
            else:
                modifier = ''
        # Parse the arrangement
        if line[0:13] == '>>Arrangement':
            arrangement = [part.strip('\n').strip(' ') for part in line.split(': ')[1].split(',')]
        
        # Parse out each part
        if line[0:3] == '>>>':
            part = line[3:].strip('\n')
            parts[part] = dict()
            line_counter = 0
            # This variable checks to make sure that we are parsing the correct part
            part_is_correct = False 
            
            for line2 in song:
                
                # Make sure that the part variable is correct, then we can proceed
                if line2[0:3] == '>>>' and line2[3:].strip('\n') == part:
                    part_is_correct = True
                
                # Grab each chord and its position in the chord progression
                if line2[0:2] == 'C:' and part_is_correct:
                    line_counter += 1
                    parts[part][line_counter] = dict()
                    parts[part][line_counter]['chords'] = dict()
                    chords = [c for c in line2.strip('\n').split(':')[1].split(' ') if c != '']
                    for chord in chords:
                        position = line2[2:].index(chord)
                        parts[part][line_counter]['chords'][position] = chord
                # Grab out the lyrics
                if line2[0:2] == 'L:' and part_is_correct:
                    parts[part][line_counter]['lyrics'] = line2.strip('\n').split(':')[1]
                    
                # End parsing
                if line2[0:3] == '<<<' and part_is_correct:
                    break
                    
                    
    return title, key, modifier, arrangement, parts

In [449]:
def get_transpose_delta(oldkey, newkey):
    keys = ['A', 'Bb', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'Ab']
    old_idx = keys.index(oldkey)
    new_idx = keys.index(newkey)
    
    return (new_idx - old_idx)

def transpose_parts(parts, transpose_delta):
    from copy import deepcopy
    
    transposed_parts = deepcopy(parts)
    for part, lines in transposed_parts.items():
        for line, contents in lines.items():
            for position, chord in contents['chords'].items():
                contents['chords'][position] = get_transposed_chord(chord, transpose_delta)
                
    return transposed_parts

In [454]:
title, key, modifier, arrangement, parts = read_song(u'有一天_input.txt')
# print(transpose_parts(parts, transpose_delta))
print(modifier)




In [471]:
# Prototyped code for output
def write_chords(filename, title, key, modifier, arrangement, parts, new_key):
    
    newkey = new_key.split(';')[0]
    if len(new_key.split(';')) > 1:
        newmodifier = new_key.split(';')[1]
    else:
        newmodifier = ''
    if newmodifier != modifier:
        raise Exception('New key does not have the same modifier as old key.')
    import codecs
    
    with codecs.open(filename, "w+", "utf-8") as f: 
        keys = ['A', 'Bb', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'Ab']
        f.write(u'Title: {0}\n'.format(title))
        f.write(u'Key: {0}{1}\n'.format(newkey, modifier))
        f.write(u'Arrangement: ')
        for part in arrangement:
            f.write('{0} '.format(part))
        f.write('\n\n')

        transpose_delta = get_transpose_delta(key, newkey)
        parts = transpose_parts(parts, transpose_delta)

        for part in arrangement:
            f.write(u'{0}\n'.format(part))
            lines = parts[part]
            for line, contents in lines.items():

                chordstring = ' '
                maxchordpos = max(contents['chords'].keys())
                i = 1
                while i < maxchordpos + 1:
                    if i not in contents['chords'].keys():
                        chordstring += ' '
                        i += 1
                    else:
                        for s in contents['chords'][i].split(';'):
                            chordstring += s
                            i += len(s)
                f.write(u'{0}\n'.format(chordstring))
                f.write(u'{0}\n'.format(contents['lyrics']))
            f.write('\n')

In [472]:
print(title)


有一天

In [473]:
# transpose_delta = get_transpose_delta('A', 'C')
print(write_chords('有一天 Dmaj.txt', title, key, modifier, arrangement, parts, 'D'))


None

In [329]:
# Function for doing chord transposition
def get_transposed_key(current_key, transpose_delta):
    """
    Note: only handles the base key and chord key, no modifiers allowed!
    """
    
    current_idx = keys.index(current_key)
    new_idx = current_idx + transpose_delta
    
    if new_idx >= len(keys):
        new_idx = new_idx % len(keys)
#     print(new_idx)
        
    return keys[new_idx]

In [247]:
# Prototype code for computing transposition
chord_progression = ['D', 'A', 'C;m', 'G;m7', 'G/C']

def get_transposed_chord(current_chord, transpose_delta):
    # Get the base key
    if len(current_chord.split('/')) > 1:
        basekey = current_chord.split('/')[1]
    else:
        basekey = ''

    # Get the chord key
    chordkey = current_chord.split('/')[0].split(';')[0]
    
    # Get any modifiers
    if len(current_chord.split(';')) > 1:
        modifier = current_chord.split(';')[1]
    else:
        modifier = ''
    
    # Transpose the chord key:
    new_chordkey = get_transposed_key(chordkey, transpose_delta)
    
    # Transpose the base key:
    if basekey != '':
        new_basekey = get_transposed_key(basekey, transpose_delta)

        return(new_chordkey + modifier + '/' + new_basekey)
    else:
        return(new_chordkey + modifier)

In [ ]:


In [1]:
from transpose import SheetMusic

In [2]:
sm = SheetMusic()
sm.read_song('有一天_input.txt')
sm.parse_song()
sm.set_new_key('E')
# sm.set_transpose_delta()
# sm.set_transposed_parts()
# print(sm.transposed_parts)
print(sm.arrangement)
sm.write_chords('有一天_output.txt')


[u'Intro', u'Stanza[1]', u'Chorus', u'Stanza[1]', u'Chorus']
Intro
Stanza[1]
Chorus
Stanza[1]
Chorus

In [5]:


In [ ]: