I am new to programming and Python, but a lot of my current research concerns extracting data from musicxml files. I have a piece of music and want to extract the number of accidentals that occur in a piece that do not form part of the key signature. I have no idea how to do this, please could someone help? Here's an example of one measure from the musicxml file I am looking at:
<measure number='19'>
<print new-system='no'/>
<note>
<rest/>
<duration>768</duration>
<voice>1</voice>
<type>quarter</type>
<staff>1</staff>
</note>
<backup>
<duration>768</duration>
</backup>
<note>
<pitch>
<step>E</step>
<octave>4</octave>
</pitch>
<duration>2304</duration>
<tie type='start'/>
<voice>2</voice>
<type>half</type>
<dot/>
<staff>1</staff>
<notations>
<tied type='start'/>
<slur type='stop' number='1'/>
</notations>
</note>
<backup>
<duration>1536</duration>
</backup>
<note>
<pitch>
<step>E</step>
<alter>3</alter>
<octave>3</octave>
</pitch>
<duration>1536</duration>
<voice>1</voice>
<type>half</type>
<staff>1</staff>
</note>
<note>
<chord/>
<pitch>
<step>G</step>
<alter>4</alter>
<octave>3</octave>
</pitch>
<duration>1536</duration>
<voice>1</voice>
<type>half</type>
<staff>1</staff>
</note>
<backup>
<duration>2304</duration>
</backup>
<note>
<pitch>
<step>E</step>
<octave>2</octave>
</pitch>
<duration>2304</duration>
<voice>5</voice>
<type>half</type>
<dot/>
<staff>2</staff>
</note>
</measure>
The problem translates to searching through the musicxml file and counting the number of times
<pitch>
<step>*</step>
<alter>**</alter>
...
occurs where * is not (F or C) and also finding the number of times that * is F or C and is not followed by the <alter>
tag.
Any help or advice would be much appreciated!
Export a score project in MusicXML format In Logic Pro, choose File > Export > Score as MusicXML. In the Save dialog, type a name for the exported file and browse to a location to save it. Click Save.
Finale can import MusicXML 2.0 files (compressed and uncompressed, . mxl and . xml), MusicXML 1.1 files, and MusicXML 1.0 files.
Apart from native format files (*. mscz and *. mscx), MuseScore can also open MusicXML, compressed MusicXML and MIDI files, as well as a variety of files in other formats.
I can't help with Python details, but I have two MusicXML-related suggestions:
1) Your question is phrased in terms of accidentals, but your code focuses on the alter element. The alter element is used for pitch alteration; the accidental element is what is used for written accidentals. Which one are you looking for? The duality between how much sounds and how it appears in notation is common in MusicXML, and important to understand for doing research with MusicXML files.
2) If you are new to programming and Python, I would suggest using a higher-level toolkit designed expressly for musicology with good MusicXML support. You will move the problem domain up to a higher level which should let you make progress a lot faster. The obvious choice for this is the music21 toolkit, which is also written in Python. There's lots more information at http://web.mit.edu/music21/.
Good luck with your research!
python has an xml.dom module that allows you to quickly navigate through xml files. If you have any experience with web development, it's very similar to javascript's document object model.
from xml.dom.minidom import parse, parseString
def get_step(note):
stepNode = note.getElementsByTagName("step")[0]
#get the text from the Text Node within the <step>,
#and convert it from unicode to ascii
return str(stepNode.childNodes[0].nodeValue)
def get_alter(note):
alters = note.getElementsByTagName("alter")
if len(alters) == 0:
return None
return alters[0]
def is_rest(note):
return len(note.getElementsByTagName("rest")) > 0
def is_accidental(note):
return get_alter(note) != None
dom = parse("data.xml")
notes = dom.getElementsByTagName("note")
#rests don't have steps or alters, so we don't care about them. Filter them out.
notes = filter(lambda note: not is_rest(note), notes)
#compile a list of notes of all accidentals (notes with <alter> tags)
accidentals = filter(is_accidental, notes)
#remove notes that are F or C
accidentals_that_are_not_f_or_c = filter(lambda note: get_step(note) not in ["F", "C"], accidentals)
#compile a list of notes that don't contain the alter tag
non_accidentals = filter(lambda note: not is_accidental(note), notes)
#remove notes that are not F or C
non_accidentals_that_are_f_or_c = filter(lambda note: get_step(note) in ["F", "C"], non_accidentals)
print "Accidental notes that are not F or C:"
if len(accidentals_that_are_not_f_or_c) == 0:
print "(None found)"
else:
for note in accidentals_that_are_not_f_or_c:
print get_step(note)
print "Non-accidental notes that are F or C:"
if len(non_accidentals_that_are_f_or_c) == 0:
print "(None found)"
else:
for note in non_accidentals_that_are_f_or_c:
print get_step(note), get_step(note) in ["F", "C"]
output:
Accidental notes that are not F or C:
E
G
Non-accidental notes that are F or C:
(None found)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With