【问题标题】:Extracting information from Musicxml从 Musicxml 中提取信息
【发布时间】:2013-01-30 12:37:35
【问题描述】:

我是编程和 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>

问题转化为搜索musicxml文件并计算次数

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

发生在 * 不是(F 或 C)的情况下,并且还会找出 * 是 F 或 C 且后面没有 &lt;alter&gt; 标记的次数。

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

【问题讨论】:

    标签: python musicxml


    【解决方案1】:

    我无法提供 Python 的详细信息,但我有两个与 MusicXML 相关的建议:

    1) 您的问题是用临时记号表达的,但您的代码侧重于 alter 元素。 alter 元素用于改变音高;意外元素是用于书面意外的元素。你在找哪一个?在 MusicXML 中,有多少声音和它在记谱法中的出现方式之间的二元性很常见,对于使用 MusicXML 文件进行研究来说理解这一点很重要。

    2) 如果您不熟悉编程和 Python,我建议您使用专为音乐学设计的高级工具包,并具有良好的 MusicXML 支持。您会将问题域提升到更高的级别,这应该让您更快地取得进展。显而易见的选择是 music21 工具包,它也是用 Python 编写的。 http://web.mit.edu/music21/ 有更多信息。

    祝你研究顺利!

    【讨论】:

    • 谢谢迈克尔,我发现music21 真的很有用。在我的 musicxml 文件中,使用了 alter 标签而不是意外标记。我试图找到与给定键签名有关的所有意外音符。在music21中有没有一种快速的方法来做到这一点?乐曲中某处调号发生变化的乐曲呢?
    • 嗨 2025161:在 music21 中,您可以使用 .flat.notes 迭代每个音符(假设没有和弦;或 .getElementsByClass('Note') 如果有),然后为每个 Note 对象比较其 . pitch.accidental 对象到 n.getContextByClass('KeySignature').accidentalByStep(n.pitch.step) 并找到它们不同的地方。请注意,这个简单的代码在 O(n^2) 时间内运行;你可以缓存你的 KeySignature 对象,让它在大分数上运行得更快。
    【解决方案2】:

    python 有一个xml.dom 模块,可让您快速浏览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"]
    

    输出:

    Accidental notes that are not F or C:
    E
    G
    Non-accidental notes that are F or C:
    (None found)
    

    【讨论】:

    • 谢谢你,但是该代码给了我相同的结果,就好像我要导入 lxml.etree 并使用 musicxml.xpath('count(//alter)')。我想编译所有临时记号的音符名称列表(在 标签下),然后删除那些是 F 或 C 的。我还需要编译一个不包含 的音符列表标记并删除那些不是 F 或 C 的注释。原谅我的无知,我对此真的很陌生。
    猜你喜欢
    • 2017-06-07
    • 2012-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多