美文网首页
iOS中MusicXML的解析和使用

iOS中MusicXML的解析和使用

作者: shikaiming | 来源:发表于2020-04-09 16:35 被阅读0次

    iOS中MusicXML的解析和使用

    MusicXML

    维基上MusicXML的解释是:(英语:Music Extensible Markup Language,音乐扩展标记语言)是一个开放的基于XML的记录西式乐谱的文件格式。该格式是完全自由、开放记录的,并依据W3C社区的许可协议自由使用。
    简单的来说,MusicXML其实就是XML,只不过承载的是乐谱信息的XML。在我们需要绘制或者创建六线谱之类的时候,可以通过MusicXML来记录我们需要绘制或者创建的信息。目的是为音乐符号创造一种通用格式。(本文是基于MusicXML 3.0和2.0,所以可能会有一些出入。)因为项目中用到的是吉他谱,就以吉他谱的含义来进行说明和解释。

    一 文件解析

    MusicXML本质也是XML,所以文件上的解析可以按XML的解析来。
    XML的解析在iOS里面有两种解析方式,一个SAX解析,一个DOM解析。

    方式一:SAX解析

    SAX解析的特点是逐行进行解析。也就是一边读取一边处理。对于大文件,极大的提高了解析效率。

    方式二:DOM解析

    DOM解析的特点是通过节点解析。需要一次性读取整个XML文件并形成一个节点树,通过遍历树结构可以检索任意XML节点,读取它的属性和值。
    比如第三方:GDataXMLNode

    在这里我用的SAX解析,具体可以去看下这里,是我之前用来解析MusicXML文档写的。

    • 注意点:因为是使用的utf8编码,所以一旦XML里面出现了其他的编码方式,就有可能造成解析失败,所以在解析前最好将xml处理一遍。

    二 属性解析

    MusicXML本质上还是XML,所以文件结构是和XML一样的,这个是XML文档所需要的XML声明。声明用的xml版本是1.0和xml传输数据的时候的字符编码。(假如文档里有中文,编码方式不是UTF-8,显示上就会乱码)

    <?xml version="1.0" encoding="UTF-8" ?>
    

    这里是说明当前使用的MusicXML版本是什么,标签里面包含的内容就是MusicXML的内容

     <score-partwise version =“ 3.0”>
      ...
     </score-partwise>
    

    score-partwise元素里面的有几个大元素:

    1. work元素,work-title里面内容是这个xml的名字

       <work>
          <work-title>Aloha oe</work-title>
       </work>
      
    2. identification,这里是文档的一些编辑信息,比如编辑日期,是用什么软件编辑的

       <identification>
           <encoding>
            <encoding-date>2019-10-08</encoding-date>
            <software>Guitar Pro 7.0.9</software>
            <encoder></encoder>
           </encoding>
       </identification>
      
    3. defaults,这里是一些页面的宽高信息

       <defaults>
            <scaling>
             <millimeters>6.4</millimeters>
             <tenths>40</tenths>
            </scaling>
            <page-layout>
             <page-height>1850</page-height>
             <page-width>1310</page-width>
            </page-layout>
       </defaults>
      
    4. part-list,这里面是一些乐器类型,MIDI信息

      <part-list>
        <score-part id="P1">
         <part-name>Ukulele</part-name>
         <part-abbreviation>uke.</part-abbreviation>
         <midi-instrument id="P1">
          <midi-channel>1</midi-channel>
          <midi-bank>1</midi-bank>
          <midi-program>25</midi-program>
          <volume>80</volume>
          <pan>0</pan>
         </midi-instrument>
      </score-part>
      
    5. part,这里面是音符信息,默认是只有一个part的,所以大多数MusicXML里面是只有一个part元素,比如:

      <score-partwise>
           <part id="P1">
              ...
           </part>
       </score-partwise>
      
      但有可能会出现多个part,具体看制谱的时候是怎么做的,比如:
      <score-partwise>
          <part id="P1">
              ...
          </part>
          <part id="P2">
              ...
          </part>
      </score-partwise>
      
    • measure元素,part里面是小节measure元素,比如一首谱子有24个小节,那么就会有24个measure,measure里面的属性number等于多少是可以自己定义的,比如从0开始,比如从1开始。measure里面包含了一个小节里面所有的信息。

      • attributes,先看measure里面第一个元素attributes,一般出现在第一个小节中,它里面是该乐谱的基本信息。
        1. divisions,divisions表示的是一个四分音符的时值,每个小节可能有不同的值,比如说在第一个小节中

           <divisions>1</divisions>
          

          表示的是当前小节中一个四分音符的时值是1个单位,divisions是要配合note中的duration看的,比如在4/4的谱子中,下面这个四分音符note的duration就是1,

          <note>
               <duration>1</duration>
               <type>quarter</type>
          </note>
          

          而下面这个全音符的duration就是4,因为4/4是以四分音符为一拍,每小节四拍。所以全音符的话时值相当于四个四分音符,所以它的duration就是4。

          <note>
              <duration>4</duration>
              <type>whole</type>
          </note>
          

      再比如如果当前音符存在附点,附点的时值是当前音符的一半,因为按上下文当前divisions还是1,而在当前出现了附点,divisions要变为2,所以在接下来会变成下面这样

            ```
             <divisions>2</divisions>
                <note>
                <dot/>
                <duration>3</duration>
                <type>quarter</type>
                </note>
            ```
      

      再比如如果当前小节存在十六分音符:

            ```
            <divisions>4</divisions>
                <note>
                <duration>1</duration>
                <type>16th</type>
             </note>
            ```
      
        1. key,key元素表示乐谱的升降号情况,fifths为0表示不升不降,一般正数表示升调的个数,负数表示降调的个数,这个元素还有一个属性`mode/type`来表示此调为大调(major)还是小调。
          
            ```
                <key>
                 <fifths>0</fifths>
                 <mode>major</mode>
                </key>
            ```
        2. time,time元素里面是这首曲子拍速等一些相关的信息,比如下面的含义就是以8分音符为一拍,每小节6拍。
            ```
                <time>
                 <beats>6</beats>//每个小节有几个拍
                 <beat-type>8</beat-type>//以哪种音符为一拍
                </time>
            ```
        3. clef,clef里面是谱号信息。
            
            ```
                <clef number="1">
                 <sign>TAB</sign>
                 <line>5</line>
                </clef>
            ```
        4. staff-details,staff-details这里是空弦的时候每根弦的音名。
            *staff-lines,staff-lines元素指定了行数
      
      • harmony,和弦图元素
      • note,然后接下来是<note>标签,这里面是每个音符的一些信息。
        • chord,这个元素可以理解为和弦,叠音,也就是说当这个标签出现的时候,竖直方向是有多个音的,用叠音描述会形象一些,也就是几个音叠在一起;相反如果没有这个元素,可以大致认为当前这个音符是根音,也就是在最底部的音。比如:

           <note>
            <chord/>
            <type>quarter</type>
            <stem>up</stem>
            <notations>
             <technical>
              <string>4</string>
              <fret>2</fret>
             </technical>
            </notations>
           </note>
          
        • rest,这个元素是休止符的表示,比如下面表示一个二分休止符:

           <note>
            <rest/>
            <duration>2</duration>
            <type>half</type>
           </note>
          
        • duration,上面divisions元素中已经说过了,表示当前音符的时值,也就是这个音符的持续时间。具体值是通过divisions来计算。

        • type,表示当前音符是什么类型,比如<type>half</type>,表示的是个二分音符。type里面的值是有固定的,大致是这些

          • whole:全音符,也就是占一个小节
          • half:二分音符
          • quarter:四分音符
          • eighth:八分音符
          • 16th:16分音符
          • 32th:32分音符
            如果出现了更小的音符,基本就是以数字+th为名字。
        • pitch,音高,里面是音、调的一些信息。

          • step:表示是abcdefg哪个调。

          • alter:表示升降,作为音高的一部分,-2或2表示重降和重升。

          • octave:表示在哪个八度上。
            比如:

             <pitch>
              <step>F</step>
              <alter>-2</alter>
              <octave>4</octave>
             </pitch>
            
        • stem:符干。

        • voice:声部。

        • dot:附点,表示当前音符的时值增加一半。比如下面例子,某个小节中的一个四分音符,如果divisions为2的话,它的时值duration是3。divisions表示的,可以理解成一个四分音符的时值。那么当前这个小节中的四分音符加个附点的话,它时值就是一个四分的1.5倍,也就是3。

           <note>
              <duration>3</duration>
              <type>quarter</type>
              <dot/>
           </note>
          
        • tie:表示一个连音的开始和结束。可能会存在多个,有个number属性可以用来区分或者标识具体的tie元素。
          比如下面表示一个连音:

          <note>
           <tie type="start"/>
          </note>
          <note>
           <tie type="stop"/>
           <tie type="start"/>
          </note>
          <note>
           <tie type="stop"/>
          </note>
          
        • lyric:歌词。

          <note>
           <lyric>
               <syllabic>begin</syllabic>
               <text>我爱的</text>//这里是具体的歌词内容
           </lyric>
           </note>
          
        • beam:桥梁,可能存在多个,用来显示八音符,十六分音符底部横梁等。

           <note>
           <beam number="1">begin</beam>
           </note>
           
           <note>
           <beam number="1">continue</beam>
           <beam number="2">begin</beam>
           </note>
          
           <note>
           <beam number="1">continue</beam>
           <beam number="2">end</beam>
           </note>
          
        • notations:里面包含的是这个音符具体的一些信息,比如几弦几品,是什么音之类的信息。具体是下面这些元素:

          • brush:扫弦。因为用的GuitarPro7软件制谱,所以GP7导出的xml里面扫弦是导出是长下面这样的,其他软件不大确定。

            • type:扫弦的方向,
              * down说明是向上扫弦,箭头向上;
              * up说明是向下扫弦,箭头向下。
              <notations>
             <?GP7 <root><brush type="down"/></root>?>
             </notations>
            
          • arpeggiate:琶音。

            • direction:琶音方向,
              * up是向上琶音,箭头向上。
              * down是向下琶音,箭头向下。
              <notations>
                <arpeggiate direction="up"/>
              </notations>
            
          • tuplet:三连音,基本能遇到的就两种吧? 一个是: 八分音符样子的三个,就是一拍的三连音;另外一个是:四分音符样子的三个,就是两排拍的三连音,和beats,beat-type无关。

            • type:来标识三连音的开始和结束,start,stop。
            • number:来区别哪个三连音。
            • placement:支架朝向above-below。
            • bracket:是否显示支架 yes-no。
                ```
                 <notations>
                 <tuplet type="start" number="1" bracket="yes" placement="below"/>
                 <notations>
                ```
            * slide:滑弦,开始音品数大于终止音品数,则是下滑音,否则是上滑音。
                * type:滑音的开始或者结束,start,stop。
                * number:标识。
                
            * slur:连接符,这里一般特指滑音或者击勾弦的连接符,实际使用中貌似可以忽略它的存在,因为slide或者hammer-on元素里面的type属性已经能完整的告诉我们他们的开始和结束了。可能我还没遇到slur的特定情况吧。
                * type:连接的开始或者结束。
            
                ```
                 <notations>
                 <slur type="start"/>//连接符
                 <slide number="5" type="start"/>
                 </notations>
                ```
            * tied:这里的tied元素含义和外层tie元素意思是一样的,都是用来表示连音的开始和结束。
                            
                ```
                 <notations>
                    <tied type="start"/>
                 </notations>
                ```
            * technical:这个元素里面是几弦几品,手指,推弦,泛音等一些信息。
                
                ```
                 <technical>
                  <string>3</string>
                  <fret>2</fret>
                 <fingering>2</fingering>
                 <pluck></pluck>
                 </technical>
                ```
    
                * string:告诉我们这个音符是几弦。
                * fret:告诉我们这个音符是几品。
                * fingering:告诉我们按哪个手指。
                * pluck:左手哪根手指。
                * bend:推弦,推全音或者推半音
                        * bend_alter:推半音还是全音标识,全音2,半音1,回原位0
                        * isRelease:推弦回原位标识,有这个标识是会原位,否则不会。
                        
                        <technical>
                          <bend>
                           <bend-alter>2</bend-alter>
                          </bend>
                          <bend>
                           <bend-alter>0</bend-alter>
                           <release/>
                          </bend>
                         </technical>
                        
                * harmonic,natural:泛音。
                    
                    ```
                    <technical>
                      <harmonic>
                       <natural/>
                       <base-pitch/>
                      </harmonic>
                     </technical>
                    ```
                * hammer-on:击勾弦,用的是同一个字段,<fret>品数由小到大是击弦,品数由大到小是勾弦。也可以直接根据hammer-on元素中的内容判断,是`H`基本上就是击弦;勾弦的话内容就是`P`的标识。
                    * number:标识。
                    * type:击勾弦的开始结束,start,stop。
                    比如下面这个,是一个击弦,
            ```
            <note>
                <notations>
                 <technical>
                  <hammer-on number="1" type="start">H</hammer-on>
                  <string>2</string>
                  <fret>0</fret>
                 </technical>
                 <slur type="start"/>
                </notations>
            </note>
            <note>
                <notations>
                 <technical>
                  <hammer-on number="1" type="stop"/>
                  <string>2</string>
                  <fret>2</fret>
                 </technical>
                 <slur type="stop"/>
                </notations>
             </note>
            ```
    

    基本能用到的大多数就是这么多了,更多详细的可以查看MusicXML的官网文档

    三 (六线谱)吉他谱绘制

    绘制的话,看具体的需求了,可以尝试在layer上异步绘制,然后在需要的情况下再渲染到view上。比如用CAShapeLayer,轻量,性能又好。

    相关文章

      网友评论

          本文标题:iOS中MusicXML的解析和使用

          本文链接:https://www.haomeiwen.com/subject/bynqmhtx.html