victor@2: ''' victor@2: Created on 10/11/2014 victor@2: victor@2: @organization: Lancaster University & University of Leeds victor@2: @version: 1.0 victor@2: Created on 11/12/2014 victor@2: victor@2: @author: Victor Padilla victor@2: @contact: v.padilla@lancaster.ac.uk victor@2: victor@2: Functions related to convert music21 output victor@2: to symbols for aligning and voting victor@2: ''' victor@2: from music21 import note victor@2: from music21 import chord victor@2: from music21 import meter victor@2: from music21 import key victor@2: from music21 import stream victor@2: from music21 import tie victor@2: from music21 import bar victor@2: from music21 import harmony victor@2: from music21 import clef victor@2: class SymbolConversion: victor@2: victor@2: victor@2: def __getSymbolMesure(self,symbol): victor@2: ''' victor@2: Detects if it is a barline symbol and gets the first element victor@2: ''' victor@2: if isinstance(symbol,list): victor@2: if symbol[0].find('!')!=-1: victor@2: return symbol victor@2: victor@2: def convertM21(self,symbolArray): victor@2: ''' victor@2: Converts one Array of symbols to music21 victor@2: victor@2: usage: victor@2: victor@2: outVote=vote.vote(omr_symbolsAlign) victor@2: #apply voices if it is needed victor@2: victor@2: outVote=sc.setVoices(outVote) victor@2: #convert to music21 victor@2: resultS2=sc.convertM21(outVote) victor@2: victor@2: ''' victor@2: victor@2: sOut=stream.Score() victor@2: sPart=stream.Part() victor@2: measureIndex=1 victor@2: measure=stream.Measure() victor@2: measure.number=measureIndex victor@2: voicesLength=8 victor@2: for v in range(voicesLength): victor@2: voice=stream.Voice() victor@2: voice.id=v victor@2: measure.append(voice) victor@2: indexS=0 victor@2: victor@2: for symbol in symbolArray: victor@2: mytie="" victor@2: realDuration=None victor@2: s=symbol victor@2: victor@2: if isinstance(s,list): victor@2: s=s[0] victor@2: if s.find('TS:')!=-1: victor@2: ts=meter.TimeSignature(s[3:]) victor@2: victor@2: measure.append(ts) victor@2: if s.find('KS:')!=-1: victor@2: k=key.KeySignature(int(s[3:])) victor@2: victor@2: measure.append(k) victor@2: if s.find('CL:')!=-1: victor@2: c=clef.clefFromString(str(s[3:])) victor@2: victor@2: measure.append(c) victor@2: if s.find('N:')!=-1: victor@2: try: victor@2: if isinstance(symbol,list): victor@2: realDuration=symbol[1] victor@2: mytie=symbol[2] victor@2: victor@2: sep=s.index("_") victor@2: duration=s[sep+1:] victor@2: #************************************* victor@2: #duration vs realDuration for triplets victor@2: if realDuration!=None: victor@2: duration=realDuration victor@2: #************************************* victor@2: if(float(duration)>0): victor@2: n=note.Note(s[2:sep],quarterLength=float(duration)) victor@2: if symbol[5]!=None: victor@2: n.color=symbol[5] victor@2: if mytie!="": victor@2: n.tie=tie.Tie(mytie) victor@2: if len(symbol)>6:#voices victor@2: measure.voices[symbol[6]].append(n) victor@2: else: victor@2: measure.append(n) victor@2: except: victor@2: print "error"+s victor@2: victor@2: if s.find('R:')!=-1: victor@2: try: victor@2: if isinstance(symbol,list): victor@2: realDuration=symbol[1] victor@2: mytie=symbol[2] victor@2: duration=s[2:] victor@2: #************************************* victor@2: #duration vs realDuration for triplets victor@2: if realDuration!=None: victor@2: duration=realDuration victor@2: #************************************* victor@2: n=note.Rest(quarterLength=float(duration)) victor@2: if symbol[5]!=None: victor@2: n.color=symbol[5] victor@2: if len(symbol)>6:#voices victor@2: measure.voices[symbol[6]].append(n) victor@2: else: victor@2: measure.append(n) victor@2: except: victor@2: print "error"+s victor@2: victor@2: if s.find('C:')!=-1: victor@2: notes=s.split("[:") victor@2: cPitch=[] victor@2: for n in notes: victor@2: if n!='C:': victor@2: sep=n.index("_") victor@2: duration=n[sep+1:] victor@2: pitch= n[0:sep] victor@2: cPitch.append(pitch) victor@2: c=chord.Chord(cPitch) victor@2: c.duration.quarterLength=float(duration) victor@2: if symbol[5]!=None: victor@2: c.color=symbol[5] victor@2: if mytie!="": victor@2: c.tie=tie.Tie(mytie) victor@2: victor@2: if len(symbol)>6:#voices victor@2: measure.voices[symbol[6]].append(c) victor@2: else: victor@2: measure.append(c) victor@2: victor@2: if s.find('!')!=-1: victor@2: if isinstance(symbol,list): victor@2: barType= symbol[1] victor@2: barRepeat= symbol[2] victor@2: if barType!="": victor@2: try: victor@2: mybartype=bar.styleToMusicXMLBarStyle(barType) victor@2: myBar=bar.Barline(style=mybartype) victor@2: measure.rightBarline=myBar victor@2: except: victor@2: print "error barline" victor@2: victor@2: if barRepeat!="": victor@2: try: victor@2: myBar=bar.Repeat(direction=barRepeat) victor@2: if barRepeat=="start": victor@2: measure.leftBarline=myBar victor@2: if barRepeat=="end": victor@2: measure.rightBarline=myBar victor@2: except: victor@2: print "error barline" victor@2: sPart.append(measure) victor@2: measureIndex+=1 victor@2: measure=stream.Measure() victor@2: measure.number=measureIndex victor@2: for v in range(voicesLength): victor@2: voice=stream.Voice() victor@2: voice.id=v victor@2: measure.append(voice) victor@2: victor@2: indexS+=1 victor@2: victor@2: sOut.append(sPart) victor@2: return sOut victor@2: victor@2: victor@2: victor@2: victor@2: def __orderChord(self,mychord): victor@2: ''' victor@2: Private function that returns a chord ordered victor@2: in a string from lower to higher victor@2: ''' victor@2: midi=[] victor@2: midi2=[] victor@2: orderC=[] victor@2: for n in mychord: victor@2: if isinstance(n,note.Note): victor@2: midi.append(n.midi) victor@2: midi2.append(n.midi) victor@2: victor@2: while len(midi)>0: victor@2: indexMin=midi2.index(min(midi)) victor@2: indexPop=midi.index(min(midi)) victor@2: orderC.append(mychord[indexMin]) victor@2: midi.pop(indexPop) victor@2: victor@2: myOrderChord=chord.Chord(orderC) victor@2: myOrderChord.duration.quarterLength=mychord.duration.quarterLength victor@2: return myOrderChord victor@2: victor@2: victor@2: def __getKeyOffset(self,item): victor@2: ''' victor@2: Private function that returns the offset of one item victor@2: ''' victor@2: return item['offset'] victor@2: victor@2: def __removeDuplicates(self,input_raw): victor@2: ''' victor@2: Private function to remove duplicates in the string input victor@2: ''' victor@2: seen = set() victor@2: new_l = [] victor@2: for d in input_raw: victor@2: t = tuple(d.items()) victor@2: if t not in seen: victor@2: seen.add(t) victor@2: new_l.append(d) victor@2: victor@2: return new_l victor@2: victor@2: victor@2: def getElementsFromMeasureOrderByOffset(self,measure): victor@2: ''' victor@2: Returns the symbols of a measure ordered by offset victor@2: ''' victor@2: offset=measure.flat.offsetMap victor@2: offset_n=self.__removeDuplicates(offset) victor@2: sorted_offset=sorted(offset_n,key=self.__getKeyOffset) victor@2: return sorted_offset victor@2: victor@2: def __swapSymbols(self,s1,s2): victor@2: ''' victor@2: Swap the s1,s2 symbols victor@2: ''' victor@2: inter=s1 victor@2: s1=s2 victor@2: s2=inter victor@2: return s1,s2 victor@2: victor@2: def orderSymbolsByPitch(self,symbols): victor@2: ''' victor@2: Orders the symbol string from lower to high if they have victor@2: the same offset victor@2: ''' victor@2: for i in range(len(symbols)-1): victor@2: for j in range(i,i+2): victor@2: pitch_i=0 victor@2: pitch_j=0 victor@2: if(symbols[i]['offset']==symbols[j]['offset']): victor@2: if isinstance(symbols[i]['element'],note.Note): victor@2: pitch_i=symbols[i]['element'].pitch.midi victor@2: if isinstance(symbols[j]['element'],note.Note): victor@2: pitch_j=symbols[j]['element'].pitch.midi victor@2: victor@2: if pitch_j>pitch_i:#higher pitch first victor@2: symbols[i],symbols[j]=self.__swapSymbols(symbols[i],symbols[j]) victor@2: victor@2: if pitch_j==pitch_i and pitch_j>0:#longest first if equal pitch victor@2: if symbols[i]['element'].duration, 'endTime': 1.0, 'offset': 0.0} victor@2: s=symbol['element'] victor@2: if 'TimeSignature' in s.classes: victor@2: newMeasure.append(s) victor@2: str0="TS:"+str(s.numerator)+"/"+str(s.denominator) victor@2: omr_symbols.append([str0,None,None,symbol['offset'],symbol['endTime'],None]) victor@2: victor@2: elif 'KeySignature' in s.classes: victor@2: newMeasure.append(s) victor@2: str0="KS:"+str(s.sharps) victor@2: omr_symbols.append([str0,None,None,symbol['offset'],symbol['endTime'],None]) victor@2: victor@2: elif 'Clef' in s.classes: victor@2: newMeasure.append(s) victor@2: strClef="CL:"+str(s.sign) victor@2: if isFirstClef: victor@2: omr_symbols.append([strClef,None,None,symbol['offset'],symbol['endTime'],None]) victor@2: strClef="" victor@2: isFirstClef=False victor@2: victor@2: elif 'Note' in s.classes: victor@2: newMeasure.append(s) victor@2: mytype=s.duration.type victor@2: duration=note.duration.convertTypeToQuarterLength(mytype) victor@2: realDuration=s.duration.quarterLength victor@2: if realDuration==duration+duration/2: #dot case victor@2: duration=realDuration victor@2: n="N:"+s.pitch.nameWithOctave+"_"+str(duration) victor@2: # Ties case victor@2: mytie="" victor@2: if s.tie!=None: victor@2: mytie=s.tie.type victor@2: victor@2: if float(realDuration)>0: victor@2: omr_symbols.append([n,realDuration,mytie,symbol['offset'],symbol['endTime'],s.color] ) victor@2: victor@2: elif 'Rest' in s.classes: victor@2: newMeasure.append(s) victor@2: mytype=s.duration.type victor@2: if mytype!="complex": victor@2: duration=note.duration.convertTypeToQuarterLength(mytype) victor@2: else: victor@2: duration=s.duration.quarterLength victor@2: realDuration=s.duration.quarterLength victor@2: if realDuration==duration+duration/2: #dot case victor@2: duration=realDuration victor@2: n="R:"+str(duration) victor@2: # realDuration=s.duration.quarterLength victor@2: omr_symbols.append([n,realDuration,False,symbol['offset'],symbol['endTime'],s.color]) victor@2: victor@2: elif 'Chord' in s.classes: victor@2: if type(s) is not harmony.ChordSymbol: victor@2: newMeasure.append(s) victor@2: mytype=s.duration.type victor@2: duration=note.duration.convertTypeToQuarterLength(mytype) victor@2: realDuration=s.duration.quarterLength victor@2: if realDuration==duration+duration/2: #dot case victor@2: duration=realDuration victor@2: chord="C:" victor@2: sOrder=self.__orderChord(s) victor@2: for n in sOrder: victor@2: chord+="[:"+n.pitch.nameWithOctave+"_"+str(duration) victor@2: victor@2: victor@2: victor@2: # Ties case victor@2: mytie="" victor@2: if s.tie!=None: victor@2: mytie=s.tie.type victor@2: omr_symbols.append([chord,realDuration,mytie,symbol['offset'],symbol['endTime'],s.color]) victor@2: victor@2: elif 'Barline' in s.classes: victor@2: styleBarline=s.style victor@2: try: victor@2: directionRepeat=s.direction victor@2: except: victor@2: directionRepeat="" victor@2: victor@2: victor@2: omr_symbols.append(['!',styleBarline,directionRepeat,symbol['offset'],symbol['endTime'],None]) victor@2: if strClef!="": victor@2: omr_symbols.append([strClef,None,None,0,0,None]) victor@2: omr_filtered.append(newMeasure) victor@2: return omr_filtered,omr_symbols victor@2: victor@2: def removeExtraTies(self,arraySymbols): victor@2: ''' victor@2: Removes the non logical ties from the symbol array victor@2: victor@2: ''' victor@2: for s in arraySymbols: victor@2: if isinstance(s,list): victor@2: mainSymbol=s[0] victor@2: if mainSymbol.find('N:')!=-1: victor@2: tie1=s[2] victor@2: if arraySymbols.index(s)0: victor@2: rest=[] victor@2: rest.append("R:"+str(offsetNote)) victor@2: rest.append(offsetNote) victor@2: rest.append(False) victor@2: rest.append(0) victor@2: rest.append(offsetNote) victor@2: rest.append(None) victor@2: rest.append(v) victor@2: newMeasure.append(rest) victor@2: if(offset==offsetNote): victor@2: s.append(v) victor@2: newMeasure.append(s) victor@2: offset=s[4] victor@2: victor@2: victor@2: for s in strMeasure: victor@2: if self.__getSymbolMesure(s)!=None: victor@2: newMeasure.append(s) victor@2: victor@2: victor@2: return newMeasure