zoukankan      html  css  js  c++  java
  • Roland钢琴开发中音符值、度、与音名之间的转换算法

    在Roland钢琴伴侣的开发中,首先将mid文件解析出来取到每一个音符的起始时间,每一个音符的时值,音符值(比如中央C的值是60),在绘五线谱的时候需要将每一个音符值与它对应的度(octave)和音名之间相互转换。

     

    WhiteNote.h

    /**@class WhiteNote

     * The WhiteNote class represents a white keynote, a non-sharp,non-flat note.  Todisplay midi notes as sheet music, the notes

     must be converted to white notes andaccidentals.

     *

     * White notes consist of a letter (A thru G)and an octave (0 thru 10).

     * The octave changes from G to A.  After G2 comes A3.  Middle-C is C4.

     *

     * The main operations are calculatingdistances between notes, and comparing notes.

     */

    /*The table below is very important,you must be understand it.

    @class WhiteNote includes two attributes(one is ‘letter’,another is‘Octave’)

    int letter;  /* The letter of the note, A thru G */

    int octave;   /* The octave, 0 thru 10. */

    */

    这个类里面有一个很重要的枚举类型:

    /** Enumeration of the notes in a scale (A, A#, ... G#) */

    enum {

        NoteScale_A       = 0,

        NoteScale_Asharp  = 1,

        NoteScale_Bflat   = 1,

        NoteScale_B       = 2,

        NoteScale_C       = 3,

        NoteScale_Csharp  = 4,

        NoteScale_Dflat   = 4,

        NoteScale_D       = 5,

        NoteScale_Dsharp  = 6,

        NoteScale_Eflat   = 6,

        NoteScale_E       = 7,

        NoteScale_F       = 8,

        NoteScale_Fsharp  = 9,

        NoteScale_Gflat   = 9,

        NoteScale_G       = 10,

        NoteScale_Gsharp  = 11,

        NoteScale_Aflat   = 11

    };

    这个枚举里面的值和下表里面的A   A#   B    C C# D   D#   E    F    F#   G    G# 这些值一一对应。

    /**Convert a note (A, A#, B, etc) and octave into a Midi Note number.

     */

    int notescale_to_number(int notescale, int octave) {

        return 9 + notescale +octave * 12;

    }

    notescale对应上面枚举里面的值,octave对应下表的组数,举一个例,我们找到第四组的的C,在上面枚举中查找C的值和NoteScale_C的值相等(等于3),

    所以notescale_to_number(NoteScale_C, 4) = 60,刚好和第四组的C的音符值对应。这是一个通过scale和octave转换成音符的核心算法。

    第-1组

    0      1     2     3     4     5     6     7     8      

    C    C#   D    D#   E    F    F#   G    G#  

     

    第0组

    9     10   11   12   13   14   15   16   17   18

    A    A#   B     C     C#    D   D#   E    F    F#

    19   20  

    G    G#

    第1组

    21    22   23    24   25   26   27   28   29   30

    A     A#   B      C    C#    D   D#    E    F     F#  

    31   32

    G    G#

    第2组

    33   34   35    36   37   38   39   40   41   42

    A    A#   B     C    C#   D    D#    E    F     F#

    43   44     

    G    G#  

    第3组

    45   46   47    48   49   50   51   52   53   54

    A    A#   B     C    C#    D    D#    E     F    F#

    55   56

    G    G#

     

     

    第4组

    57   58   59   60   61   62   63   64   65   66   

    A    A#   B     C   C#    D     D#    E     F     F#

    67   68   

    G    G#

                   

        

    第5组

    69   70   71    72   73   74   75   76   77   78

    A    A#   B     C    C#   D    D#   E    F    F#

    79   80  

    G    G#

     

    第6组

    81   82   83    84   85   86   87   88   89   90

    A    A#   B     C    C#    D    D#   E    F     F#

    91   92  

    G    G#

     

    第7组

    93    94   95    96   97   98   99   100  101  102

    A    A#    B      C     C#   D    D#    E      F     F#

    103  104 

    G     G#

     

    第8组

    105  106  107  108  109  110  111  112  113  114

    A       A#     B     C     C#      D    D#     E        F    F#
    115  116 

    G       G#

     

     

    第9组

    117  118  119  120  121  122  123  124  125  126

    A       A#      B     C    C#      D     D#    E       F    F#

    127

     G

    接下来介绍另外一个核心方法,这个方法是将音符值转换成NoteScale枚举值,例如60,转换之后notescale_from_number(60)就等于NoteScale_C( 3 ).

    int notescale_from_number(int number) {

        return (number + 3) % 12;

    }

    /** Return true if this notescale number is a black key */

    BOOL notescale_is_black_key(int notescale) {

        if (notescale == NoteScale_Asharp ||

            notescale == NoteScale_Csharp ||

            notescale == NoteScale_Dsharp ||

            notescale == NoteScale_Fsharp ||

            notescale == NoteScale_Gsharp) {

     

            return YES;

        }

        else {

            return NO;

        }

    }

    上面这个方法是判断一个音符是否为black key.

  • 相关阅读:
    linux 文件权限(s、t、i、a)解析
    vim Vundle
    数据结构学习(1)
    Android ImageView设置图片原理(上)
    C++11 之auto
    Android屏幕分辨率获取方法--源码剖析
    C++的发展方向是对的嘛?
    c++ 的前世今生
    学习知识的一种思路
    遗失的访谈小评
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3246754.html
Copyright © 2011-2022 走看看