def removeDuplicateTimeSigs(partToAdjust: stream.Part): currentTS = 'FAKE' timeSignatures = partToAdjust.recurse().getElementsByClass('TimeSignature') for ts in timeSignatures: if ts.ratioString == currentTS: partToAdjust.remove(ts, recurse=True) else: currentTS = ts.ratioString return partToAdjust
def CompileSong(ClassifiedStream=None, FileName=str(), ClosestApprox=True, UpperApprox=False, Split=False): if ClosestApprox and UpperApprox: #closest approximation is preferred if both are active UpperApprox = False #turning off upper semiton approximation if not ClosestApprox and not UpperApprox: #ensuring there is an approximation method ClosestApprox = True #default approximation method UpperSemitone =\ { 'C-': 'C', 'C': 'C', 'C#': 'D', 'D-': 'D', 'D': 'D', 'D#': 'E', 'E-': 'E', 'E': 'E', 'E#': 'F', 'F-': 'F', 'F' : 'F', 'F#': 'G', 'G-': 'G', 'G': 'G', 'G#': 'A', 'A-': 'A', 'A': 'A', 'A#': 'B', 'B-': 'B', 'B': 'B', 'B#': 'C', } #upper approximation map ClosestSemitone =\ { 'C-': 'C', 'C': 'C', 'C#': 'C', 'D-': 'D', 'D': 'D', 'D#': 'D', 'E-': 'E', 'E': 'E', 'E#': 'E', 'F-': 'F', 'F' : 'F', 'F#': 'F', 'G-': 'G', 'G': 'G', 'G#': 'G', 'A-': 'A', 'A': 'A', 'A#': 'A', 'B-': 'B', 'B': 'B', 'B#': 'B', } #clostest approximation map for Part in ClassifiedStream: #for loop for every part for Element in Part[:]: #for loop for every element if Element[ 'Type'] == 'Part': #checking if the element is a stream part Part.remove(Element) elif Element['Type'] == 'Key': #checking if the element is key Element['Extra'] = str( Element['Extra'].tonic.name + ' ' + Element['Extra'].mode) #turning key to string elif Element['Type'] == 'Note': #checking if the element is a note if ClosestApprox: #checking the approximation method Element['Sound'] = ClosestSemitone[ Element['Sound']] #remapping the sound elif UpperApprox: #checking the approximation method Element['Sound'] = UpperSemitone[ Element['Sound']] #remapping the sound elif Element['Type'] == 'Chord': #checkinf the element is a chord if ClosestApprox: #checking the approximation method Element['Sound'] = [ ClosestSemitone[Note] for Note in Element['Sound'] ] #remapping the sound elif UpperApprox: #checking the approximation method Element['Sound'] = [ UpperSemitone[Note] for Note in Element['Sound'] ] #remapping the sound if Split: #check if the user wants to split tracks Tracks = [i for i in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'] #name for subtracks if len(Tracks) > len( ClassifiedStream): #check what element has more tracks for i in range(len(ClassifiedStream) ): #for loop for every track in the MIDI file FilePart = f'MappedSongs/{FileName}[{Tracks[i]}].cmid' #new name of the file Part = [ClassifiedStream[i]] #list of single part of MIDI file with open(FilePart, 'wb') as OutputFile: #creating a compiled file Data = Dumps(Part, protocol=HighestProtocol) #serializing data OutputFile.write(Data) #writing data to the file else: for i in range( len(Tracks) ): #for loop for every track in the MIDI file (will cut all the tracks next to 26) FilePart = f'MappedSongs/{FileName}[{Tracks[i]}].cmid' #new name of the file Part = [ClassifiedStream[i]] #list of single part of MIDI file with open(FilePArt, 'wb') as OutputFile: #creating a compiled file Data = Dumps(Part, protocol=HighestProtocol) #serializing data OutputFile.write(Data) #writing data to the file else: FileName = f'MappedSongs/{FileName}.cmid' #completed file name + path with open(FileName, 'wb') as OutputFile: #creating a compiled file Data = Dumps(ClassifiedStream, protocol=HighestProtocol) #serializing data OutputFile.write(Data) #writing data to the file