--- /dev/null
+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