1 /*
2
3 Copyright (C) 2007 Grame
4
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 Grame Research Laboratory, 9, rue du Garet 69001 Lyon - France
21 research@grame.fr
22
23 */
24
25 #ifdef WIN32
26 # pragma warning (disable : 4786)
27 #endif
28
29 #include "pitchApplyOperation.h"
30
31 using namespace std;
32
33 namespace guido
34 {
35
36 //_______________________________________________________________________________
37 // octaveVisitor
38 //_______________________________________________________________________________
39 class octaveVisitor : public visitor<SARNote>
40 {
41 public:
octaveVisitor()42 octaveVisitor() { fBrowser.set(this); }
~octaveVisitor()43 virtual ~octaveVisitor() {}
44
45 int getLastOctave(const Sguidoelement& elt);
46 void forceOctave(const Sguidoelement& elt, int currentOctave);
47
48 protected:
49 tree_browser<guidoelement> fBrowser;
50 int fCurrentOctave;
51 bool fForceOctave;
52 virtual void visitStart ( SARNote& elt );
53 };
54
55 //_______________________________________________________________________________
forceOctave(const Sguidoelement & elt,int currentOctave)56 void octaveVisitor::forceOctave( const Sguidoelement& elt, int currentOctave )
57 {
58 fCurrentOctave = currentOctave;
59 fForceOctave = true;
60 if (elt) fBrowser.browse (*elt);
61 }
62
63 //_______________________________________________________________________________
getLastOctave(const Sguidoelement & elt)64 int octaveVisitor::getLastOctave( const Sguidoelement& elt )
65 {
66 fCurrentOctave = ARNote::getDefaultOctave();
67 fForceOctave = false;
68 if (elt) fBrowser.browse (*elt);
69 return fCurrentOctave;
70 }
71
72 //_______________________________________________________________________________
visitStart(SARNote & elt)73 void octaveVisitor::visitStart( SARNote& elt )
74 {
75 int octave = elt->GetOctave();
76 if (fForceOctave) {
77 if (octave == ARNote::getImplicitOctave())
78 elt->SetOctave(fCurrentOctave);
79 fBrowser.stop();
80 }
81 else if (octave != ARNote::getImplicitOctave())
82 fCurrentOctave = octave;
83 }
84
85 //_______________________________________________________________________________
86 // pitchApplyBaseOperation
87 //_______________________________________________________________________________
browse(const Sguidoelement & score)88 Sguidoelement pitchApplyBaseOperation::browse( const Sguidoelement& score ) {
89 fInChord = false;
90 Sguidoelement outscore;
91 if (score) {
92 fBrowser.browse (*score);
93 outscore = fStack.top();
94 fStack.pop();
95 }
96 return outscore;
97 }
98
99 //_______________________________________________________________________________
visitStart(SARVoice & elt)100 void pitchApplyBaseOperation::visitStart( SARVoice& elt )
101 {
102 fInChord = false;
103 fLastOctave = fCurrentOctave = fCurrentScoreOctave = ARNote::getDefaultOctave();
104 clonevisitor::visitStart (elt);
105 }
106
107 //_______________________________________________________________________________
setPitch(SARNote & note,const pitchvisitor::TPitch & pitch,int & currentOctave) const108 void pitchApplyBaseOperation::setPitch( SARNote& note, const pitchvisitor::TPitch& pitch, int& currentOctave ) const
109 {
110 int octave = pitch.fOctave;
111 if (octave == currentOctave) octave = ARNote::getImplicitOctave();
112 else currentOctave = octave;
113 note->setName(pitch.fName);
114 note->SetOctave(pitch.fOctave);
115 note->SetAccidental(pitch.fAlter);
116 }
117
118 //_______________________________________________________________________________
startChord(SARChord & elt,bool clone)119 void pitchApplyBaseOperation::startChord( SARChord& elt, bool clone )
120 {
121 fInChord = true;
122 fChordBase = (fMode == kUseHighest) ? -1 : 999;
123 if (clone) clonevisitor::visitStart (elt);
124 }
125
126 //_______________________________________________________________________________
endChord(SARChord & elt,int targetpitch,bool clone)127 void pitchApplyBaseOperation::endChord ( SARChord& elt, int targetpitch, bool clone )
128 {
129 fInChord = false;
130 if (!clone) {
131 octaveVisitor cv;
132 cv.forceOctave(elt, fLastOctave);
133 transposeOperation transpose;
134 Sguidoelement chord = transpose (Sguidoelement(elt), targetpitch - fChordBase);
135 if (chord) {
136 int octave = cv.getLastOctave(chord);
137 if (octave != ARNote::getDefaultOctave())
138 fCurrentOctave = octave;
139 push (chord, false);
140 }
141 }
142 else clonevisitor::visitEnd (elt);
143 }
144
145 //_______________________________________________________________________________
setChordBase(SARNote & currentelt)146 void pitchApplyBaseOperation::setChordBase ( SARNote& currentelt )
147 {
148 int currentpitch = currentelt->midiPitch(fCurrentScoreOctave);
149 switch (fMode) {
150 case kUseHighest:
151 if (currentpitch > fChordBase) fChordBase = currentpitch;
152 break;
153 case kUseLowest:
154 if (currentpitch < fChordBase) fChordBase = currentpitch;
155 break;
156 }
157 }
158
159 //_______________________________________________________________________________
octaveCheck(SARNote & elt)160 void pitchApplyBaseOperation::octaveCheck ( SARNote& elt )
161 {
162 if (fLastOctave != ARNote::getImplicitOctave()) {
163 int octave = elt->GetOctave();
164 if (ARNote::implicitOctave(octave)) elt->SetOctave(fLastOctave);
165 fLastOctave = ARNote::getImplicitOctave();
166 }
167 }
168
169 //_______________________________________________________________________________
startNote(SARNote & elt)170 SARNote pitchApplyBaseOperation::startNote ( SARNote& elt )
171 {
172 if (!elt->isPitched()) { clonevisitor::visitStart (elt); return 0; }
173
174 if (!elt->implicitOctave())
175 fCurrentScoreOctave = elt->GetOctave();
176 SARNote note = copy(elt);
177 if (note) {
178 if (!note->implicitOctave())
179 fLastOctave = note->GetOctave(); // store the last explicit octave
180 }
181 return note;
182 }
183
184 }
185