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