music21.noteworthy.binaryTranslate

Attempts at reading pure .nwc files in music21

First will solve uncompressed .nwc then compressed .nwc

Thanks to Juria90 and the nwc2xml project for solving so many of the documentation problems. No part of this code is taken from that project, but this project would have been impossible without his work.

Translates .nwc into .nwctxt and then uses Jordi Guillen’s .nwctxt translator to go from there to music21.

BETA – does not work for many file elements and is untested.

Demo, showing the extent of problems. The measure numbers are not set. Lyrics are missing and the triplet in the AltoClef part is omitted. This is very beta. Much better would be to convert the file into .xml or .nwctxt first.

>>> c = converter.parse('/Users/cuthbert/desktop/cuthbert_test1.nwc')
>>> c.show('text')
{0.0} <music21.metadata.Metadata object at ...>
{0.0} <music21.stream.Part ...>
    {0.0} <music21.stream.Measure 0 offset=0.0>
        {0.0} <music21.clef.TrebleClef>
        {0.0} <music21.meter.TimeSignature 4/4>
        {0.0} <music21.note.Note G>
        {1.0} <music21.note.Note C>
        {2.0} <music21.note.Note C>
        {3.0} <music21.note.Note B>
    {4.0} <music21.stream.Measure 0 offset=4.0>
        {0.0} <music21.note.Note C>
{0.0} <music21.stream.Part ...>
    {0.0} <music21.stream.Measure 0 offset=0.0>
        {0.0} <music21.clef.TrebleClef>
        {0.0} <music21.meter.TimeSignature 4/4>
        {0.0} <music21.note.Note G>
        {1.0} <music21.note.Note A>
        {2.0} <music21.note.Note A>
        {3.5} <music21.note.Note G>
    {4.0} <music21.stream.Measure 0 offset=4.0>
        {0.0} <music21.note.Note G>
{0.0} <music21.stream.Part ...>
    {0.0} <music21.stream.Measure 0 offset=0.0>
        {0.0} <music21.clef.AltoClef>
        {0.0} <music21.meter.TimeSignature 4/4>
        {0.0} <music21.note.Note D>
        {2.0} <music21.note.Note C#>
        {3.0} <music21.note.Note D>
        {4.0} <music21.note.Note E>
    {5.0} <music21.stream.Measure 0 offset=5.0>
        {0.0} <music21.note.Note E>
{0.0} <music21.stream.Part ...>
    {0.0} <music21.stream.Measure 0 offset=0.0>
        {0.0} <music21.clef.BassClef>
        {0.0} <music21.meter.TimeSignature 4/4>
        {0.0} <music21.note.Note G>
        {1.0} <music21.note.Note F>
        {2.0} <music21.note.Note E>
        {3.0} <music21.note.Note G>
    {4.0} <music21.stream.Measure 0 offset=4.0>
        {0.0} <music21.note.Note C>

NWCConverter

class music21.noteworthy.binaryTranslate.NWCConverter(**keywords)

A converter object for binary .nwc files. Do not normally use directly; use converter.parse.

>>> nwcc = noteworthy.binaryTranslate.NWCConverter()
>>> nwcc
<music21.noteworthy.binaryTranslate.NWCConverter object at 0x...>
>>> nwcc.fileContents is None
True
>>> nwcc.parsePosition
0
>>> nwcc.version  # version of nwc file to be parsed
200
>>> nwcc.numberOfStaves
0
>>> nwcc.staves
[]

NWCConverter methods

NWCConverter.advanceToNotNUL(nul=b'\x00')
NWCConverter.byteToInt(updateParsePosition=True)

changes a byte into an unsigned int (i.e., if the byte is > 127 then it’s subtracted from 256)

NWCConverter.byteToSignedInt(updateParsePosition=True)

changes a byte into a signed int (i.e., if the byte is > 127 then it’s subtracted from 256)

NWCConverter.dumpToNWCText()
NWCConverter.fileVersion(updateParsePosition=True)
NWCConverter.isValidNWCFile(updateParsePosition=True)
NWCConverter.parse()

the main parse routine called by parseFile() or parseString()

NWCConverter.parseFile(fp: Path | str)

Parse a file (calls .toStream)

>>> fp = '/Users/cuthbert/desktop/cuthbert_test1.nwc'
>>> nwcc = noteworthy.binaryTranslate.NWCConverter()
>>> nwcc.fileContents is None
True
>>> streamObj = nwcc.parseFile(fp)
>>> len(nwcc.fileContents)  # binary
1139
>>> nwcc.fileContents[0:80]
b'[NoteWorthy ArtWare]\x00\x00\x00[NoteWorthy
         Composer]\x00\x01\x02\x02\x00\x00\x00N/A\x000_JldRQMSKq6M5a3FQqK_g\x00\x00\x00'
>>> streamObj
<music21.stream.Score ...>
NWCConverter.parseHeader()

Sets a ton of information from the header, and advances the parse position.

NWCConverter.parseString(bytesIn=None)

same as parseFile but takes a string (in Py3, bytes) of binary data instead.

NWCConverter.readBytes(bytesToRead=1, updateParsePosition=True)

reads the next bytesToRead bytes and then (optionally) updates self.parsePosition

NWCConverter.readLEShort(updateParsePosition=True)

Helper module: read a little-endian short value to an integer

>>> nwcc = noteworthy.binaryTranslate.NWCConverter()
>>> nwcc.fileContents = b''
>>> nwcc.parsePosition
0
>>> nwcc.readLEShort()
258
>>> nwcc.parsePosition
2
>>> nwcc.readLEShort()
259
>>> nwcc.parsePosition
4

Or to not update the parsePosition, send False: >>> nwcc.parsePosition = 0 >>> nwcc.readLEShort(False) 258 >>> nwcc.readLEShort(False) 258 >>> nwcc.parsePosition 0

NWCConverter.readToNUL(updateParsePosition=True)

reads self.fileContents up to, but not including, the next position of x00.

updates the parsePosition unless updateParsePosition is False

NWCConverter.skipBytes(numBytes=1)
NWCConverter.toStream()

NWCObject

class music21.noteworthy.binaryTranslate.NWCObject(staffParent=None, parserParent=None)

NWCObject methods

NWCObject.barline()
NWCObject.clef()
NWCObject.dynamic()
NWCObject.dynamicVariation()
NWCObject.ending()
NWCObject.flowDir()
NWCObject.instrument()
NWCObject.keySig()
NWCObject.mpc()

what is this?

NWCObject.note()
NWCObject.noteChordMember()
NWCObject.parse()

determine what type of object I am, and set things accordingly

NWCObject.pedal()
NWCObject.performance()
NWCObject.rest()
NWCObject.restChordMember()
NWCObject.setDurationForObject()

get duration string for note or rest

NWCObject.tempo()
NWCObject.tempoVariation()
NWCObject.textObj()
NWCObject.timeSig()

NWCStaff

class music21.noteworthy.binaryTranslate.NWCStaff(parent=None)

NWCStaff methods

NWCStaff.dump()
NWCStaff.parse()
NWCStaff.parseHeader()
NWCStaff.parseLyrics()
NWCStaff.parseObjects()