('C#', 1), ('D#', 3), ('F#', 6), ('G#', 8), ('A#', 10), ('C', 0), ('D', 2), ('E', 4), ('F', 5), ('G', 7), ('A', 9), ('B', 11) ] # have to check the sharps first so it doesn't switch 'C#' into 'w0#' fullKeyTable = [[[]]] #outer level: major/melodic minor/harmonic minor #middle level: the twelve "root keys": C, C#, D, D#, etc. #inner level: all the chords within that root key fullKeyTable[0][0] = ["C", "Dm", "Em", "F", "G", "G7", "Am", "Bdim"] #major fullKeyTable.append( [["Cm", "Dm", "D#7", "F", "G", "G7", "Adim", "Bdim"]]) #melodic minor... note D#aug converted to D#7 by our casting fullKeyTable.append([["Cm", "Ddim", "D#7", "Fm", "G", "G7", "G#", "Bdim"]]) #harmonic minor for k in range(0, len(fullKeyTable)): for i in range(1, 12): curKey = [] for j in range(0, len(fullKeyTable[k][0])): tempChord = caster.makeFlatsSharps(fullKeyTable[k][0][j]) curKey.append( caster.shiftNumChord( caster.letterChordToNumChord(tempChord, noteNums), i)) fullKeyTable[k].append(curKey) with open("key_table_UTF-8.txt", "w") as f: for level in fullKeyTable: for key in level: for note in key: note = caster.numChordToLetterChord(note) f.write(note + " "), f.write("\n") print("Finished generating key tables")
#We should append A minor still? #now cast our chords to simplify them #make a new list with the cast of each chord, using the table, and count the amount of each chord castedChords = [] #have to check the sharps first so it doesn't switch 'C#' into 'w0#' noteNums = [('C#', 1), ('D#', 3), ('F#', 6), ('G#', 8), ('A#', 10), ('C', 0), ('D', 2), ('E', 4), ('F', 5), ('G', 7), ('A', 9), ('B', 11)] for origChord in origChords: castedFlag = False #ADDITIONAL CODE FOR CHECKER VERSION #example of process: E/C# -> w4/w1 -> w0/w9 (store shift as 4) -> C/A -> Am -> w9m -> w1m -> C#m #convert origChord to numeral version origChord = caster.makeFlatsSharps(origChord) tempChord = caster.letterChordToNumChord(origChord, noteNums) #shift numeral chord to C numeral version if tempChord[1]=='1' and len(tempChord)>2 and \ (tempChord[2]=='0' or tempChord[2]=='1'): rootNum = int(tempChord[1:3]) else: rootNum = int(tempChord[1]) shift = rootNum tempChord = caster.shiftNumChord(tempChord, -shift) #convert C numeral version to C letter version tempChord = caster.numChordToLetterChord(tempChord) #cast C letter version using table for chord in castingTable: if tempChord == chord[0]: tempChord = chord[1]
def convert(input_file, output_file): #Example input and output files #input_file = "chords_uku_english_only_songmarkers_empty_lines_removed.txt" #output_file = "rns_uku_english_only_songmarkers_empty_lines_removed.txt" #global scope variables noteNums = [ ('C#', 1), ('D#', 3), ('F#', 6), ('G#', 8), ('A#', 10), ('C', 0), ('D', 2), ('E', 4), ('F', 5), ('G', 7), ('A', 9), ('B', 11) ] # have to check the sharps first so it doesn't switch 'C#' into 'w0#' # read in cadence casting table with open('cadence_casting_UTF-8.txt', 'r') as f: inputs = [] outputs = [] exploLine = [] for line in f: exploLine = line.split("\t") exploLine[0] = exploLine[0].replace('\xef\xbb\xbf', '') # clean up special chars inputs.append(exploLine[0].replace( '\\ufeff', '').strip()) # clean up the special chars outputs.append(exploLine[1].replace( '\n', '').strip()) # clean up special chars castingTable = list(zip( inputs, outputs)) # convert casting table to a list of tuples print("Opened Cadence Casting Table") print(castingTable) # test to make sure we've read in the table correctly # read in key tables for finding tonic num keyTable = [] with open('key_table_UTF-8.txt', 'r') as f: curLine = f.readline() while (curLine != ""): keyTable.append(curLine.split()) curLine = f.readline() print(keyTable) # test to make sure we've read table correctly #read in chords from file, song by song #split is by " | | S O N G M A R K E R | |", and it starts with lyrics and the songmarker is AFTER each song with open(input_file, 'r') as f: with open(output_file, 'w') as out: curLine = f.readline() while (curLine != ""): #--STAGE 0: RESET-- origChords = [] numChords = [] tonicNum = 0 songmarker = "" #--STAGE 1: READING SONG-- if (curLine != "\n" and curLine.find("SONG OVER") == -1): while (curLine.find("SONG OVER") == -1 ): #while we're not at the Songmarker lineChords = curLine.split() for chord in lineChords: origChords.append(chord) origChords.append( '\n') #keep output of original file intact curLine = f.readline() songmarker = curLine #make sure we print the songmarker line after each song # now we've hit a songmarker, so let's move on to processing! else: out.write( curLine) #keep the formatting of original file intact #--STAGE 2: PROCESSING-- #only process if there actually are chords in origChords if (len(origChords) > 0): #find tonic chord tonicNum = findTonicNumNo7.findTonicNumNo7( origChords, keyTable) #convert all chords in song to number chords for origChord in origChords: origChord = caster.makeFlatsSharps(origChord) # shift numeral chord to relative to C (w0) numChords.append( caster.shiftNumChord( caster.letterChordToNumChord( origChord, noteNums), -tonicNum)) #cast to correct interval based on semitones #we convert each chord to its interval notation (e.g. V, vi, I, etc.) for i in range(0, len(numChords)): for chord in castingTable: if numChords[i] == chord[0]: numChords[i] = chord[1] break #break out of inner loop #print for numChord in numChords: out.write(numChord) if numChord != '\n': out.write(" ") out.write(songmarker) curLine = f.readline()