-import binascii, sys, zlib, traceback \r
-\r
-shortcopyleft = """\r
-nwc2ly - Converts NWC(v 1.75) to LY fileformat\r
-Copyright (C) 2005 Joshua Koo (joshuakoo @ myrealbox.com)\r
-\r
-This program is free software; you can redistribute it and/or\r
-modify it under the terms of the GNU General Public License\r
-as published by the Free Software Foundation; either version 2\r
-of the License, or (at your option) any later version.\r
-\r
-This program is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with this program; if not, write to the Free Software\r
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
-"""\r
-\r
-##\r
-# most infomation obtained about the nwc format \r
-# is by using noteworthycomposer and the somewhat like the french cafe method\r
-# (http://samba.org/ftp/tridge/misc/french_cafe.txt)\r
-#\r
-#\r
-## \r
-# Revisions\r
-# 0.1 07 april 2005 initial hex parsing;\r
-# 0.2 13 april 2005 added multiple staff, keysig, dots, durations\r
-# 0.3 14 april 2005 clef, key sig detection, absolute notes pitching\r
-# 0.4 15 April 2005 Relative Pitchs, Durations, Accidentals, Stem Up/Down, Beam, Tie\r
-# 0.5 16 April 2005 Bug fixes, Generate ly score , Write to file, Time Sig, Triplets, Experimental chords\r
-# 0.6 17 April 2005 Compressed NWC file Supported!\r
-# 0.7 19 April 2005 Version detection, Header \r
-# 20 April 2005 BUGS FiXes, small Syntax changes\r
-# 21 April 2005 Still fixing aimlessly \r
-# 23 April 2005 Chords Improvement\r
-# 24 April 2005 staccato, accent, tenuto. dynamics, midi detection (but unsupported)\r
-# 0.8 24 April 2005 Experimental Lyrics Support\r
-# 0.9 29 April 2005 Workround for \acciaccatura, simple Check full bar rest adjustment\r
-# \r
-## \r
-# TODO\r
-# Proper syntax and structure for staffs, lyrics, layering\r
-# version 1.7 Support\r
-# nwc2ly in lilytool\r
-# \r
-# Piano Staff\r
-# Chords\r
-# Pedals\r
-# Midi Instruments\r
-# Visability\r
-# Lyrics\r
-# Context Staff\r
-# Staff layering / Merging\r
-##\r
-#\r
-# BUGS text markups, chords, fermata\r
-######\r
-# \r
-# cd /cygdrive/c/development/nwc2ly\r
-# $ python nwc2ly.py lvb7th1\ uncompressed.nwc test.ly > convert.log\r
-#######\r
-\r
-nwc2lyversion = '0.9.0'\r
-############\r
-# Options #\r
-############\r
-debug = 0 \r
- # You can use 0 for False and 1 for True\r
-relativePitch = 1\r
-relativeDuration = 1\r
-barLinesComments = 10 # Comments for every x lines # section/line comment\r
-\r
-insertBeaming = 1\r
-insertSteming = 1\r
-#insertText = 0\r
-\r
-nwcversion = 1.75\r
-##############\r
-\r
-args = len(sys.argv)\r
-if args<2:\r
- print "Syntax: python nwc2ly.py nwcfile [lyfile]"\r
- sys.exit()\r
-nwcfile = sys.argv[1] # 'simple1.nwc' #'simple2.nwc' 'simple3.nwc' 'bbc5-1-org.nwc' bbc5-1-nop.\r
-\r
-if args<3:\r
- lyfile = '' # 'test.ly'\r
-else:\r
- lyfile = sys.argv[2]\r
-\r
-\r
-\r
-def getFileFormat(nwcData):\r
- #'[NoteWorthy ArtWare]'\r
- #'[NoteWorthy Composer]'\r
- nwcData.seek(0)\r
- company = readLn(nwcData)\r
- nwcData.seek(2,1) # pad\r
- product = readLn(nwcData)\r
- version = readLn(nwcData)\r
- version = ord(version[0]) * 0.01 + ord(version[1])\r
- nwcversion = version\r
- print 'NWC file version', nwcversion, 'detected!'\r
- pad(nwcData,2) # times saved\r
- name1 = readLn(nwcData)\r
- name2 = readLn(nwcData)\r
- \r
- pad(nwcData,8)\r
- huh = nwcData.read(1)\r
- pad(nwcData,1)\r
- \r
-def getFileInfo(nwcData):\r
- title = readLn(nwcData)\r
- author = readLn(nwcData)\r
- copyright1 = readLn(nwcData)\r
- copyright2 = readLn(nwcData)\r
- comments = readLn(nwcData)\r
- \r
- header = "\\header {"\r
- header += "\n\ttitle = \"%s\"" % title\r
- header += "\n\tenteredby = \"%s\"" % author\r
- header += "\n\tcopyright = \"%s\"" % copyright1\r
- header += "\n\tfooter = \"%s\"" % copyright2\r
- header += "\n\t%%{ %s %%}" % comments\r
- header += "\n}"\r
- \r
- # TO ADD IN DEFAULT BLANK FEILDS TO KEY IN\r
- print 'title,author,copyright1,copyright2,comments: ', (title,author,copyright1,copyright2,comments)\r
- return header\r
-\r
-# Page Setup\r
-def getPageSetup(nwcData):\r
- # ??\r
- getMargins(nwcData)\r
- #getContents(nwcData)\r
- #getOptions(nwcData)\r
- getFonts(nwcData)\r
-\r
- \r
-def getMargins(nwcData):\r
- readTill(nwcData,'\x01')\r
- pad(nwcData,1)\r
- # get string size 43\r
- margins = readLn(nwcData)\r
- print 'margins ', margins\r
- #mirrorMargines\r
- #UOM\r
- return \r
-\r
-def getOptions(nwcData):\r
- # page numbering, from\r
- # title page info\r
- # extend last system\r
- # incrase note spacing for larger note duration\r
- # staff size\r
- # staff labels (none, first systems, top systems, all systems\r
- # measure numbers none, plain, circled, boxed\r
- # measure start\r
- return\r
-\r
-def getFonts(nwcData):\r
- # 12 Times\r
- readTill(nwcData,'\xFF')\r
- n = nwcData.read(1)\r
- pad(nwcData,1)\r
- for i in range (12):\r
- # Font Name\r
- font = readLn (nwcData)\r
- \r
- # 00\r
- \r
- # Style 'Regular' 'Italic' 'Bold' 'Bold Italic'\r
- style = ord(nwcData.read(1)) & 3\r
- \r
- # Size\r
- size = ord(nwcData.read(1))\r
- \r
- ## 00\r
- nwcData.seek(1,1)\r
- \r
- # Typeface\r
- # 00 Western, b1 Hebrew\r
- typeface = nwcData.read(1)\r
- \r
- print 'Font detected' , font, 'size',size, 'style ', style, ' typeface',typeface\r
- \r
-\r
-def findNoOfStaff(nwcData):\r
- # Infomation on Staffs \x08 00 00 FF 00 00 n\r
- data = 0;\r
- \r
- readTill(nwcData,'\xFF')\r
- print "Where am I? ", nwcData.tell()\r
- \r
- \r
- nwcData.read(2)\r
- \r
- layering = nwcData.read(1) # FF or 00\r
- \r
- noOfStaffs = ord(nwcData.read(1))\r
- nwcData.read(1)\r
- print noOfStaffs, " noOfStaffs found"\r
- return noOfStaffs\r
-\r
-def findStaffInfo(nwcData):\r
- # Properties for Staff\r
- # General \r
- # Name.\r
- # Group\r
- # Ending Bar\r
- # Visual\r
- # Verticle Upper Size\r
- # Verticle Lower Size\r
- # Style\r
- # Layer Next Staff\r
- # Color\r
- # Midi\r
- # Part Volume\r
- # Stereo Pan\r
- # Transposition\r
- # Muted\r
- # PlayBack Device\r
- # Playback Channel\r
- # Instrument\r
- # Patch Name\r
- # Patch List Type\r
- # Bank Select \r
- # Controller0\r
- # Controller32\r
- # Staff Lyrics\r
- # LineCount\r
- # AlignSyllableRule\r
- # StaffPlacementAligment\r
- # StaffPlacementOffset\r
- # StaffPropertiesVerticleSizeUpper\r
- # StaffPropertiesVerticleSizeLower\r
- \r
- format = ''\r
- staffName = readLn(nwcData)\r
- format += "\\context Staff = %s " % staffName # or voice or lyrics \r
- \r
- groupName = readLn(nwcData) # HOW TO ORGANISE THEM??\r
- \r
- endbar = ord(nwcData.read(1)) # & (2^3-1)\r
- #print 'end ',endbar\r
- endingBar = ending[endbar] # 10 --> OC for lyrics? 10000 1100\r
- \r
- muted = ord(nwcData.read(1)) & 1\r
- nwcData.read(1)\r
- \r
- channel = ord(nwcData.read(1)) + 1\r
- nwcData.read(9)\r
- \r
- stafftype = staffType[ord(nwcData.read(1))&3]\r
- nwcData.read(1)\r
- \r
- uppersize = 256 - ord(nwcData.read(1)) # - signed +1 )& 2^7-1 )\r
- readTill(nwcData,'\xFF')\r
- \r
- lowersize = ord(nwcData.read(1))\r
- ww = nwcData.read(1) \r
- print '[uppersize,lowersize]',[uppersize,lowersize]\r
- \r
- noOfLines = ord(nwcData.read(1))\r
- print '[staffName,groupName,endingBar,stafftype,noOfLines]', [staffName,groupName,endingBar,stafftype,noOfLines]\r
- \r
- layer = ord(nwcData.read(1)) & 1\r
- \r
- # signed transposition\r
- # FF?\r
- \r
- partVolume = ord(nwcData.read(1))\r
- ord(nwcData.read(1))\r
- \r
- stereoPan = ord(nwcData.read(1))\r
- if nwcversion == 1.7:\r
- nwcData.read(2)\r
- else:\r
- nwcData.read(3)\r
- \r
- nwcData.read(2)\r
- #lyrics = ord(nwcData.read(1)) & 1\r
- lyrics = readInt(nwcData)\r
- noOfLyrics = readInt(nwcData)\r
- \r
- lyricsContent = ''\r
- if lyrics:\r
- lyricOptions = readInt(nwcData)\r
- nwcData.read(3)\r
- for i in range(noOfLyrics):\r
- print 'looping ',i, 'where', nwcData.tell()\r
- lyricsContent += '\\ \lyricmode { ' # lyrics\r
- lyricsContent += getLyrics(nwcData) #\r
- lyricsContent += '}'\r
- nwcData.read(1)\r
- \r
- nwcData.read(1)\r
- color = ord(nwcData.read(1)) & 3 #12\r
- \r
- noOfTokens = readInt(nwcData)\r
- print noOfTokens, " Tokens found", nwcData.tell()\r
- return noOfTokens, format, lyricsContent\r
- \r
-\r
-\r
-\r
-\r
-def pad(nwcData, length):\r
- nwcData.seek(length,1)\r
-\r
-def readTill(nwcData, delimit):\r
- data = ''\r
- value = ''\r
- while data!=delimit:\r
- value += data\r
- data = nwcData.read(1)\r
- \r
- return value\r
- \r
-def readLn(nwcData):\r
- return readTill (nwcData,'\x00')\r
- # reads until 00 is hit\r
- # od oa == \n\r
-\r
-def readInt(nwcData):\r
- data = nwcData.read(2)\r
- no = ord(data[0])\r
- no += ord(data[1]) * 256\r
- return no\r
-\r
-\r
-def getLyrics(nwcData):\r
- \r
- data = ''\r
- print 'reach'\r
- blocks = ord(nwcData.read(1))\r
- if blocks==4: blocks = 1\r
- if blocks==8: blocks = 2\r
- if blocks == 0: return \r
- \r
- lyricsLen = readInt(nwcData)\r
- \r
- print 'blocks ',blocks, 'lyrics len', lyricsLen, 'at ', nwcData.tell()\r
- \r
- nwcData.read(1)\r
- for i in range (blocks):\r
- data += nwcData.read(1024)\r
- \r
- lyrics = data[1:lyricsLen-1]\r
- print 'lyrics ', lyrics\r
- return lyrics\r
- \r
-def getDuration(data):\r
- durationBit = ord(data[2]) & 7\r
- durationDotBit = ord(data[6]) \r
- \r
- duration = durations[durationBit]\r
- if (durationDotBit & 1<<2):\r
- durationDot = '.'\r
- elif (durationDotBit & 1):\r
- durationDot = '..'\r
- else :\r
- durationDot = ''\r
- return duration + durationDot\r
-\r
-def getKey(data):\r
- data = binascii.hexlify(data)\r
- \r
- if (keysigs.has_key(data)):\r
- return '\key ' + keysigs[data]\r
- return '% unknown key'\r
-\r
-def getLocation(data):\r
- offset = ord(data[8]);\r
- if offset > 127 :\r
- return 256-offset\r
- if (ord(data[9])>>3 & 1):\r
- return -offset\r
- \r
- return offset\r
- #print 'offset ', offset\r
- #print binascii.hexlify(data[8:9])\r
-\r
-def getAccidental(data):\r
- data = ord(data)\r
- data = (data & 7 )\r
- return acdts[data]\r
-\r
-def getNote(data):\r
- \r
- # pitch\r
- pitch = getLocation(data)\r
- \r
- # get Accidentals\r
- accidental = getAccidental(data[9])\r
- \r
- # get Relative Duration\r
- duration = getDuration(data)\r
- \r
- # check stems\r
- stem = ord(data[4])\r
- stem = (stem >> 4) & 3\r
- \r
- # check beam\r
- beam = ord(data[4]) & 3\r
- \r
- # triplets \r
- triplet = triplets [ord(data[4])>>2 & 3 ]\r
- \r
- # check tie\r
- tie = ''\r
- if ord(data[6]) >> 4 & 1:\r
- tie = '~'\r
- \r
- staccato = (ord(data[6]) >> 1) & 1\r
- accent = (ord(data[6]) >> 5) & 1\r
- \r
- tenuto = (ord(data[7]) >> 2) & 1\r
- slur = slurs[ord(data[7]) & 3 ]\r
- grace = (ord(data[7]) >> 5) & 1\r
- \r
- # check slur\r
- slur = slurs[ord(data[7]) & 3 ]\r
- \r
- \r
- #TODO should use a dictionary\r
- return (pitch, accidental, duration, stem, beam, triplet, slur, tie, grace, staccato, accent, tenuto)\r
-\r
-def getRelativePitch(lastPitch, pitch):\r
- octave = ''\r
- diff = pitch - lastPitch\r
- if diff>3:\r
- for i in range((diff-4 + 7)/7):\r
- octave += "'"\r
- if octave == '':\r
- octave += "'"\r
- elif diff<-3:\r
- for i in range((-diff-4 + 7)/7):\r
- octave += ","\r
- if octave == '':\r
- octave += ","\r
- return octave\r
- \r
-def durVal(duration):\r
- where = duration.find('.')\r
- \r
- if where>-1:\r
- durVal = 128/int (duration[:where])\r
- nextVal = durVal\r
- for i in range(len(duration)-where):\r
- nextVal = nextVal / 2\r
- durVal += nextVal\r
- \r
- else:\r
- durVal = 128/int (duration)\r
- return durVal\r
- \r
-def processStaff(nwcData):\r
- keysigCount =0\r
- timesigCount=0\r
- noteCount=0\r
- restCount=0\r
- staffCount=0\r
- barlineCount=0\r
- clefCount=0\r
- textCount =0\r
- dynamicCount = 0\r
- \r
- lastPitch = scale.index('c')\r
- lastDuration = 0\r
- lastClef = scale.index(clefs[0]) # index referenced to note of last clef\r
- lastStem = 0\r
- lastTimesig = 1\r
- \r
- lastKey = { 'c': '', #c \r
- 'd': '', 'e': '', 'f': '', 'g': '', 'a': '', 'b': '' }\r
- currentKey = lastKey.copy()\r
- \r
- data = 0\r
- token = 1\r
- \r
- result = ""\r
- result += "\n\t\\new Staff {\n\t\t"\r
- lastChord = 0\r
- lastGrace = 0;\r
- \r
- (noOfTokens,format, lyrics) = findStaffInfo(nwcData);\r
- if lyrics!='':\r
- #result += '\\lyricmode { ' + lyrics + '}'\r
- result += '%%Lyrics %%{ ' + lyrics + '%%}'\r
- \r
- if relativePitch: \r
- result+="\\relative c {"\r
- else :\r
- result+=" {"\r
- result+="\n\t\t\n\n\t\t"\r
- result+= '\n\t %% Staff %s \n\t' % staff \r
- \r
- #print "00112233445566778899\n"\r
- extra = ''\r
- # the juice\r
- \r
- while data!="":\r
- \r
- token += 1\r
- if token==noOfTokens:\r
- result += "\n\t\t}\n\t}\n\t"\r
- print "going next staff! %s" % nwcData.tell()\r
- break\r
- \r
- \r
- if nwcversion==1.7:\r
- nwcData.seek(2,1)\r
- \r
- data = nwcData.read(1)\r
- #print 'test', data\r
- \r
- # clef\r
- if data=='\x00':\r
- data = nwcData.read(6)\r
- clefCount += 1\r
- \r
- key = ord(data[2]) & 3 \r
- octave = ord(data[4]) & 3\r
- # print binascii.hexlify(data) , "CLEF? "\r
- lastClef = scale.index(clefs[key]) + octaves[octave]\r
- #TODO check for octave shifts _8\r
- lastClef += clefShift[octave] \r
- result += '\clef "' + clefNames[key] + clefOctave[octave]+ '"\n\t\t'\r
- \r
- # key signature\r
- elif data=='\x01':\r
- data = nwcData.read(12)\r
- keysigCount = keysigCount + 1\r
- \r
- #\r
- flatBits = ord(data[2])\r
- sharpBits = ord(data[4])\r
- \r
- for note in lastKey.keys():\r
- noteInd = ['a','b','c','d','e','f','g'].index(note)\r
- if (flatBits >> noteInd & 1):\r
- lastKey[note] = 'es'\r
- elif (sharpBits >> noteInd & 1):\r
- lastKey[note] = 'is'\r
- else:\r
- lastKey[note] = ''\r
- \r
- currentKey = lastKey.copy()\r
- result = result + getKey(data[1:5]) + "\n\t\t"\r
- \r
- #print "data", binascii.hexlify(data)\r
- #print "flat", binascii.hexlify(flatBits)\r
- #print "sharp", binascii.hexlify(data[4])\r
- #print getKey(data[1:5])\r
- \r
- \r
- # barline\r
- elif data=='\x02':\r
- data = nwcData.read(4)\r
- barlineCount += 1\r
- \r
- currentKey = lastKey.copy()\r
- \r
- result += "|\n\t\t"\r
- if (barlineCount % barLinesComments == 0):\r
- result += "\n\t\t% Bar " + str(barlineCount + 1) + "\n\t\t" \r
- #print '.',\r
- print "Bar ",barlineCount, " completed, "\r
- \r
- # timesig\r
- elif data=='\x05':\r
- data = nwcData.read(8)\r
- timesigCount = timesigCount + 1 \r
- beats = ord(data[2])\r
- beatValues = [ 1, 2, 4, 8 ,6, 32 ]\r
- beatValue = beatValues[ord(data[4])]\r
- timesig = str(beats) + "/" + str(beatValue)\r
- lastTimesig = timesigValues[timesig]\r
- result += "\\time " + timesig + " "\r
- # Tempo\r
- elif data=='\x06':\r
- print "Tempo"\r
- data = nwcData.read(7)\r
- tempo = readLn(nwcData)\r
- result += '\n\t\t%%tempo %s\n\t\t' % tempo\r
- #tempoCount = tempoCount + 1 \r
- \r
- # note\r
- elif data=='\x08':\r
- data = nwcData.read(10)\r
- noteCount = noteCount + 1\r
- \r
- if debug: print binascii.hexlify(data) , noteCount , nwcData.tell()\r
- (pitch, accidental, duration, stem, beam, triplet, slur, tie, grace, staccato, accent, tenuto) = getNote(data)\r
- \r
- \r
- articulate = ''\r
- if staccato: articulate+= '-.'\r
- if accent: articulate+= '->'\r
- if tenuto: articulate+= '--'\r
- \r
- beam = beams[beam]\r
- \r
- chordMatters = ''\r
- if lastChord>0 and beam==']' :\r
- chordMatters = ' } >> '\r
- lastChord = 0\r
- elif lastChord>0:\r
- \r
- print 'CHORd', durVal(duration), lastChord\r
- dur = durVal(duration)\r
- #lastChord = 1.0/((1.0 / lastChord) - (1.0/durVal(duration)))\r
- lastChord -= dur \r
- \r
- if lastChord <= 0 :\r
- chordMatters = ' } >> '\r
- lastChord = 0\r
- \r
- \r
- \r
- if not insertBeaming: beam = ''\r
- \r
- # pitch\r
- pitch += lastClef\r
- note = scale[pitch]\r
- \r
- \r
- # get Accidentals\r
- #print 'accidental',accidental\r
- if (accidental!='auto'):\r
- currentKey[note[0]] = accidental\r
- accidental = currentKey[note[0]]\r
- \r
- if (relativePitch):\r
- octave = getRelativePitch(lastPitch, pitch)\r
- lastPitch = pitch\r
- else:\r
- octave = note[1:]\r
- pitch = note[0] + accidental + octave\r
- \r
- # get Relative Duration\r
- if (relativeDuration):\r
- if (lastDuration==duration):\r
- duration = ''\r
- else:\r
- lastDuration = duration\r
- \r
- # check stems\r
- if insertSteming and (stem!= lastStem) :\r
- lastStem = stem\r
- stem = stems[stem]\r
- else :\r
- stem = ''\r
- \r
- # normal note\r
- if extra!='':\r
- extra = '-"' + extra + '"'\r
- \r
- if grace and not lastGrace: result += "\\acciaccatura { "\r
- \r
- if not grace and lastGrace: result += " } "\r
- result += triplet[0] + stem + pitch + duration + articulate + extra \r
- result += slur + tie + beam + triplet[1] +chordMatters + " "\r
- \r
- \r
- # reset\r
- lastGrace = grace\r
- extra = ''\r
- # rest\r
- elif data=='\x09':\r
- data = nwcData.read(10)\r
- restCount = restCount + 1 \r
- \r
- # get Relative Duration\r
- duration = getDuration(data)\r
- if duration == '1':\r
- duration = lastTimesig\r
- if (relativeDuration):\r
- if (lastDuration==duration):\r
- duration = ''\r
- else:\r
- lastDuration = duration\r
- \r
- result = result + 'r' + duration + " "\r
-\r
- # text\r
- elif data=='\x11':\r
- textCount = textCount + 1\r
- data = nwcData.read(2) #pad\r
- textpos = nwcData.read(1)\r
- data = nwcData.read(2) #pad\r
- text = ''\r
- data = nwcData.read(1)\r
- while data!='\x00':\r
- text += data\r
- data = nwcData.read(1)\r
- \r
- #if text.isdigit() : # check numbers\r
- # text = "-\\markup -\\number "+ text \r
- # #text = "-\\markup {\\number "+ text +"}"\r
- #else :\r
- # text = '-"' + text + '"'\r
- \r
- extra += ' ' + text\r
- \r
- # dynamics\r
- elif data=='\x07':\r
- dynamicCount = dynamicCount + 1\r
- data = nwcData.read(9)\r
- # chord\r
- elif data=='\x0A' or data=='\x12':\r
- \r
- data = nwcData.read(12)\r
- \r
- chordAmt = ord(data[10])\r
- chords = []\r
- chordDur = getDuration(data)\r
- #print 'duration',chordDur\r
- \r
- #print "WARNING Chord support is experimental", chordDur, chordAmt\r
- #print binascii.hexlify(data), 'barlines ', barlineCount\r
- #print 'no. of notes in chord' , chordAmt\r
- \r
- chord1 = []\r
- chord2 = []\r
- \r
- for i in range(chordAmt):\r
- # rest or note\r
- what = nwcData.read(1)\r
- \r
- data = nwcData.read(10)\r
- ha = getNote(data)\r
- #print 'data ', ha\r
- (pitch, accidental, duration, stem, beam, triplet, slur, tie, grace, staccato, accent, tenuto) = ha\r
- # add to list\r
- if ha[2] == chordDur:\r
- chord1.append( (pitch,accidental ) )\r
- if beam==0 or beam ==4 :\r
- lastChord = 0\r
- \r
- \r
- else : # 2 voices\r
- chord2.append( (pitch,accidental, duration) )\r
- lastChord = durVal(duration) \r
- \r
- \r
- if len(chord2)==0: # block chord\r
- result += ' <'\r
- for i in range(len(chord1)):\r
- (pitch,accidental ) = chord1[i]\r
- pitch += lastClef\r
- note = scale[pitch]\r
- \r
- if (accidental!='auto'):\r
- currentKey[note[0]] = accidental\r
- accidental = currentKey[note[0]]\r
- \r
- if (relativePitch):\r
- octave = getRelativePitch(lastPitch, pitch)\r
- lastPitch = pitch\r
- else:\r
- octave = note[1:]\r
- result += note[0] + accidental + octave + ' '\r
- result += '>' +chordDur +' '\r
- lastPitch = chord1[0][0] + lastClef\r
- else: # 2 voices\r
- result += ' << ' \r
- for i in range(len(chord2)):\r
- (pitch,accidental,duration ) = chord2[i]\r
- pitch += lastClef\r
- note = scale[pitch]\r
- \r
- if (accidental!='auto'):\r
- currentKey[note[0]] = accidental\r
- accidental = currentKey[note[0]]\r
- \r
- if (relativePitch):\r
- octave = getRelativePitch(lastPitch, pitch)\r
- lastPitch = pitch\r
- else:\r
- octave = note[1:]\r
- result += note[0] + accidental + octave + duration + ' '\r
- \r
- result += " \\\\ {"\r
- \r
- for i in range(len(chord1)):\r
- (pitch,accidental ) = chord1[i]\r
- pitch += lastClef\r
- note = scale[pitch]\r
- \r
- if (accidental!='auto'):\r
- currentKey[note[0]] = accidental\r
- accidental = currentKey[note[0]]\r
- \r
- if (relativePitch):\r
- octave = getRelativePitch(lastPitch, pitch)\r
- lastPitch = pitch\r
- else:\r
- octave = note[1:]\r
- result += note[0] + accidental + octave +chordDur + ' '\r
- if lastChord >0 : lastChord = durVal(duration) - durVal(chordDur)\r
- if lastChord==0: result += ' } >> '\r
- # end 2 voices\r
- lastDuration = chordDur\r
- \r
- # check if duration / stem / same \r
- # < >duration ties,beam, slurs\r
- \r
- # Pedal\r
- elif data=='\x0b':\r
- print 'Ped '\r
- data = data = nwcData.read(5)\r
- # midi control instruction / MPC\r
- elif data=='\x0d':\r
- print 'midi control instruction'\r
- data = data = nwcData.read(36)\r
- # fermata / Breath mark\r
- elif data=='\x0E':\r
- print "Fermata"\r
- data = nwcData.read(6)\r
- extra += "\\fermata" \r
- \r
- # Dynamics\r
- elif data=='\x0f':\r
- print "Dynamics"\r
- data = nwcData.read(5)\r
- \r
- # Performance Style\r
- elif data=='\x10':\r
- print "Performance Style"\r
- data = nwcData.read(5)\r
- \r
- # Instrument Patch\r
- elif data=='\x04':\r
- print "Instrument Patch"\r
- data = nwcData.read(10)\r
- \r
- \r
- # todo\r
- else :\r
- print "WARNING: Unrecognised token ",binascii.hexlify(data), " at #", nwcData.tell(), " at Token", token\r
- \r
- \r
- \r
- # output converted file?\r
- print "\nStats"\r
- print keysigCount, " keysigCount found"\r
- print noteCount, " notes found"\r
- print staffCount, " staffCount found"\r
- print clefCount, " clefCount found"\r
- print barlineCount, " barlineCount found"\r
- print timesigCount, " timesigCount found"\r
- print textCount, " textCount found"\r
- print dynamicCount, " dynamicCount found"\r
- print restCount, " restCount found"\r
- \r
- #print "\nLilypond format:\n"\r
- return result\r
- \r
-# Variables\r
-keysigs = {\r
-'00000000' : 'c \major % or a \minor' ,\r
-'00000020' : 'g \major % or e \minor' ,\r
-'00000024': 'd \major % or b \minor' ,\r
-'00000064' : 'a \major % or fis \minor' ,\r
-'0000006c' : 'e \major % or cis \minor' ,\r
-'0000006d' : 'b \major % or gis \minor' ,\r
-'0000007d' : 'fis \major % or dis \minor' ,\r
-'0000007f' : 'cis \major % or ais \minor' ,\r
-'00020000' : 'f \major % or d \minor' ,\r
-'00120000' : 'bes \major % or g \minor' ,\r
-'00130000' : 'ees \major % or c \minor' ,\r
-'001b0000' : 'aes \major % or f \minor' ,\r
-'005b0000' : 'des \major % or bes \minor' ,\r
-'005f0000' : 'ges \major % or ees \minor' ,\r
-'007f0000' : 'ces \major % or a \minor'\r
-}\r
-\r
-acdts = ( 'is', 'es', '' ,'isis', 'eses', 'auto' ) \r
-\r
-clefs = { 0 : "b'",\r
- 1 : "d",\r
- 2 : "c'",\r
- 3 : "a'",\r
- }\r
-\r
-clefNames = { 0: 'treble',\r
- 1: 'bass',\r
- 2: 'alto',\r
- 3: 'tenor',\r
- }\r
-octaves = { 0: 0, 1:7, 2:-7 }\r
-scale = [ # this list is taken from lilycomp\r
- "c,,,","d,,,","e,,,","f,,,","g,,,","a,,,","b,,,",\r
- "c,,","d,,","e,,","f,,","g,,","a,,","b,,",\r
- "c,","d,","e,","f,","g,","a,","b,",\r
- "c","d","e","f","g","a","b",\r
- "c'","d'","e'","f'","g'","a'","b'",\r
- "c''","d''","e''","f''","g''","a''","b''",\r
- "c'''","d'''","e'''","f'''","g'''","a'''","b'''",\r
- "c''''","d''''","e''''","f''''","g''''","a''''","b''''",\r
- ]\r
-\r
-stems = [ '\stemNeutral ', '\stemUp ', '\stemDown ']\r
-\r
-slurs = [ '', '(' , ')', '' ]\r
-\r
-triplets = [ \r
- ('' , '' ),\r
- ( '\\times 2/3 { ', '') ,\r
- ('' , '' ),\r
- ('' , ' }' ),\r
- ]\r
-\r
-durations = ( '1','2','4','8','16','32','64' ) \r
-\r
-barlines = (\r
- '|', # 'Single'\r
- '||', # 'Double'\r
- '.|', # SectionOpen\r
- '|.', # SectionClose\r
- '|:', # MasterRepeatOpen\r
- ':|', # MasterRepeatClose\r
- '|:', # LocalRepeatOpen\r
- ':|', # LocalRepeatClose\r
-)\r
-\r
-ending = (\r
-'|.', # SectionClose\r
-':|', # MasterRepeatClose\r
-'|', # 'Single'\r
-'||', # 'Double'\r
-'' # Open hidden\r
-)\r
-\r
-staffType = (\r
-'Standard' , # Standard\r
-'Upper Grand Staff' , # Upper Grand Staff\r
-'Lower Grand Staff' , # Lower Grand Staff\r
-'Orchestra' , # Orchestra\r
-)\r
-\r
-\r
-beams = [ '', '[', '',']' ]\r
-\r
-\r
-# end ' \bar "|."'\r
-\r
-# Notation Properties\r
-# extra accidental spacing\r
-# extra note spacing\r
-# muted\r
-# no ledger lines\r
-# slurdirection\r
-# tiedirection\r
-# lyricsyllable\r
-# visability \r
-# show printed\r
-# item color\r
-\r
-#dynamics\r
-# cmd = DynamicVariance\r
-# Decrescendo \setTextCresc \<\r
-# setTextCresc Crescendo \> setHairpinCresc\r
-# Dynamics stop '\! '\r
-# style = ff pp\r
-\r
-clefOctave = [ '' , '^8', '_8' , '' ]\r
-clefShift = [0,7,-7, 0]\r
-\r
-\r
-# '#(set-accidental-style '#39'modern-cautionary)'\r
-#(ly:set-point-and-click 'line-column)\r
-#(set-global-staff-size 20)\r
-\r
-timesigValues = { \r
- '4/4' : '1', '3/4' : '2.', '2/4' : '2', '1/4' : '1',\r
- '1/8' : '8', '2/8' : '4', '3/8' : '4.', '6/8' : '2.',\r
- '4/8' : '2', '9/8' : '12', '12/8' : '1',\r
- '2/2' : '1', '4/2' : '0', '1/2' : '2', \r
- }\r
-\r
-print "python nwc2ly is running..."\r
-try:\r
-\r
- nwcData = open( nwcfile,'rb')\r
- \r
- # check if its a readable nwc format\r
- # compressed - [NWZ]\r
- # uncompressed - [NoteWorthy ArtWare] [NoteWorthy Composer]\r
- format = nwcData.read(5)\r
- if format== '[NWZ]':\r
- nwcData.seek(1,1)\r
- print 'Compressed NWC detected!'\r
- print 'Dumping to uncompressed NWC format and attemping conversion soon...'\r
- uncompress = open ('uncompressed.nwc','wb')\r
- uncompress.write(zlib.decompress(nwcData.read()))\r
- uncompress.close()\r
- print 'Inflating done. Now opening new file...'\r
- nwcData.close()\r
- nwcData = open( 'uncompressed.nwc','rb')\r
- nwcData.seek(6)\r
- elif format!= '[Note':\r
- print 'Unknown format, please use an uncompress NWC format and try again.' \r
- sys.exit()\r
- \r
- \r
- \r
- resultFile = '%% Generated from python nwc2ly converter v%s by Joshua Koo (joshuakoo@myrealbox.com)' % nwc2lyversion\r
- resultFile += '\n\n\\version "2.4.0"'\r
- resultFile += "\n"\r
- \r
- \r
- # START WORK\r
- getFileFormat(nwcData)\r
- resultFile+=getFileInfo(nwcData)\r
- resultFile+= "\n\n\\score {"\r
- resultFile+= "\n\t<<\n\t\t"\r
- \r
- getPageSetup(nwcData)\r
- \r
- noOfStaffs = findNoOfStaff(nwcData);\r
- \r
- for staff in range(1,noOfStaffs+1):\r
- print "\n\nWorking on Staff", staff\r
- result = processStaff(nwcData)\r
- #print result\r
- resultFile += result\r
- \r
- resultFile+= "\n\t>>"\r
- resultFile+= "\n\t\layout {}"\r
- resultFile+= "\n\t\midi {}"\r
- resultFile+= "\n}"\r
- nwcData.close()\r
- \r
- if lyfile=='':\r
- print 'Dumping output file to screen'\r
- print resultFile\r
- else :\r
- write = open( lyfile ,'w')\r
- write.write (resultFile)\r
- write.close()\r
-\r
-except IOError:\r
- print 'File does not exist or an IO error occurred'\r
-except Exception, e: #KeyError\r
- print "Error while reading data at ", nwcData.tell() ,"\n"\r
- print 'Dumping whatever result first'\r
- print resultFile\r
- print result\r
- print\r
- traceback.print_exc()\r
-\r
-print\r
-print\r
-print "Please send all bugs and requests to joshuakoo@myrealbox.com"\r
+import binascii, sys, zlib, traceback
+from ConfigParser import SafeConfigParser
+
+shortcopyleft = """
+nwc2ly - Converts NWC(v 1.75) to LY fileformat
+Copyright (C) 2005 Joshua Koo (joshuakoo @ myrealbox.com)
+and Hans de Rijck (hans @ octet.nl)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+"""
+
+##
+# most infomation obtained about the nwc format
+# is by using noteworthycomposer and the somewhat like the french cafe method
+# (http://samba.org/ftp/tridge/misc/french_cafe.txt)
+#
+#
+##
+# Revisions
+# 0.1 07 april 2005 initial hex parsing;
+# 0.2 13 april 2005 added multiple staff, keysig, dots, durations
+# 0.3 14 april 2005 clef, key sig detection, absolute notes pitching
+# 0.4 15 April 2005 Relative Pitchs, Durations, Accidentals, Stem Up/Down, Beam, Tie
+# 0.5 16 April 2005 Bug fixes, Generate ly score , Write to file, Time Sig, Triplets, Experimental chords
+# 0.6 17 April 2005 Compressed NWC file Supported!
+# 0.7 19 April 2005 Version detection, Header
+# 20 April 2005 BUGS FiXes, small Syntax changes
+# 21 April 2005 Still fixing aimlessly
+# 23 April 2005 Chords Improvement
+# 24 April 2005 staccato, accent, tenuto. dynamics, midi detection (but unsupported)
+# 0.8 24 April 2005 Experimental Lyrics Support
+# 0.9 29 April 2005 Workround for \acciaccatura, simple Check full bar rest adjustment
+# 1.0 10 July 2005 Hans de Rijck,
+# added dynamics, dynamic variance, tempo, tempo variance,
+# performance style, page layout properties
+# corrected barlines, lyrics, slurs, natural accidentals
+# using inifile for settings
+# limited support for NWC version 2.0
+#
+##
+# TODO
+# Proper syntax and structure for staffs, lyrics, layering
+# version 1.7 Support
+# nwc2ly in lilytool
+#
+# Piano Staff
+# Chords
+# Midi Instruments
+# Visability
+# Lyrics
+# Context Staff
+# Staff layering / Merging
+##
+#
+# BUGS text markups, chords
+######
+#
+# cd /cygdrive/c/development/nwc2ly
+# $ python nwc2ly.py lvb7th1\ uncompressed.nwc test.ly > convert.log
+#######
+
+#################################
+# Options #
+#################################
+
+cp = SafeConfigParser()
+cp.read( 'C:\development\nwc2ly\hans version\nwc2ly.ini' )
+#/cygdrive/C/development/nwc2ly/hans\ version/
+debug = int(cp.get('settings', 'debug'))
+relativePitch = int(cp.get('settings', 'relativePitch'))
+relativeDuration = int(cp.get('settings', 'relativeDuration'))
+barLinesComments = int(cp.get('settings', 'barLinesComments'))
+
+insertBeaming = int(cp.get('settings', 'insertBeaming'))
+insertSteming = int(cp.get('settings', 'insertSteming'))
+insertText = int(cp.get('settings', 'insertText'))
+
+paperSize = cp.get('settings', 'Papersize')
+fillLast = int(cp.get('settings', 'fillLast'))
+
+LilyPondVersion = cp.get('settings', 'LilyPondVersion')
+
+stdGrace = cp.get('settings', 'stdGrace')
+accidentalStyle = cp.get('settings', 'accidentalStyle')
+
+#################################
+# /Options #
+#################################
+
+global measureStart
+global nwcversion
+
+nwc2lyversion = '1.0'
+
+##############
+
+args = len(sys.argv)
+if args<2:
+ print "Syntax: python nwc2ly.py nwcfile [lyfile]"
+ sys.exit()
+nwcfile = sys.argv[1]
+
+if args<3:
+ lyfile = ''
+else:
+ lyfile = sys.argv[2]
+
+
+
+def getFileFormat(nwcData):
+ global nwcversion
+ #'[NoteWorthy ArtWare]'
+ #'[NoteWorthy Composer]'
+ nwcData.seek(0)
+ company = readLn(nwcData)
+ nwcData.seek(2,1) # pad
+ product = readLn(nwcData)
+ if debug: print "product: ", product
+ #version = readLn(nwcData)
+
+ version = nwcData.read(3)
+ if debug: print " version: ", binascii.hexlify(version)
+ huh = nwcData.read(1)
+ version = ord(version[0]) * 0.01 + ord(version[1])
+ nwcversion = version
+ print 'NWC file version', nwcversion, 'detected!'
+ pad(nwcData,2) # times saved
+ name1 = readLn(nwcData)
+ name2 = readLn(nwcData)
+
+ pad(nwcData,8)
+ huh = nwcData.read(1)
+ pad(nwcData,1)
+
+def getFileInfo(nwcData):
+ title = readLn(nwcData)
+ author = readLn(nwcData)
+ copyright1 = readLn(nwcData)
+ copyright2 = readLn(nwcData)
+ if nwcversion == 2.0 : whatsIt = readLn(nwcData)
+ comments = readLn(nwcData)
+
+ header = "\\header {"
+ header += "\n\ttitle = \"%s\"" % title
+ header += "\n\tcomposer = \"%s\"" % author
+ header += "\n\tcopyright = \\markup \\teeny \"%s\"" % copyright1
+ header += "\n\tfooter = \"%s\"" % copyright2
+ header += "\n\t%%{ %s %%}" % comments
+ header += "\n}"
+
+ # TO ADD IN DEFAULT BLANK FIELDS TO KEY IN
+ print 'title,author,copyright1,copyright2,comments: ', (title,author,copyright1,copyright2,comments)
+ return header
+
+# Page Setup
+def getPageSetup(nwcData):
+ # ??
+ margins = getMargins(nwcData)
+ #getContents(nwcData)
+ #getOptions(nwcData)
+ staffSize = getFonts(nwcData)
+ barlineCount = 0
+ return margins, staffSize
+
+def getMargins(nwcData):
+ global measureStart
+ #readTill(nwcData,'\x01') # not correct, should read 9 bytes (HdR)
+ temp = nwcData.read(9)
+ if debug : print "skipping ", binascii.hexlify(temp)
+ measureStart = ord( nwcData.read(1) )
+ pad(nwcData,1)
+ # get string size 43
+ margins = readLn(nwcData)
+ print 'Start measure ', measureStart
+ print 'margins ', margins
+ #mirrorMargines
+ #UOM
+ return margins
+
+def getOptions(nwcData):
+ # page numbering, from
+ # title page info
+ # extend last system
+ # increase note spacing for larger note duration
+ # staff size
+ # staff labels (none, first systems, top systems, all systems
+ # measure numbers none, plain, circled, boxed
+ # measure start
+ return
+
+def getFonts(nwcData):
+ # 12 Times
+ #readTill(nwcData,'\xFF') #not correct, should read 36 bytes (HdR)
+ nwcData.read(36)
+ n = nwcData.read(1)
+ print "Staff size: ", ord(n)
+ pad(nwcData,1)
+ for i in range (12):
+ # Font Name
+ font = readLn (nwcData)
+
+ # 00
+
+ # Style 'Regular' 'Italic' 'Bold' 'Bold Italic'
+ style = ord(nwcData.read(1)) & 3
+
+ # Size
+ size = ord(nwcData.read(1))
+
+ ## 00
+ nwcData.seek(1,1)
+
+ # Typeface
+ # 00 Western, b1 Hebrew
+ typeface = nwcData.read(1)
+
+ if debug: print 'Font detected' , font, 'size',size, 'style ', style, ' typeface',typeface
+
+ return ord(n)
+
+def findNoOfStaff(nwcData):
+ # Infomation on Staffs \x08 00 00 FF 00 00 n
+ data = 0;
+
+ readTill(nwcData,'\xFF')
+ if debug: print "Where am I? ", nwcData.tell()
+
+ nwcData.read(2)
+
+ layering = nwcData.read(1) # FF or 00
+
+ noOfStaffs = ord(nwcData.read(1))
+ nwcData.read(1)
+ if debug: print noOfStaffs, " noOfStaffs found"
+ return noOfStaffs
+
+def findStaffInfo(nwcData):
+ # Properties for Staff
+ # General
+ # Name.
+ # Group
+ # Ending Bar
+ # Visual
+ # Verticle Upper Size
+ # Verticle Lower Size
+ # Style
+ # Layer Next Staff
+ # Color
+ # Midi
+ # Part Volume
+ # Stereo Pan
+ # Transposition
+ # Muted
+ # PlayBack Device
+ # Playback Channel
+ # Instrument
+ # Patch Name
+ # Patch List Type
+ # Bank Select
+ # Controller0
+ # Controller32
+ # Staff Lyrics
+ # LineCount
+ # AlignSyllableRule
+ # StaffPlacementAligment
+ # StaffPlacementOffset
+ # StaffPropertiesVerticleSizeUpper
+ # StaffPropertiesVerticleSizeLower
+
+ format = ''
+ staffName = readLn(nwcData)
+ format += "\\context Staff = %s " % staffName # or voice or lyrics
+
+ groupName = readLn(nwcData) # HOW TO ORGANISE THEM??
+
+ endbar = ord(nwcData.read(1)) & 7 # mask all but last bits
+ print 'end ',endbar
+ endingBar = ending[endbar] # 10 --> OC for lyrics? 10000 1100
+
+ muted = ord(nwcData.read(1)) & 1
+ nwcData.read(1)
+
+ channel = ord(nwcData.read(1)) + 1
+ nwcData.read(9)
+
+ stafftype = staffType[ord(nwcData.read(1))&3]
+ nwcData.read(1)
+
+ uppersize = 256 - ord(nwcData.read(1)) # - signed +1 )& 2^7-1 )
+ readTill(nwcData,'\xFF')
+
+ lowersize = ord(nwcData.read(1))
+ ww = nwcData.read(1)
+ print '[uppersize,lowersize]',[uppersize,lowersize]
+
+ noOfLines = ord(nwcData.read(1))
+ print '[staffName,groupName,endingBar,stafftype,noOfLines]', [staffName,groupName,endingBar,stafftype,noOfLines]
+
+ layer = ord(nwcData.read(1)) & 1
+
+ # signed transposition
+ # FF?
+
+ partVolume = ord(nwcData.read(1))
+ ord(nwcData.read(1))
+
+ stereoPan = ord(nwcData.read(1))
+ if nwcversion == 1.7:
+ nwcData.read(2)
+ else:
+ nwcData.read(3)
+
+ nwcData.read(2)
+ #lyrics = ord(nwcData.read(1)) & 1
+ lyrics = readInt(nwcData)
+ noOfLyrics = readInt(nwcData)
+
+ lyricsContent = ''
+ if lyrics:
+ lyricOptions = readInt(nwcData)
+ nwcData.read(3)
+ for i in range(noOfLyrics):
+ print 'looping ',i, 'where', nwcData.tell(), 'NoOfLyrics:', noOfLyrics
+ #lyricsContent += '\\ \lyricmode { ' # lyrics
+ lyricsContent = str( getLyrics(nwcData) ) #
+ #lyricsContent += '}'
+ nwcData.read(1)
+
+ nwcData.read(1)
+ color = ord(nwcData.read(1)) & 3 #12
+
+ noOfTokens = readInt(nwcData)
+ print noOfTokens, " Tokens found", nwcData.tell()
+ return staffName, endingBar, noOfTokens, format, lyricsContent
+
+def pad(nwcData, length):
+ nwcData.seek(length,1)
+
+def readTill(nwcData, delimit):
+ data = ''
+ value = ''
+ while data!=delimit:
+ value += data
+ data = nwcData.read(1)
+
+ return value
+
+def readLn(nwcData):
+ return readTill (nwcData,'\x00')
+ # reads until 00 is hit
+ # od oa == \n
+
+def readInt(nwcData):
+ data = nwcData.read(2)
+ no = ord(data[0])
+ no += ord(data[1]) * 256
+ return no
+
+
+def getLyrics(nwcData):
+
+ data = ''
+ print 'reach'
+ data = nwcData.read(1)
+ if data == '': return
+ blocks = ord( data )
+ if blocks==4: blocks = 1
+ if blocks==8: blocks = 2
+ if blocks == 0: return
+ data = ''
+ lyricsLen = readInt(nwcData)
+
+ print 'blocks ',blocks, 'lyrics len', lyricsLen, 'at ', nwcData.tell()
+
+ nwcData.read(1)
+ for i in range (blocks):
+ data += nwcData.read(1024)
+
+ lyrics = data[1:lyricsLen-1]
+
+ lyrics = lyrics.replace( "\x00", "_ " )
+
+ print 'lyrics ', lyrics
+ return lyrics
+
+def getDuration(data):
+ durationBit = ord(data[2]) & 7
+ durationDotBit = ord(data[6])
+
+ duration = durations[durationBit]
+ absDuration = revDurations[durationBit]
+ if (durationDotBit & 1<<2):
+ durationDot = '.'
+ absDuration += revDurations[durationBit + 1]
+ elif (durationDotBit & 1):
+ durationDot = '..'
+ absDuration += revDurations[durationBit + 1] + revDurations[durationBit + 1]
+ else :
+ durationDot = ''
+ return duration + durationDot
+
+def getKey(data):
+ data = binascii.hexlify(data)
+
+ if (keysigs.has_key(data)):
+ return '\key ' + keysigs[data]
+ return '% unknown key'
+
+def getLocation(data):
+ offset = ord(data[8]);
+ if offset > 127 :
+ return 256-offset
+
+ #next statement doesn't work for me (HdR)
+ #if (ord(data[9])>>3 & 1):
+ # return -offset
+
+ return -offset
+
+ return offset
+
+def getAccidental(data):
+ data = ord(data)
+ data = (data & 7 )
+ return acdts[data]
+
+def getDynVariance(data):
+ data = ord(data)
+ data = (data & 7 )
+ return dynVariance[data]
+
+def getPerfStyle(data):
+ data = ord(data)
+ temp = '_\\markup {\\small \\italic \\bold {' + perfStyle[data] + '}}'
+ return temp
+
+def getTempoVariance(data):
+ data = ord(data)
+ if data == 0 or data == 1 :
+ temp = '\\' + tempoVariance[ data ]
+ else:
+ temp = '_\\markup {\\small \\italic \\bold {' + tempoVariance[data] + '}}'
+ return temp
+
+def getNote(data):
+
+ # pitch
+ pitch = getLocation(data)
+
+ # get Accidentals
+ accidental = getAccidental(data[9])
+
+ # get Relative Duration
+ duration = getDuration(data)
+
+ # check stems
+ stem = ord(data[4])
+ stem = (stem >> 4) & 3
+
+ # check beam
+ beam = ord(data[4]) & 3
+
+ # triplets
+ triplet = triplets [ord(data[4])>>2 & 3 ]
+
+ # check tie
+ tie = ''
+ if ord(data[6]) >> 4 & 1:
+ tie = '~'
+
+ staccato = (ord(data[6]) >> 1) & 1
+ accent = (ord(data[6]) >> 5) & 1
+
+ tenuto = (ord(data[7]) >> 2) & 1
+ grace = (ord(data[7]) >> 5) & 1
+
+ # check slur
+ slur = slurs[ord(data[7]) & 3 ]
+ #if debug: print "Slur ", ord(data[7]), slur
+
+ #TODO should use a dictionary
+ return (pitch, accidental, duration, stem, beam, triplet, slur, tie, grace, staccato, accent, tenuto)
+
+def getRelativePitch(lastPitch, pitch):
+ octave = ''
+ diff = pitch - lastPitch
+ if diff>3:
+ for i in range((diff-4 + 7)/7):
+ octave += "'"
+ if octave == '':
+ octave += "'"
+ elif diff<-3:
+ for i in range((-diff-4 + 7)/7):
+ octave += ","
+ if octave == '':
+ octave += ","
+ return octave
+
+def durVal(duration):
+ where = duration.find('.')
+
+ if where>-1:
+ durVal = 128/int (duration[:where])
+ nextVal = durVal
+ for i in range(len(duration)-where):
+ nextVal = nextVal / 2
+ durVal += nextVal
+
+ else:
+ durVal = 128/int (duration)
+ return durVal
+
+def processStaff(nwcData):
+ keysigCount =0
+ timesigCount=0
+ noteCount=0
+ restCount=0
+ staffCount=0
+ clefCount=0
+ textCount=0
+ tempoCount=0
+ barlineCount = measureStart - 1
+ dynamicCount = 0
+
+ lastPitch = scale.index('c')
+ lastDuration = 0
+ lastClef = scale.index(clefs[0]) # index referenced to note of last clef
+ lastStem = 0
+ lastTimesig = 1
+
+ lastKey = { 'c': '', #c
+ 'd': '', 'e': '', 'f': '', 'g': '', 'a': '', 'b': '' }
+ currentKey = lastKey.copy()
+
+ data = 0
+ token = 1
+
+ result = ""
+ result += "\n\t\\new Staff {\n\t" + "#(set-accidental-style '" + accidentalStyle + ") "
+ lastChord = 0
+ lastGrace = 0;
+ lastSlur = ' ';
+
+ (staffName, endingBar, noOfTokens, format, lyrics) = findStaffInfo(nwcData);
+ if debug: print "staff info: name, endingbar, noOfTokens, format, lyrics-"
+ if debug: print staffName, endingBar, noOfTokens, format, lyrics
+
+ if relativePitch:
+ result+="\\relative c {"
+ else :
+ result+=" {"
+
+ result+= '\n\n\t% Staff ' + str(staff) + '\t\t(' + staffName + ')\n\n\t'
+ result+= '\\set Staff.instrument = #\"' + staffName + '\"\n\t'
+ result+= '\\set Score.skipBars = ##t\n\n\t'
+
+ #print "00112233445566778899\n"
+ extra = ''
+ dynamic = ''
+ style = ''
+ # the juice
+
+ dualVoice = 0
+ while data!="":
+
+ token += 1
+ if token==noOfTokens:
+ result += "\\bar \"" + endingBar + "\"\n\t\t"
+
+ if dualVoice == 1: # no beams and slurs with two voices
+ result += "%Todo: check for slurs and beams in the bar above\n\t\t"
+ dualVoice = 0
+
+ result += "}\n\t"
+ if lyrics!='':
+ result += '\n\t\t\\addlyrics{ ' + lyrics + '}'
+ result += "\n\t}\n\t"
+ print "going next staff! %s" % nwcData.tell()
+ break
+
+
+ if nwcversion==1.7:
+ nwcData.seek(2,1)
+
+ data = nwcData.read(1)
+ #print 'test', data
+
+ # clef
+ if data=='\x00':
+ data = nwcData.read(6)
+ clefCount += 1
+ if debug: print binascii.hexlify(data), ' = clef ',
+
+ key = ord(data[2]) & 3
+ octave = ord(data[4]) & 3
+ # print binascii.hexlify(data) , "CLEF? "
+ lastClef = scale.index(clefs[key]) + octaves[octave]
+ #TODO check for octave shifts _8
+ #lastClef += clefShift[octave] # on ottava don't shift, just print 8va
+ if debug: print clefNames[key], clefOctave[octave]
+ result += '\clef "' + clefNames[key] + clefOctave[octave]+ '"\n\t\t'
+
+ # key signature
+ elif data=='\x01':
+ data = nwcData.read(12)
+ keysigCount = keysigCount + 1
+ if debug: print binascii.hexlify(data), ' = Key signature ',
+
+ #
+ flatBits = ord(data[2])
+ sharpBits = ord(data[4])
+
+ for note in lastKey.keys():
+ noteInd = ['a','b','c','d','e','f','g'].index(note)
+ if (flatBits >> noteInd & 1):
+ lastKey[note] = 'es'
+ elif (sharpBits >> noteInd & 1):
+ lastKey[note] = 'is'
+ else:
+ lastKey[note] = ''
+
+ currentKey = lastKey.copy()
+ if debug: print getKey(data[1:5])
+ result = result + getKey(data[1:5]) + "\n\t\t"
+
+ #print "data", binascii.hexlify(data)
+ #print "flat", binascii.hexlify(flatBits)
+ #print "sharp", binascii.hexlify(data[4])
+ #print getKey(data[1:5])
+
+
+ # barline
+ elif data=='\x02':
+ data = nwcData.read(4)
+ #if debug: print ' = Barline ', barlines[ ord(data[2]) ]
+ #if debug: print binascii.hexlify(data)
+ barlineCount += 1
+ currentKey = lastKey.copy()
+
+ if ( data[2] == '\x00' ):
+ result += "|\n\t\t"
+ else:
+ result += "\\bar \"" + barlines[ ord(data[2]) ] + "\"\n\t\t"
+
+ if dualVoice == 1: # no beams and slurs with two voices
+ result += "%Todo: check for slurs and beams in the bar above\n\t\t"
+
+ if (barlineCount % barLinesComments == 0):
+ result += "\n\t\t% Bar " + str(barlineCount + 1) + "\n\t\t"
+ #print '.',
+ print 'Bar ', barlineCount, ' completed,'
+
+ dualVoice = 0
+ # Repeat
+
+ elif data=='\x03':
+ if debug: print "Repeat",
+ data = nwcData.read(4)
+ if debug: print binascii.hexlify(data),
+ if debug: print " = repeat: ", ord( data[2] )
+ result += "%Todo: place alternatives for \\repeat volta " + str(ord( data[2] )) + "\n\t\t"
+
+ # Instrument Patch
+ elif data=='\x04':
+ if debug: print "Instrument Patch",
+ data = nwcData.read(10)
+ if debug: print binascii.hexlify(data)
+ #readLn(nwcData)
+ #readLn(nwcData)
+ #readLn(nwcData)
+
+ # timesig
+ elif data=='\x05':
+ data = nwcData.read(8)
+ if debug: print binascii.hexlify(data),
+ timesigCount = timesigCount + 1
+ beats = ord(data[2])
+ beatValues = [ 1, 2, 4, 8 ,6, 32 ]
+ beatValue = beatValues[ord(data[4])]
+ timesig = str(beats) + "/" + str(beatValue)
+ if debug: print ' = Timesig', timesig
+ lastTimesig = timesigValues[timesig]
+ result += "\\time " + timesig + " "
+
+ # Tempo
+ elif data=='\x06':
+ if debug: print "Tempo ",
+ data = nwcData.read(7)
+ if debug: print binascii.hexlify(data)
+ tempo = readLn(nwcData)
+
+ # byte 4 length, byte 6 note,
+ tempoNote = data[6]
+ tempoDuration = ord(data[4])
+ if debug: print "duration ", tempoDuration
+
+ if ( data[6] == '\x00' ):
+ tempoNote = '8'
+ tempoMultiply = int( tempoDuration * 2)
+ elif ( data[6] == '\x01' ):
+ tempoNote = '8.'
+ tempoMultiply = int( tempoDuration / 0.75 )
+ elif ( data[6] == '\x02' ):
+ tempoNote = '4'
+ tempoMultiply = tempoDuration
+ elif ( data[6] == '\x03' ):
+ tempoNote = '4.'
+ tempoMultiply = int( tempoDuration / 1.5)
+ elif ( data[6] == '\x04' ):
+ tempoNote = '2'
+ tempoMultiply = int( tempoDuration / 2)
+ elif ( data[6] == '\x05' ):
+ tempoNote = '2.'
+ tempoMultiply = int( tempoDuration / 3)
+
+ result += '\n\t\t\\tempo ' + tempoNote + '=' + str( tempoMultiply ) + ' '
+ tempoCount = tempoCount + 1
+
+ # dynamics
+ elif data=='\x07':
+ dynamicCount = dynamicCount + 1
+ data = nwcData.read(9)
+ if debug: print binascii.hexlify(data),
+ dynamic = dynamics[ ord(data[4]) & 7 ]
+ if debug: print ' = Dynamic ' + dynamic
+
+ # note
+ elif data=='\x08':
+ data = nwcData.read(10)
+ noteCount = noteCount + 1
+
+ if debug: print 'note ', binascii.hexlify(data) , noteCount , nwcData.tell(),
+
+ (pitch, accidental, duration, stem, beam, triplet, slur, tie, grace, staccato, accent, tenuto) = getNote(data)
+
+ if debug: print pitch, accidental, duration, stem, beam, triplet, slur, tie, grace, staccato, accent, tenuto
+
+
+ articulate = ''
+ if staccato: articulate+= '-.'
+ if accent: articulate+= '->'
+ if tenuto: articulate+= '--'
+
+ beam = beams[beam]
+
+ chordMatters = ''
+ if lastChord>0 and beam==']' :
+ if debug: print 'Chord ] ', durVal(duration), lastChord
+ chordMatters = ' } >> '
+ lastChord = 0
+ elif lastChord>0:
+ if debug: print 'Chord last ', durVal(duration), lastChord
+ dur = durVal(duration)
+ #lastChord = 1.0/((1.0 / lastChord) - (1.0/durVal(duration)))
+ lastChord -= dur
+
+ if lastChord <= 0 :
+ chordMatters = ' } >> '
+ lastChord = 0
+
+
+
+ if not insertBeaming: beam = ''
+
+ # pitch
+ pitch += lastClef
+ note = scale[pitch]
+
+ natural = ''
+
+ # get Accidentals
+ if ( accidental == '!' ) : # also do forced naturals
+ natural = accidental
+ accidental = ''
+
+ if (accidental!='auto'):
+ currentKey[note[0]] = accidental
+
+ accidental = currentKey[note[0]]
+
+ if (relativePitch):
+ octave = getRelativePitch(lastPitch, pitch)
+ lastPitch = pitch
+ else:
+ octave = note[1:]
+ pitch = note[0] + accidental + octave
+
+ # get Relative Duration
+ if (relativeDuration):
+ if (lastDuration==duration):
+ duration = ''
+ else:
+ lastDuration = duration
+
+ # check stems
+ if insertSteming and (stem!= lastStem) :
+ lastStem = stem
+ stem = stems[stem]
+ else :
+ stem = ''
+
+ # normal note
+ if extra!='':
+ extra = '-"' + extra + '"'
+
+ if grace and not lastGrace: result += '\\' + stdGrace + " { "
+
+ if nwcversion == 2.0:
+ if ( slur == ' ' or slur == '' ) and lastSlur == '(' :
+ slur = ')'
+ lastSlur = ' '
+ if debug : print ' slur closed'
+ elif slur == '(' and lastSlur == '(' :
+ slur = ' '
+ lastSlur = '('
+ if debug : print ' slur continued'
+ elif slur == '(' and lastSlur == ' ' :
+ slur = '('
+ lastSlur = '('
+ if debug : print ' slur opened'
+
+ if dualVoice == 1: # no beams and slurs with two voices
+ beam = ''
+ slur = ''
+
+ if not grace and lastGrace: result += " } "
+ result += triplet[0] + stem + pitch + natural + duration + articulate + dynamic + style + extra
+ result += slur + tie + beam + triplet[1] +chordMatters + " "
+
+
+ # reset
+ lastGrace = grace
+ extra = ''
+ dynamic = ''
+ style = ''
+ # rest
+ elif data=='\x09':
+ data = nwcData.read(10)
+ if debug: print 'rest ', binascii.hexlify(data) , noteCount , nwcData.tell()
+ (pitch, accidental, duration, stem, beam, triplet, slur, tie, grace, staccato, accent, tenuto) = getNote(data)
+
+ restCount = restCount + 1
+
+ # get Relative Duration
+ duration = getDuration(data)
+ if duration == '1':
+ duration = lastTimesig
+ if (relativeDuration):
+ if (lastDuration==duration):
+ duration = ''
+ else:
+ lastDuration = duration
+
+ result = result + triplet[0] + 'r' + str(duration) + dynamic + triplet[1] + " "
+ dynamic = ''
+
+ #chord starting with a rest
+ elif data == '\x12':
+ data = nwcData.read(12) # rest info now in data
+ print binascii.hexlify(data), "Chord started with rest. Rest skipped for now"
+ (pitch, accidental, duration, stem, beam, triplet, slur, tie, grace, staccato, accent, tenuto) = getNote(data)
+ result += "\n\t\t\\mark \\markup {r" + duration + "}\n\t\t%Todo: Above rest must be added to next chord\n\t\t"
+ token -= 1 #doesn't count as token
+
+ # chord
+ elif data=='\x0A' : # or data=='\x12':
+ if data == '\x0a' :
+ data = nwcData.read(12)
+
+ chordAmt = ord(data[10])
+ chords = []
+ chordDur = getDuration(data)
+ #print 'duration',chordDur
+
+ print binascii.hexlify(data), "Chord ", chordDur, chordAmt
+ #print 'no. of notes in chord' , chordAmt
+
+ chord1 = []
+ chord2 = []
+
+ for i in range(chordAmt):
+ # rest or note
+ what = nwcData.read(1)
+ data = nwcData.read(10)
+ ha = getNote(data)
+
+ noteCount = noteCount + 1
+ if debug: print 'chord ', binascii.hexlify(data) , noteCount , nwcData.tell(),
+ (pitch, accidental, duration, stem, beam, triplet, slur, tie, grace, staccato, accent, tenuto) = ha
+ if debug: print pitch, accidental, duration, stem, beam, triplet, slur, tie, grace, staccato, accent, tenuto
+
+ # add to list
+ if ha[2] == chordDur or len(chord2) > 0:
+ chord1.append( (pitch,accidental ) )
+ if beam==0 or beam ==4 :
+ lastChord = 0
+ else : # 2 voices
+ chord2.append( (pitch,accidental, duration) )
+ lastChord = durVal(duration)
+
+ if len(chord2)==0: # block chord
+ result += triplet[0] + ' <'
+ for i in range(len(chord1)):
+ (pitch,accidental ) = chord1[i]
+ pitch += lastClef
+ note = scale[pitch]
+
+ natural = ''
+
+ # get Accidentals
+ if ( accidental == '!' ) : # also do forced naturals
+ natural = accidental
+ accidental = ''
+
+ if (accidental!='auto'):
+ currentKey[note[0]] = accidental
+
+ accidental = currentKey[note[0]]
+
+ if (relativePitch):
+ octave = getRelativePitch(lastPitch, pitch)
+ lastPitch = pitch
+ else:
+ octave = note[1:]
+ result += note[0] + accidental + octave + natural + ' '
+
+ if dualVoice == 1: # no beams and slurs with two voices
+ slur = ''
+
+ result += '>' + chordDur + slur + triplet[1] + ' ' # added slur (HdR)
+ lastPitch = chord1[0][0] + lastClef
+ else: # 2 voices Beware, this is experimental and not working good.
+ dualVoice = 1
+ result += ' << '
+ for i in range(len(chord2)):
+ (pitch,accidental,duration ) = chord2[i]
+ pitch += lastClef
+ note = scale[pitch]
+
+ if ( accidental == '!' ) : # also do forced naturals
+ natural = accidental
+ accidental = ''
+
+ if (accidental!='auto'):
+ currentKey[note[0]] = accidental
+
+ accidental = currentKey[note[0]]
+
+ if (relativePitch):
+ octave = getRelativePitch(lastPitch, pitch)
+ lastPitch = pitch
+ else:
+ octave = note[1:]
+ result += note[0] + accidental + octave + duration + ' ' #no slur, must be done manually
+
+ result += " \\\\ {"
+
+ for i in range(len(chord1)):
+ (pitch,accidental ) = chord1[i]
+ pitch += lastClef
+ note = scale[pitch]
+
+ if ( accidental == '!' ) : # also do forced naturals
+ natural = accidental
+ accidental = ''
+
+ if (accidental!='auto'):
+ currentKey[note[0]] = accidental
+
+ accidental = currentKey[note[0]]
+
+ if (relativePitch):
+ octave = getRelativePitch(lastPitch, pitch)
+ lastPitch = pitch
+ else:
+ octave = note[1:]
+ result += note[0] + accidental + octave + chordDur + ' ' # no slur, must be done manually
+ if lastChord >0 : lastChord = durVal(duration) - durVal(chordDur)
+ if lastChord==0: result += ' } >> '
+ # end 2 voices
+ lastDuration = chordDur
+ # check if duration / stem / same
+ # < >duration ties,beam, slurs
+
+ # Pedal
+ elif data=='\x0b':
+ data = data = nwcData.read(5)
+ if data[4] == '\x01':
+ style += '\\sustainDown'
+ elif data[4] == '\x00':
+ style += '\\sustainUp'
+ if debug: print binascii.hexlify(data),
+ if debug: print ' = Pedal, style: ', style
+
+ # midi control instruction / MPC
+ elif data=='\x0d':
+ if debug: print 'midi control instruction',
+ data = data = nwcData.read(36)
+ if debug: print binascii.hexlify(data)
+
+ # fermata / Breath mark
+ elif data=='\x0e':
+ data = nwcData.read(6)
+ style += getTempoVariance( data[4] )
+ if debug: print binascii.hexlify(data),
+ if debug: print " = tempo variance, style: ", style
+
+ # Dynamic variance
+ elif data=='\x0f':
+ data = nwcData.read(5)
+ style += getDynVariance( data[4] )
+ if debug: print binascii.hexlify(data),
+ if debug: print " = Dynamic variance, style: ", style
+
+ # Performance Style
+ elif data=='\x10':
+ data = nwcData.read(5)
+ style += getPerfStyle( data[4] )
+ if debug: print binascii.hexlify(data),
+ if debug: print " = Performance Style, style: ", style
+
+ # text
+ elif data=='\x11':
+ textCount = textCount + 1
+ data = nwcData.read(2) #pad
+ textpos = nwcData.read(1)
+ data = nwcData.read(2) #pad
+ text = ''
+ data = nwcData.read(1)
+ while data!='\x00':
+ text += data
+ data = nwcData.read(1)
+
+ #if text.isdigit() : # check numbers
+ # text = "-\\markup -\\number "+ text
+ # #text = "-\\markup {\\number "+ text +"}"
+ #else :
+ # text = '-"' + text + '"'
+
+ if text == 'tr':
+ style += '\\trill'
+ else :
+ if insertText :
+ extra += ' ' + text
+
+
+ # todo
+ else :
+ print "WARNING: Unrecognised token ",binascii.hexlify(data), " at #", nwcData.tell(), " at Token", token
+
+
+
+ # output converted file?
+ print "\nStats"
+ print keysigCount, " keysigCount found"
+ print noteCount, " notes found"
+ print staffCount, " staffCount found"
+ print clefCount, " clefCount found"
+ print barlineCount, " barlineCount found"
+ print timesigCount, " timesigCount found"
+ print textCount, " textCount found"
+ print tempoCount, " tempoCount found"
+ print dynamicCount, " dynamicCount found"
+ print restCount, " restCount found"
+
+ return result
+
+# Variables
+keysigs = {
+'00000000' : 'c \major % or a \minor' ,
+'00000020' : 'g \major % or e \minor' ,
+'00000024': 'd \major % or b \minor' ,
+'00000064' : 'a \major % or fis \minor' ,
+'0000006c' : 'e \major % or cis \minor' ,
+'0000006d' : 'b \major % or gis \minor' ,
+'0000007d' : 'fis \major % or dis \minor' ,
+'0000007f' : 'cis \major % or ais \minor' ,
+'00020000' : 'f \major % or d \minor' ,
+'00120000' : 'bes \major % or g \minor' ,
+'00130000' : 'ees \major % or c \minor' ,
+'001b0000' : 'aes \major % or f \minor' ,
+'005b0000' : 'des \major % or bes \minor' ,
+'005f0000' : 'ges \major % or ees \minor' ,
+'007f0000' : 'ces \major % or a \minor'
+}
+
+acdts = ( 'is', 'es', '!' ,'isis', 'eses', 'auto' )
+
+dynVariance = ( '\\<', # crescendo
+ '\\>', # decrescendo
+ '\\>', # diminuendo
+ '\\rfz', # rinforzando
+ '\\sfz' # sforzando
+ )
+
+perfStyle = ( 'ad lib.',
+ 'animato',
+ 'cantabile',
+ 'con brio',
+ 'dolce',
+ 'espressivo',
+ 'grazioso',
+ 'legato',
+ 'maestoso',
+ 'marcato',
+ 'meno mosso',
+ 'poco a poco',
+ 'piu mosso',
+ 'semplice',
+ 'simile',
+ 'solo',
+ 'sostenuto',
+ 'sotto voce',
+ 'staccato',
+ 'subito',
+ 'tenuto',
+ 'tutti',
+ 'volta subito'
+ )
+
+clefs = { 0 : "b'",
+ 1 : "d",
+ 2 : "c'",
+ 3 : "a'",
+ }
+
+clefNames = { 0: 'treble',
+ 1: 'bass',
+ 2: 'alto',
+ 3: 'tenor',
+ }
+octaves = { 0: 0, 1:7, 2:-7 }
+scale = [ # this list is taken from lilycomp
+ "c,,,","d,,,","e,,,","f,,,","g,,,","a,,,","b,,,",
+ "c,,","d,,","e,,","f,,","g,,","a,,","b,,",
+ "c,","d,","e,","f,","g,","a,","b,",
+ "c","d","e","f","g","a","b",
+ "c'","d'","e'","f'","g'","a'","b'",
+ "c''","d''","e''","f''","g''","a''","b''",
+ "c'''","d'''","e'''","f'''","g'''","a'''","b'''",
+ "c''''","d''''","e''''","f''''","g''''","a''''","b''''",
+ "c'''''","d'''''","e'''''","f'''''","g'''''","a'''''","b'''''",
+ ]
+
+stems = [ '\stemNeutral ', '\stemUp ', '\stemDown ']
+
+# what is slur 3? continuation of existing slur? (HdR)
+slurs = [ '', '(' , ')', '' ]
+
+tempoVariance = ['breathe',
+ 'fermata',
+ 'accel.',
+ 'allarg.',
+ 'rall.',
+ 'ritard.',
+ 'rit.',
+ 'rubato',
+ 'string.'
+ ]
+dynamics = [ '\\ppp ',
+ '\\pp ',
+ '\\p ',
+ '\\mp ',
+ '\\mf ',
+ '\\f ',
+ '\f ',
+ '\\fff '
+ ]
+
+triplets = [
+ ('' , '' ),
+ ( '\\times 2/3 { ', '') ,
+ ('' , '' ),
+ ('' , ' }' ),
+ ]
+
+durations = ( '1','2','4','8','16','32','64' )
+revDurations = ( 64, 32, 16, 8, 4, 2, 1 )
+
+barlines = (
+ '|', # 'Single'
+ '||', # 'Double'
+ '.|', # SectionOpen
+ '|.', # SectionClose
+ '|:', # MasterRepeatOpen
+ ':|', # MasterRepeatClose
+ '|:', # LocalRepeatOpen
+ ':|', # LocalRepeatClose
+)
+
+ending = (
+'|.', # SectionClose
+':|', # MasterRepeatClose
+'|', # 'Single'
+'||', # 'Double'
+'' # Open hidden
+)
+
+staffType = (
+'Standard' , # Standard
+'Upper Grand Staff' , # Upper Grand Staff
+'Lower Grand Staff' , # Lower Grand Staff
+'Orchestra' , # Orchestra
+)
+
+
+beams = [ '', '[', '',']' ]
+
+
+# end ' \bar "|."'
+
+# Notation Properties
+# extra accidental spacing
+# extra note spacing
+# muted
+# no ledger lines
+# slurdirection
+# tiedirection
+# lyricsyllable
+# visability
+# show printed
+# item color
+
+#dynamics
+# cmd = DynamicVariance
+# Decrescendo \setTextCresc \<
+# setTextCresc Crescendo \> setHairpinCresc
+# Dynamics stop '\! '
+# style = ff pp
+
+clefOctave = [ '' , '^8', '_8' , '' ]
+clefShift = [0,7,-7, 0]
+
+
+# '#(set-accidental-style '#39'modern-cautionary)'
+#(ly:set-point-and-click 'line-column)
+#(set-global-staff-size 20)
+
+timesigValues = {
+ '4/4' : '1', '3/4' : '2.', '2/4' : '2', '1/4' : '1', '6/4' : '2.', '5/4' : 1,
+ '1/8' : '8', '2/8' : '4', '3/8' : '4.', '6/8' : '2.',
+ '4/8' : '2', '9/8' : '12', '12/8' : '1',
+ '2/2' : '1', '4/2' : '0', '1/2' : '2',
+ }
+
+print "python nwc2ly is running..."
+try:
+
+ nwcData = open( nwcfile,'rb')
+
+ # check if its a readable nwc format
+ # compressed - [NWZ]
+ # uncompressed - [NoteWorthy ArtWare] [NoteWorthy Composer]
+ format = nwcData.read(5)
+ if format== '[NWZ]':
+ nwcData.seek(1,1)
+ print 'Compressed NWC detected!'
+ print 'Dumping to uncompressed NWC format and attemping conversion soon...'
+ uncompress = open ('uncompressed.nwc','wb')
+ uncompress.write(zlib.decompress(nwcData.read()))
+ uncompress.close()
+ print 'Inflating done. Now opening new file...'
+ nwcData.close()
+ nwcData = open( 'uncompressed.nwc','rb')
+ nwcData.seek(6)
+ elif format!= '[Note':
+ print 'Unknown format, please use an uncompress NWC format and try again.'
+ sys.exit()
+
+
+ if debug: print "Getting file format"
+ getFileFormat(nwcData)
+ if debug: print "Getting file info"
+ fileInfo = getFileInfo(nwcData)
+ if debug: print "Getting page setup"
+ (margins, staffSize) = getPageSetup(nwcData)
+
+ #0.09850000 0.20094000 0.29944000 0.50037998
+ #0123456789012345678901234567890123456789012345
+ topMargin = margins[0:9]
+ leftMargin = margins[11:20]
+ rightMargin = margins[22:31]
+ bottomMargin = margins[33:42]
+
+ topMargin = round( float(topMargin), 2 )
+ bottomMargin = round( float(bottomMargin), 2)
+ leftMargin = round( float(leftMargin), 2 )
+ rightMargin = round( float(rightMargin), 2 )
+ if debug: print "top ", str(topMargin)
+ if debug: print "bottom ", str(bottomMargin)
+ if debug: print "left ", str(leftMargin)
+ if debug: print "right ", str(rightMargin)
+
+ resultFile = '%% Generated from python nwc2ly converter v%s by Joshua Koo (joshuakoo@myrealbox.com)' % nwc2lyversion
+ resultFile += '\n\\paper \n{\n'
+ resultFile += '\t#(set-paper-size "' + paperSize + '")\n'
+ resultFile += '\t#(set-global-staff-size ' + str(staffSize) + ')\n'
+ resultFile += '\ttopmargin = ' + str(topMargin) + '\\in\n'
+ resultFile += '\tleftmargin = ' + str(leftMargin) + '\\in\n'
+ resultFile += '\trightmargin = ' + str(rightMargin) + '\\in\n'
+ resultFile += '\tbottommargin = ' + str(bottomMargin) + '\\in\n'
+ resultFile += '\traggedlastbottom = ##'
+ if fillLast:
+ resultFile += 'f\n'
+ else:
+ resultFile += 't\n'
+ resultFile += '}'
+ resultFile += '\n\n\\version "' + LilyPondVersion + '"'
+ resultFile += "\n"
+
+ # START WORK
+ resultFile+= fileInfo
+ resultFile+= "\n\n\\score {"
+ resultFile+= "\n\t<<\n\t\t"
+
+
+ noOfStaffs = findNoOfStaff(nwcData);
+
+ for staff in range(1,noOfStaffs+1):
+ print "\n\nWorking on Staff", staff
+ result = processStaff(nwcData)
+ #print result
+ resultFile += result
+
+ resultFile+= "\n\t>>"
+# resultFile+= "\n\t\layout {}"
+# resultFile+= "\n\t\midi {}"
+ resultFile+= "\n}"
+ nwcData.close()
+
+ if lyfile=='':
+ print 'Dumping output file to screen'
+ print resultFile
+ else :
+ write = open( lyfile ,'w')
+ write.write (resultFile)
+ write.close()
+
+except IOError:
+ print 'File does not exist or an IO error occurred'
+except Exception, e: #KeyError
+ print "Error while reading data at ", nwcData.tell() ,"\n"
+ print 'Dumping whatever result first'
+ print resultFile
+ print Exception, e
+ traceback.print_exc()
+
+print
+print
+print "Please send all bugs and requests to joshuakoo@myrealbox.com"