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.

原文地址:https://www.cnblogs.com/jiangu66/p/3246754.html