1 /*
2   Copyright © Grame 2008
3 
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Lesser General Public
6     License as published by the Free Software Foundation; either
7     version 2.1 of the License, or (at your option) any later version.
8 
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Lesser General Public License for more details.
13 
14     You should have received a copy of the GNU Lesser General Public
15     License along with this library; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 
18     Grame Research Laboratory, 9, rue du Garet 69001 Lyon - France
19     research@grame.fr
20 
21 */
22 
23 #ifndef __pitchApplyOperation__
24 #define __pitchApplyOperation__
25 
26 #include <vector>
27 #include <iostream>
28 
29 #include "ARChord.h"
30 #include "ARNote.h"
31 #include "AROthers.h"
32 #include "arexport.h"
33 #include "clonevisitor.h"
34 #include "operation.h"
35 #include "guidorational.h"
36 #include "pitchvisitor.h"
37 #include "transposeOperation.h"
38 #include "tree_browser.h"
39 
40 namespace guido
41 {
42 
43 /*!
44 \addtogroup operations
45 @{
46 */
47 
48 /*!
49 \brief the base visitor of pitch application.
50 
51 	Intended to minimize code size.
52 	Can only be instantiated by derived class.
53 */
54 class gar_export pitchApplyBaseOperation :
55 	public operation,
56 	public clonevisitor
57 {
58     protected:
pitchApplyBaseOperation(chordPitchMode m)59  				 pitchApplyBaseOperation(chordPitchMode m) : fMode(m) { fBrowser.set(this); }
~pitchApplyBaseOperation()60 		virtual ~pitchApplyBaseOperation()	{}
61 
62 
63 		bool	fInChord;
64 		chordPitchMode fMode;	// the chord pitch extraction and application mode;
65 		tree_browser<guidoelement>	fBrowser;
66 		int		fCurrentScoreOctave;	// the original score current octave
67 		int		fCurrentOctave;			// used to code implicit octave
68 		int		fLastOctave;			// used to restore correct octave at iterator end pos and at chords beginning
69 		int		fChordBase;				// used to transpose chords
70 
71 		Sguidoelement browse		( const Sguidoelement& score );
72 		virtual void visitStart		( SARVoice& elt );
73 		virtual void setPitch		( SARNote& note, const pitchvisitor::TPitch& pitch, int& currentOctave ) const;
74 		virtual void startChord		( SARChord& elt, bool clone );
75 		virtual void endChord		( SARChord& elt, int targetpitch,  bool clone );
76 		virtual void setChordBase	( SARNote& elt );
77 		virtual void octaveCheck	( SARNote& elt );
78 		virtual SARNote startNote	( SARNote& elt );
79 };
80 
81 /*!
82 \brief A visitor that applies a list of pitches to a score.
83 */
84 template <typename T> class gar_export pitchApplyOperation : public pitchApplyBaseOperation
85 {
86     public:
87 		typedef typename T::iterator pitchIterator;
pitchApplyOperation(chordPitchMode m)88  				 pitchApplyOperation(chordPitchMode m) : pitchApplyBaseOperation(m) {}
~pitchApplyOperation()89 		virtual ~pitchApplyOperation()	{}
90 
91 		/*! applies a list of pitches to a score
92 			\param score the taret score
93 			\param start an iterator on pitch values
94 			\param end an iterator on the end of pitch values
95 			\return a new score
96 		*/
operator()97 		Sguidoelement operator() ( const Sguidoelement& score, pitchIterator start, pitchIterator end ) {
98 			fPos = start;
99 			fEndPos = end;
100 			return browse(score);
101 		}
102 
103 		/*! applies a list of durations to a score
104 			\param score1 the taret score
105 			\param score2 a score which pitch is applied to the target score
106 			\return a new score
107 			\note pitch is extracted from the first voice only.
108 		*/
operator()109 		SARMusic operator() ( const SARMusic& score1, const SARMusic& score2 )
110 		{
111 			pitchvisitor pv(fMode);
112 			T list;
113 			pv.pitch(score2, 0, &list);
114 			Sguidoelement elt = (*this)(score1, list.begin(), list.end());
115 			return dynamic_cast<ARMusic*>((guidoelement*)elt);
116 		}
117 
118     protected:
119 		typename T::iterator fPos, fEndPos;
120 
visitStart(SARNote & elt)121 		virtual void visitStart( SARNote& elt ) {
122 			SARNote note = startNote(elt);
123 			if (note) {
124 				if (fPos != fEndPos) {
125 					pitchvisitor::TPitch pitch = *fPos;
126 					if (!fInChord) {
127 						setPitch( note, pitch, fCurrentOctave);
128 						push( note );
129 						fPos++;
130 					}
131 					else setChordBase (elt);
132 				}
133 				else {
134 					octaveCheck (note);
135 					push( note );
136 				}
137 			}
138 		}
139 
visitStart(SARChord & elt)140 		virtual void visitStart( SARChord& elt ) { startChord (elt, fPos == fEndPos); }
visitEnd(SARChord & elt)141 		virtual void visitEnd  ( SARChord& elt ) {
142 			if (fPos == fEndPos) endChord (elt, 0, true);
143 			else {
144 				endChord (elt, pitchvisitor::midiPitch (*fPos), false);
145 				fPos++;
146 			}
147 		}
148 };
149 
150 /// \brief a specialized class on low chords pitches
151 template <typename T> class gar_export pitchLowApplyOperation : public pitchApplyOperation<T>
152 {
pitchLowApplyOperation()153     public: pitchLowApplyOperation() : pitchApplyOperation<T>(kUseLowest) {}
154 };
155 
156 /// \brief a specialized class on high chords pitches
157 template <typename T> class gar_export pitchHighApplyOperation : public pitchApplyOperation<T>
158 {
pitchHighApplyOperation()159     public: pitchHighApplyOperation() : pitchApplyOperation<T>(kUseHighest) {}
160 };
161 
162 /*! @} */
163 
164 } // namespace MusicXML
165 
166 
167 #endif
168