# -*- coding: ISO-8859-1 -*- """ Copyright (c) 2004 Stefan Thierfeldt >>> erstellt eine Lautentabulatur unter der aktuellen Notenzeile alle Stimmen, die in die Lautentabulatur übertragen werden, müssen in einer Notenzeile stehen. Sie werden auf eine wählbare Anzahl von Lautensaitenlinien in französischer Notation übertragen. Über den Lautensaiten werden Notenhalssymbole für die Notenlänge eingefügt. Mittels Dialog sind Kenndaten wie Abstände, Schriftgröße, Saitenanzahlen usw. wählbar. Stand: 28.02.2004 Stefan Thierfeldt, Jülich <<< """ lautenTabTag = '31667-1' def setSaiten(anzsait, distY): # gibt im Array result die y-Werte der anzait+1 Saitenpositionen zurück # 1 mehr, da auch unter der Tabulatur Noten stehen können result = [] y = 0 for i in range(anzsait + 1): result .append(i*distY) return result def transpToSaite(chromPitch, anzSait): # gibt die Nummer der Saite und die Nummer des Bundes auf der Saite zurück # die Anzahl der Saiten wird übermittelt, um nach unten hin nicht # auf zu tiefe Saiten zu kommen # Saiten der Laute: g', d', a, f, c, G, F, D, C # entspricht Pitch: 79, 74, 69, 65, 60, 55, 53, 50, 48 pitches = [79, 74, 69, 65, 60, 55, 53, 50, 48] saite = 0 bund = 0 for i in range(len(pitches)): if chromPitch >= pitches[i]: saite = i bund = chromPitch-pitches[i] break result = [saite, bund] return result def toNoteSymbol(laenge): # gibt den Buchstaben (bezogen auf den Capella-Zeichensatz) zurück, # der der Notenlänge entspricht result = 'ã' # Kopf ganze Note als default if laenge == Rational(3,2): result = 'ã.' # punktierte Ganze elif laenge == Rational(1,1): result = 'ã' # ganze Note elif laenge == Rational(1,2): result = '®' # halbe Note elif laenge == Rational(3,4): result = '®.' # punktierte Halbe elif laenge == Rational(1,4): result = '¢' # Viertelnote elif laenge == Rational(3,8): result = '¢.' # punktierte Viertel elif laenge == Rational(1,8): result = '¤' # Achtelnote elif laenge == Rational(3,16): result = '¤.' # punktierte Achtel elif laenge == Rational(1,16): result = '¦' # Sechzehntelnote return result def toPauseSymbol(laenge): # gibt den Buchstaben (bezogen auf den Capella-Zeichensatz) zurück, # der der Pausenlänge entspricht result = 'I' # ganze Pause als default if laenge == Rational(3,2): result = 'I.' # punktierte Ganze elif laenge == Rational(1,1): result = 'I' # ganze Pause elif laenge == Rational(1,2): result = 'J' # halbe Pause elif laenge == Rational(3,4): result = 'J.' # punktierte halbe Pause elif laenge == Rational(1,4): result = 'K' # Viertelpause elif laenge == Rational(3,8): result = 'K.' # punktierte Viertelpause elif laenge == Rational(1,8): result = 'L' # Achtelpause elif laenge == Rational(3,16): result = 'L.' # punktierte Achtelpause elif laenge == Rational(1,16): result = 'M' # Sechzehntelnote return result def transpNotes(anzSait, distY, textHeight, noteHeight, repeatNoten, stimmNr, yOffset): # anzSait = Anzahl der darzustellenden Lautensaiten # distY = vertikaler Abstand der Saitenlinien # textHeight = Höhe (in Punkten) der Bundbezeichnungen # noteHeight = Höhe (in Punkten) der Capella-Notensymbole # repeatNoten: wens TRUE, werden gleiche Notenwerte mehrfach gezeichnet # stimmNr = Nummer der Stimme, aus der Notenwerte und Takte genommen werden buende = 'abcdefghijklmno' # Namen der Bünde, die darzustellen sind sel=curSelection() result = (False, False, False, False) if sel == 0: messageBox('Fehler', 'keine aktive Partitiur') return result firstsel = sel[0] lastsel = sel[1] sys = activeScore().system(firstsel[0]) staff = sys.staff(firstsel[1]) voice = staff.voice(firstsel[2]) firstnote = firstsel[3] lastnote = lastsel[3] # 1. echte Note/Pause suchen und als Verankerungspunkt merken for anchornote in voice.noteObjs(): if anchornote.isChord() or anchornote.isRest(): break # anchornote zeigt nun auf die erste echte Note oder Pause # Nun setzen wir die Y-Werte der Linien für die Saiten saitY = setSaiten(anzSait, distY) # saitY enthält die y-Koordinanten für die Lautensaiten # jetzt gehen wir durch alle Noten/Pausen in der Stimme # und tragen die Bundnummer auf die entspr. Saite ein for myvoice in staff.voices(): # wir gehen durch alle Stimmen des Systems ... for mynote in myvoice.noteObjs(): # ... und durch alle Noten in der Stimme if mynote.isRest(): # wir haben eine Pause, also Pause malen pass # erst einmal gar nichts machen, ggf. hier später verbessern else: # wir haben eine Note, wir setzen für jeden Notenkopf den Buchstaben des Bundes for myhead in mynote.heads(): # ... und durch alle Köpfe der Note tonhoehe = myhead.chromaticPitch() griffPos = transpToSaite(tonhoehe, anzSait) # griffpos enthält in [0] die Saite und in [1] den Bund # die Sateinnummer kann höher sein als die dx = 0 if griffPos[0] <= anzSait: # d.h. wir sind im normalen Liniensystem dy = yOffset + saitY[griffPos[0]] bund = buende[griffPos[1]:griffPos[1]+1] else: # d.h. wir sind unter unterster Linie dy = yOffset + saitY[anzSait] # ACHTUNG: hier werden nur leere Saiten angegeben! Wenn Ton nicht auf leerer # Saite, Benutzerverantwortung if griffPos[0] == 7: bund = '/a' # d.h. wir sind auf 8. Saite elif griffPos[0] == 8: bund = '//a' # d.h. wir sind auf 9. Saite else: bund = '///a' # d.h. wir sind auf 10. Saite # jetzt schreiben wir an die Position den Buchstaben des Bundes text = dict(type = 'text', content = bund, align = 'center', font = dict(height=textHeight), x=dx, y=dy, tag=lautenTabTag) mynote.addDrawObj(text) if stimmNr > staff.nVoices()-1: # wenn Stimmenbereich überschritten, auf höchste Stimmnummer setzen stimmNr = staff.nVoices()-1 laengeVgl = 0 # Vergleichswert für Länge der Noten for mynote in staff.voice(stimmNr).noteObjs(): # wir sind nun in der Stimme, die der Benutzer als die wichtigste # für die Darstellung ausgewählt hat # für die Stimme Nr. stimmNr in der aktuellen Zeile: # wir gehen durch alle Noten in der ausgewählten Stimme # und schreiben das Notensymbol oben über die Tabulatur xmax = mynote.posX() # xmax zählt hierbei den am weitesten rechts stehenden Taktstrich bzw. Objekt laenge = mynote.duration() pause = mynote.isRest() if laenge != laengeVgl or pause or repeatNoten == 1: laengeVgl = laenge # wir haben neue Tonlänge, also merken if pause: notesymbol = toPauseSymbol(laenge) else: notesymbol = toNoteSymbol(laenge) dx = 0 dy = yOffset + saitY[0]-1-distY # richtige y-Position für Notensymbole capFont = dict(face = 'capella3', pitchAndFamily = 2, # FF_DONTCARE | VARIABLE_PITCH charSet = 2, # SYMBOL_CHARSET height = noteHeight) text = dict(type = 'text', content = notesymbol, align = 'center', x=dx, y=dy, font=capFont, tag=lautenTabTag) mynote.addDrawObj(text) if mynote.implBarline() or mynote.isBarline(): # d.h. an dieser Note steht ein Taktstrich, wir setzen auch einen takt_dx = 4 # Versatz der Taktstriche yoben = saitY[0] + yOffset yunten = saitY[anzSait-1] + yOffset # implizite und explizite Taktstriche müssen gesondert behandelt werden if mynote.implBarline(): linie = dict(type = 'line', x1 = takt_dx, y1 = yoben, x2 = takt_dx, y2 = yunten, tag=lautenTabTag) mynote.addDrawObj(linie) else: # also expliziter Taktstrich, kann nur an Note gezeichnet werden xTakt = mynote.posX() - anchornote.posX() linie = dict(type = 'line', x1 = xTakt, y1 = yoben, x2 = xTakt, y2 = yunten, tag=lautenTabTag) anchornote.addDrawObj(linie) # jetzt zeichnen wir die max. 6 waagerechten Linien für die Lautensaiten xrechts = xmax + takt_dx - anchornote.posX() for yPos in saitY[0:anzSait]: linie = dict(type = 'line', x1 = -5, y1 = yPos+yOffset, x2 = xrechts, y2 = yPos+yOffset, tag=lautenTabTag) anchornote.addDrawObj(linie) # ---------------------------- HAUPTPROGRAMM ---------------------------------------------------- distY = 2 # der vertikale Abstand der Saiten anzSait = 6 # die Anzahl der Saiten wird auf 6 festgelegt, im Dialog nicht änderbar textHeight = 9 # die Texthöhe des Fonts beim Eintragen der Buchstaben der Bünde noteHeight = 14 # die Texthöhe des Capella-Fonts repeatNoten = 1 # Flag für wiederholte Noten-Darstellung stimmNr = 0 # Nummer der Stimme, aus der Takte und Notenlängen geholt werden yOffset = 12 # Default-Abstand von der Zeichenlinie nach unten #------ DIALOG START ------------------------ edit1 = Edit('20', min=10, max=25, width=4) edit2 = Edit('12', min=8, max=20, width=4) edit3 = Edit('9', min=7, max=12, width=4) edit4 = Edit('14', min=10, max=18, width=4) edit5 = Edit('1', min=1, max=10, width=4) hBox1 = HBox([edit1, Label('/10 Einh. Abstand Saitenlinien (10 - 25) ')], padding = 8) hBox2 = HBox([edit2, Label('Abstand Notenzeile-Tabulatur (8 - 20)')], padding = 8) hBox3 = HBox([edit3, Label('pt Schrifthöhe (7 - 12)')], padding = 8) hBox4 = HBox([edit4, Label('pt Notensymbolhöhe (10 - 18)')], padding = 8) radio = Radio(['nur 1x zeichnen', 'repetieren'], text = 'gleiche Notenwerte', value = 0) hBox5 = HBox([Label('Takte und Notenwerte aus Stimme Nr. '), edit5], padding = 8) vBox = VBox([hBox1, hBox2, hBox3, hBox4, radio, hBox5], padding = 16) dlg = Dialog('Lautentabulatur erzeugen', vBox) #------ DIALOG ENDE ------------------------- if activeScore(): if dlg.run(): activeScore().registerUndo("Lautentabulatur") distY = int(edit1.value()) / 10.0 # auf richtigen Bereich anpassen yOffset = int(edit2.value()) textHeight = int(edit3.value()) noteHeight = int(edit4.value()) repeatNoten = radio.value() # stimmNr = int(edit5.value())-1 # 1 abziehen, da Beginn bei 0 transpNotes(anzSait, distY, textHeight, noteHeight, repeatNoten, stimmNr, yOffset) # ENDE