123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- from lxml import etree
- import sys
- import getopt
- NOTE_TYPE= ["whole", "half", "quarter", "eighth", "16th", "32nd", "64th"]
- NOTE_TYPE_MULT=[ 4, 2, 1, 0.5, 0.25, 0.125, 0.0625]
- def noteTypeToIndex(s):
- i=0
- for st in NOTE_TYPE:
- if s==st:
- return i
- i=i+1
- return -1
- def fretToMidi(string, fret):
- tab=[0,40,45,50,55,59,64]
- tab=[0,64,59,55,50,45,40]
- return tab[string]+fret
- def xpathExists(obj, path):
- for x in obj.xpath(path):
- return True
- return False
-
- def xpathFirst(d, path):
- for x in d.xpath(path):
- return x
- return None
- class Note:
- def __init__(self, data):
- self.octave=0
- self.note="R"
- self.corde=0
- self.fret=0
- self.midiNote=0
- if xpathExists(data,"rest"):
- self.rest=True
- else:
- self.rest=False
- self.octave=int(xpathFirst(data,"pitch/octave").text)
- self.note=xpathFirst(data,"pitch/step").text
- self.corde=int(xpathFirst(data,"notations/technical/string").text)
- self.fret=int(xpathFirst(data,"notations/technical/fret").text)
- self.midiNote=fretToMidi(self.corde, self.fret)
-
- self.type=noteTypeToIndex(xpathFirst(data,"type").text)
- self.duree=int(xpathFirst(data,"duration").text)
- self.voix=int(xpathFirst(data,"voice").text)
- self.dot=xpathExists(data, "dot")
- self.beatmult=NOTE_TYPE_MULT[self.type]
- if self.dot:
- self.beatmult=1.5*self.beatmult
-
-
- def getMidi(self):
- return self.midiNote
-
- def getTime(self):
- return self.beatmult
- def show(self):
- print(str(self.getMidi())+": \""+str(self.type)+"\" "+str(self.dot)+" "+str(self.rest))
- class Measure:
- def __init__(self, data):
- self.notes=[]
- try:
- self.beats=int(xpathFirst(data, "attributes/time/beats").text)
- self.beatType=int(xpathFirst(data, "attributes/time/beat-type").text)
- except:
- self.notes=[]
-
- def addNote(self, note):
- self.notes.append(note)
-
- def noteToString(self):
- s=""
- i=0
- for x in self.notes:
- if i>0:
- s+=", "
- s+=str(self.notes[i].getTime())
- i+=1
- return s
-
- def timeToString(self):
- s=""
- i=0
- for x in self.notes:
- if i>0:
- s+=", "
- s+=str(self.notes[i].getTime())
- i+=1
- return s
-
- class Part:
- def __init__(self, data):
- self.id=data.get("id")
- self.notes=[]
- self.beat=0
- self.beatType=0
- path="/score-partwise/part-list/score-part[@id='"+self.id+"']/"
- self.name=xpathFirst(data, path+"part-name").text
- self.instrument=xpathFirst(data, path+"score-instrument/instrument-name").text
- self.midiChannel=xpathFirst(data, path+"midi-instrument/midi-channel").text
- self.midiProgram=xpathFirst(data, path+"midi-instrument/midi-program").text
- self.measures=[]
- for d in data.xpath("measure"):
- m=Measure(d)
- self.measures.append(m)
- for n in d.xpath("note"):
- note=Note(n)
- self.notes.append(note)
- m.addNote(note)
-
- def length(self):
- tot=0
- for x in self.notes:
- tot+=x.getTime()
- return tot
-
- def toString(self):
- return self.name+" : (\""+self.instrument+"\", "+str(self.length())+" beats, "+str(len(self.notes))+" notes)"
- def noteRangeToString(self, start, end):
- i=start
- s=""
- while i<=end:
- for x in self.measures[i].notes:
- s+= ("" if s=="" else ", ")+str(x.getMidi())
- i+=1
- return s
-
- def timeRangeToString(self, start, end):
- i=start
- s=""
- while i<=end:
- for x in self.measures[i].notes:
- s+= ("" if s=="" else ", ")+str(x.getTime())
- i+=1
- return s
-
-
- class System:
- def __init__(self, path):
- self.path=path
- self.partition=[]
- self.tree = etree.parse(self.path)
- self.parts=[]
- for data in self.tree.xpath("/score-partwise/part"):
- self.parts.append(Part(data))
-
- self.bufferNote=""
- self.bufferTime=""
-
-
- def noteRange(self, i, start, end):
- x=self.parts[i-1].noteRangeToString(start-1, end-1)
- self.bufferNote+= ("" if self.bufferNote=="" else ", ")+x
- return x;
-
- def timeRange(self, i, start, end):
- x=self.parts[i-1].timeRangeToString(start-1, end-1)
- self.bufferTime+= ("" if self.bufferTime=="" else ", ")+x
- return x;
-
- def note(self, i):
- return self.noteRange(i, 1, len(self.parts[i-1].measures));
-
- def time(self, i):
- return self.timeRange(i, 1, len(self.parts[i-1].measures));
-
- def range(self, i,start, end):
- self.timeRange(i, start, end)
- self.noteRange(i, start, end)
-
- def track(self, i):
- self.time(i)
- self.note(i)
-
- def before(self, i, n):
- self.timeRange(i, 1, n)
- self.noteRange(i, 1, n)
-
- def after(self, i, n):
- self.timeRange(i, n, len(self.parts[i-1].measures))
- self.noteRange(i, n, len(self.parts[i-1].measures))
-
- def new(self):
- self.bufferNote=""
- self.bufferTime=""
-
- def write(self, f):
- fd = open(f, "w")
- fd.write("notes=(ring "+self.bufferNote+")")
- fd.write("times=(ring "+self.bufferTime+")")
- fd.close()
-
-
- def print(self):
- print("notes=(ring "+self.bufferNote+")")
- print("times=(ring "+self.bufferTime+")")
-
- def list(self):
- i=0
- for x in self.parts:
- print("["+str(i)+"] : "+x.toString())
- i+=1
- if __name__ == '__main__':
- def usage():
- print("Usage:")
- print(sys.argv[0]+" PATH_TO_XML [COMMANDS]")
- print("ou " +sys.argv[0]+" -h | --help : Affiche cette aide")
- print("ou " +sys.argv[0]+" -l | --list : Liste les pistes")
- print("COMMANDS:")
- print("\t-n | --new : Vide le buffer courant")
- print("\t-r | --range TRACK START END : Ajoute les mesure de la piste TRACK entre les mesure START et END")
- print("\t-b | --before TRACK INDEX : Ajoute les mesure de la piste TRACK jusqu'a la mesure INDEX")
- print("\t-a | --after TRACK INDEX : Ajoute les mesure de la piste TRACK à partir de la mesure INDEX")
- print("\t-t | --track TRACK : Ajoute toutes la piste TRACK au buffer")
- print("\t-p | --print : Affiche le buffer courant")
- print("\t-w | --write FILE : Ecrit le buffer dans le fichier FILE")
- song=None
- path="/home/fanch/Documents/tabs/Johann Pachelbel - Canon In D (ver 6 by Ezechiel).xml"
- i=1
- op=False
- if len(sys.argv)==1:
- usage()
- sys.exit(-1)
- while i<len(sys.argv):
- if i==1:
- path=sys.argv[i]
- i+=1
- song=System(path)
- elif sys.argv[i]=="-n" or sys.argv[i]=="--new":
- song.new()
- elif sys.argv[i]=="-r" or sys.argv[i]=="--range":
- song.range(int(sys.argv[i+1]), int(sys.argv[i+2], sys.argv[i+3]))
- op=True
- i+=3
- elif sys.argv[i]=="-b" or sys.argv[i]=="--before":
- song.before(int(sys.argv[i+1]), int(sys.argv[i+2]))
- op=True
- i+=2
- elif sys.argv[i]=="-a" or sys.argv[i]=="--after":
- song.after(int(sys.argv[i+1]), int(sys.argv[i+2]))
- op=True
- i+=2
- elif sys.argv[i]=="-t" or sys.argv[i]=="--track":
- op=True
- song.track(int(sys.argv[i+1]))
- i+=1
- elif sys.argv[i]=="-p" or sys.argv[i]=="--print":
- song.print()
- elif sys.argv[i]=="-w" or sys.argv[i]=="--write":
- song.part(int(sys.argv[i+1]))
- i+=1
- elif sys.argv[i]=="-h" or sys.argv[i]=="--help":
- usage()
- sys.exit(-1)
- elif sys.argv[i]=="-l" or sys.argv[i]=="--list":
- usage()
- sys.exit(-1)
- else:
- usage()
- sys.exit(-1)
- i+=1
- if not op:
- song.track(1)
- song.print()
|