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