1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 
4 /*
5     Rosegarden
6     A sequencer and musical notation editor.
7     Copyright 2000-2021 the Rosegarden development team.
8     See the AUTHORS file for more details.
9 
10     This program is free software; you can redistribute it and/or
11     modify it under the terms of the GNU General Public License as
12     published by the Free Software Foundation; either version 2 of the
13     License, or (at your option) any later version.  See the file
14     COPYING included with this distribution for more information.
15 */
16 
17 #ifndef RG_NOTATION_RULES_H
18 #define RG_NOTATION_RULES_H
19 
20 
21 /**
22  * Common major and minor scales.
23  *
24  * For example, sixth note in 12-basis on Cmajor scale:
25  *   scale_Cmajor[5] = 9
26  */
27 static int scale_Cmajor[] = { 0, 2, 4, 5, 7, 9, 11 };
28 static int scale_Cminor[] = { 0, 2, 3, 5, 7, 8, 10 };
29 static int scale_Cminor_harmonic[] = { 0, 2, 3, 5, 7, 8, 11 };
30 /**
31  * Steps of common major and minor scales.
32  *
33  * For example, get accidental in 12-basis on Cmajor scale:
34  *   10 - scale_Cmajor[steps_Cmajor[10]] = 10 - 9 = +1
35  */
36 static int steps_Cmajor[] = { 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6 };
37 static int steps_Cminor[] = { 0, 0, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6 };
38 static int steps_Cminor_harmonic[] = { 0, 0, 1, 2, 2, 3, 3, 4, 5, 5, 5, 6 };
39 /**
40  * Same as previosly, but the use of accidentals is explicitly written.
41  *
42  * For example, get accidental in 12-basis on Cmajor scale:
43  *   10 - scale_Cmajor[steps_Cmajor_with_sharps[10]] = 10 - 9 = +1
44  *   10 - scale_Cmajor[steps_Cmajor_with_flats[10]] = 10 - 11 = -1
45  */
46 static int steps_Cmajor_with_sharps[] = { 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6 };
47 static int steps_Cmajor_with_flats[] = { 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 6 };
48 
49 namespace Rosegarden
50 {
51 
52 /*
53  * NotationRules.h
54  *
55  * This file contains the model for rules which are used in notation decisions.
56  *
57  */
58 
59 class NotationRules
60 {
61 public:
NotationRules()62     NotationRules() {
63         // This class is used in various places, and each different place pulls
64         // a bit of this and a bit of that, but nothing uses everything.  This
65         // creates a number of annoying compiler warnings about unused
66         // variables, and a shifting list of unused variables.  What's unused by
67         // this class is used by that class, and so on.  So let's use them all
68         // one time for something totally pointless, just to shut up these
69         // compiler warnings once and for all.
70         (void)scale_Cmajor[0];
71         (void)scale_Cminor[0];
72         (void)scale_Cminor_harmonic[0];
73         (void)steps_Cmajor[0];
74         (void)steps_Cminor[0];
75         (void)steps_Cminor_harmonic[0];
76         (void)steps_Cmajor_with_sharps[0];
77         (void)steps_Cmajor_with_flats[0];
78     };
~NotationRules()79     ~NotationRules() { };
80 
81     /**
82      * If a single note is above the middle line, the preferred direction is up.
83      *
84      * If a single note is on the middle line, the preferred direction is down.
85      *
86      * If a single note is below the middle line, the preferred direction is down.
87      */
isStemUp(int heightOnStaff)88     bool isStemUp(int heightOnStaff) { return heightOnStaff < 4; }
89 
90     /**
91      * If the highest note in a chord is more distant from the middle
92      * line than the lowest note in a chord, the preferred direction is down.
93      *
94      * If the extreme notes in a chord are an equal distance from the
95      * middle line, the preferred direction is down.
96      *
97      * If the lowest note in a chord is more distant from the middle
98      * line than the highest note in a chord, the preferred direction is up.
99      */
isStemUp(int highestHeightOnStaff,int lowestHeightOnStaff)100     bool isStemUp(int highestHeightOnStaff, int lowestHeightOnStaff) {
101         return (highestHeightOnStaff + lowestHeightOnStaff) < 2*4;
102     }
103 
104     /**
105      * If majority of notes are below the middle line,
106      * the preferred direction is up.
107      *
108      * If notes are equally distributed around the middle line,
109      * the preferred direction is down.
110      *
111      * If majority of notes are above the middle line,
112      * the preferred direction is down.
113      */
isBeamAboveWeighted(int weightAbove,int weightBelow)114     bool isBeamAboveWeighted(int weightAbove, int weightBelow) {
115         return weightBelow > weightAbove;
116     }
117 
118     /**
119      * If the highest note in a group is more distant from the middle
120      * line than the lowest note in a group, the preferred direction is down.
121      *
122      * If the extreme notes in a group are an equal distance from the
123      * middle line, the preferred direction is down.
124      *
125      * If the lowest note in a group is more distant from the middle
126      * line than the highest note in a group, the preferred direction is up.
127      */
isBeamAbove(int highestHeightOnStaff,int lowestHeightOnStaff)128     bool isBeamAbove(int highestHeightOnStaff, int lowestHeightOnStaff) {
129         return (highestHeightOnStaff + lowestHeightOnStaff) < 2*4;
130     }
isBeamAbove(int highestHeightOnStaff,int lowestHeightOnStaff,int weightAbove,int weightBelow)131     bool isBeamAbove(int highestHeightOnStaff, int lowestHeightOnStaff,
132                      int weightAbove, int weightBelow) {
133         if (highestHeightOnStaff + lowestHeightOnStaff == 2*4) {
134 	    return isBeamAboveWeighted(weightAbove,weightBelow);
135 	} else {
136 	    return isBeamAbove(highestHeightOnStaff,lowestHeightOnStaff);
137 	}
138     }
139 };
140 
141 }
142 
143 #endif
144