Python 从Musicxml中提取信息

Python 从Musicxml中提取信息,python,musicxml,Python,Musicxml,我不熟悉编程和Python,但我目前的很多研究都是关于从musicxml文件中提取数据。我有一段音乐,想提取一段音乐中发生的意外事件的数量,这些意外事件不构成密钥签名的一部分。我不知道怎么做,有人能帮忙吗?下面是我正在查看的musicxml文件中的一个度量值示例: <measure number='19'> <print new-system='no'/> <note> <rest/>

我不熟悉编程和Python,但我目前的很多研究都是关于从musicxml文件中提取数据。我有一段音乐,想提取一段音乐中发生的意外事件的数量,这些意外事件不构成密钥签名的一部分。我不知道怎么做,有人能帮忙吗?下面是我正在查看的musicxml文件中的一个度量值示例:

<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>

768
1.
一刻钟
1.
768
E
4.
2304
2.
一半
1.
1536
E
3.
3.
1536
1.
一半
1.
G
4.
3.
1536
1.
一半
1.
2304
E
2.
2304
5.
一半
2.
问题转化为搜索musicxml文件并计算次数

<pitch>
   <step>*</step>
   <alter>**</alter>
       ...

*
**
...
在*不是(F或C)的情况下发生,同时查找*是F或C且后面没有
标记的次数

任何帮助或建议都将不胜感激

python有一个模块,允许您快速浏览xml文件。如果您有任何web开发经验,那么它与javascript的文档对象模型非常相似

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"]

我无法帮助您了解Python的详细信息,但我有两个与MusicXML相关的建议:

1) 您的问题是以意外事件的形式表达的,但您的代码将重点放在alter元素上。alter元件用于改变音高;意外事件元素用于书面意外事件。你在找哪一个?在MusicXML中,声音的数量和它在符号中的显示方式之间的二元性是很常见的,了解这一点对于研究MusicXML文件很重要

2) 如果您是编程和Python新手,我建议您使用专门为音乐学设计的更高级别工具包,并提供良好的MusicXML支持。你将把问题领域提升到一个更高的层次,这将让你进步更快。显而易见的选择是music21工具包,它也是用Python编写的。网站上有更多信息


祝你研究顺利

感谢您的支持,但是该代码给出的结果与导入lxml.etree并使用musicxml.xpath('count(//alter')的结果相同。我想编一份所有意外事件(标签下)的音符名称列表,然后删除那些F或C。我还需要编一份不包含标签的音符列表,删除那些不是F或C的音符。请原谅我的无知,我对这一点很陌生。谢谢迈克尔,我发现音乐21真的很有用。在my musicxml文件中,使用alter标记代替意外。我试图找到所有与给定密钥签名有关的意外注释。在音乐21中有没有一种快速的方法可以做到这一点?如果乐曲中某个地方的键签名发生了变化,那该怎么办?您好2025161:在music21中,您可以使用.flat.notes(假设没有和弦;或者.getElementsByClass('note'),如果有的话)迭代每个音符,然后将每个音符对象的.pitch.Incident对象与n.getContextByClass('KeySignature').accidentalByStep进行比较(n.pitch.step)并找到它们不同的地方。请注意,这段简单的代码在O(n^2)时间内运行;您可以缓存KeySignature对象,使其在大分数上运行得更快。
Accidental notes that are not F or C:
E
G
Non-accidental notes that are F or C:
(None found)