/**************************************************************************** PROJECT: MusixTeX PreProcessor FILE : beamnote.cc AUTHOR : J. C. Nieuwenhuizen copyright (c) FlowerSoft 1995 --*/ #define max( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) #define min( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) #define abs( a ) ( ( ( a ) > 0 ) ? ( a ) : ( - ( a ) ) ) #define sign( a ) ( ( ( a ) > 0 ) ? ( 1 ) : ( - 1 ) ) #include "beam.h" #include "chord.h" #include "notename.h" // only for name.name in warning #include "beamnote.h" #include "beamlist.h" #include "duration.h" #include "featlist.h" #include "script.h" #include "staff.h" #include "init.h" #include "mpp.h" static Duration duration4( 4 ); static int ord4 = duration4.ord(); /**************************************************************************** class BeamNote --*/ BeamNote* BeamNote::last = &NOBEAMNOTE; BeamNote::BeamNote( SimpleNote& note ) : SimpleNote( note ), // beamNoteCount( beam.noteCount ), continuedBeamMultiplicity( staff.beamCount ) { if ( beam == NOBEAM ) staff.error( "BeamNote: no beam" ); if ( !beam.noteCount ) beam.noteCount = 1; beamNoteCount = beam.noteCount; } BeamNote::~BeamNote() { } void BeamNote::calculate() { // no accurate line number with warning... if ( ( _duration.ord() <= ord4 ) && !chord && ( ( beam.nPlet > 1 ) && ( beam.nPlet < 10 ) ) ) staff.warning( quoteString( "non flagged note on beam", name.name ) ); if ( ( beam.nPlet != 1 ) && ( ( beam.nPlet + 1 ) / beamNoteCount == 2 ) && !chord ) { String featureString; // featureString = ( beam.orientation == UP ? "^" : "_" ); // featureString += "{\\xplet}"; // os << "\\def\\txt{\\lower.4\\Interligne\\rlap{~" << beam.nPlet << "}}"; featureString = "xplet{"; if ( beam.orientation == UP ) // featureString += "\\lower.4\\Interligne\\rlap{~"; // featureString += "\\rlap{~"; featureString += "\\raise.4\\Interligne\\rlap{~"; else featureString += "{"; featureString += String( beam.nPlet ); featureString += "}}"; Script& feature = *new Script( Feature::TEXT, NESTED_IN( Token )Orientation( beam.orientation ) ); feature.substitute = featureString; featureList.put( feature ); } calculateStem(); SimpleNote::calculate(); calculateBeam(); } void BeamNote::calculateBeam() { // one pass heritage; this gets out of hand // must be reinterpreted and handled by // InitiateBeam if ( _duration.ord() - ord4 > beam.multiplicity ) increaseMultiplicity(); else if ( _duration.ord() - ord4 < beam.multiplicity ) decreaseMultiplicity(); last = this; if ( !continuedBeamMultiplicity ) beam.multiplicity = 0; } void BeamNote::calculateFeaturePitch() { #if 0 // nonsense, beam is no different from other note // xcept: (same direction) slur on beam: beamslur // slur on note: lower(...) by stemlength int pitchAdjustArray[ 3 ] = { 0, 0, 0 }; int *const pitchAdjust = &pitchAdjustArray[ 1 ]; pitchAdjust[ beam.orientation ] = beam.orientation * max( 0, beam.orientation * ( beam.effectivePitch( beamNoteCount ) - ( pitch() - stemLength ) ) ); featurePitch[ DOWN ] = pitch() + pitchAdjust[ DOWN ]; featurePitch[ UP ] = pitch() + pitchAdjust[ UP ]; #else // see Slur::calculate too SimpleNote::calculateFeaturePitch(); #endif } void BeamNote::calculateStem() { orientation = StemOrientation( beam.orientation ); } /* [8 16] \Notes\ibu0{!'a}{0}\qb0{!'a}% \en \notes\loff{\nbbu0}\tbu0\qb0{!'a}% \en : if terminate beam and this > lastnote [16 8] : if lastnote first of beam and this < lastnote \Notes\ibu0{!'a}{0}\qb0{!'a}% \en \notes\loffset{2}{\tbbu0}\tbu0\qb0{!'a}% \en */ void BeamNote::decreaseMultiplicity() { int multiplicity = _duration.ord() - ord4; NESTED_IN( InitiateBeam )Flag flag = ( _duration.dots ? InitiateBeam::LEFT : InitiateBeam::NO ); if ( last != &NOBEAMNOTE ) { if ( !last->beamList.empty() ) if ( String( last->beamList.bottom().name ) == "InitMultiBeam" ) delete &last->beamList.remove(); // flag only bound to note if // if ( last->terminateBeamList.empty() && !terminateBeamList.empty() ) if ( last->terminateBeamList.empty() && !terminateBeamList.empty() && last->beamList.empty() ) flag = InitiateBeam::NO; } // multiple beam started on last note // insert; reverse order int bm = beam.multiplicity; if ( !flag && ( last != &NOBEAMNOTE ) ) { for ( int i = bm; i > multiplicity; i-- ) last->beamList.put( *new TermMultiBeam( beam, i - 1, flag ) ); } else { for ( int i = multiplicity; i < bm; i++ ) terminateBeamList.insert( *new TermMultiBeam( beam, i, flag ) ); } } void BeamNote::increaseMultiplicity() { // beam initiated and terminated on this note if ( !continuedBeamMultiplicity ) terminateBeamList.insert( *new InitMultiBeam( beam, _duration.ord() - ord4, InitiateBeam::LEFT ) ); else { // 95.07.21; nasty patch... perhaps need for Chord& chord iso Boolean chord // if ( !chord ) // beamList.put( *new InitMultiBeam( beam, _duration.ord() - ord4 ) ); // else // 95.08.2; even nastier patch (check beam.mpp) // do run musixflex! // terminateBeamList.insert( *new InitMultiBeam( beam, _duration.ord() - ord4, // ( chord ? InitiateBeam::LEFT : InitiateBeam::NO ) ) ); NESTED_IN( InitiateBeam )Flag flag = ( chord ? InitiateBeam::RIGHT : InitiateBeam::NO ); if ( ( last != &NOBEAMNOTE ) && last->_duration.dots ) flag = InitiateBeam::LEFT; if ( beamList.empty() ) terminateBeamList.insert( *new InitMultiBeam( beam, _duration.ord() - ord4, flag ) ); /// ( chord ? InitiateBeam::LEFT : InitiateBeam::NO ) ) ); else beamList.put( *new InitMultiBeam( beam, _duration.ord() - ord4, ( !terminateBeamList.empty() ? InitiateBeam::LEFT : InitiateBeam::NO ) ) ); } } void BeamNote::printDurationOn( ostream& os ) const { if ( stem & BEAM ) os << 'q'; else SimpleNote::printDurationOn( os ); } void BeamNote::printNameOn( ostream& os ) const { if ( stem & BEAM ) os << beamNumber; SimpleNote::printNameOn( os ); } void BeamNote::printOn( ostream& os ) const { ;// monitor << "BeamNote::printOn" << endl; #if 0 if ( nPletFeature ) { os << "\\def\\txt{\\lower.4\\Interligne\\rlap{~" << beam.nPlet << "}}"; os << *nPletFeature; } #endif SimpleNote::printOn( os ); } void BeamNote::printStemOn( ostream& os ) const { if ( stem & BEAM ) os << 'b'; else SimpleNote::printStemOn( os ); } //-- BeamNote // /**************************************************************************** class Rest --*/ int Rest::_pitch = -1; Rest::Rest( SimpleNote& note ) : SimpleNote( note ) { } Rest::~Rest() { } void Rest::calculate() { SimpleNote::calculate(); } void Rest::calculateFeaturePitch() { featurePitch[ DOWN ] = staff.midPitch - 4; featurePitch[ UP ] = staff.midPitch + 4; } int Rest::pitch() const { return _pitch; } void Rest::printNameOn( ostream& os ) const { os << 's'; } void Rest::printOn( ostream& os ) const { if ( chord ) { if ( orientation == UP ) os << "\\raise\\Interligne"; else os << "\\lower\\Interligne"; } SimpleNote::printOn( os ); } void Rest::printStemOn( ostream& ) const { } //-- Rest // /**************************************************************************** class GhostNote --*/ int GhostNote::_pitch = -2; GhostNote::GhostNote( SimpleNote& note ) : SimpleNote( note ) { } GhostNote::~GhostNote() { } void GhostNote::calculate() { SimpleNote::calculate(); } void GhostNote::calculateFeaturePitch() { featurePitch[ DOWN ] = staff.midPitch - 4; featurePitch[ UP ] = staff.midPitch + 4; } int GhostNote::pitch() const { return _pitch; } void GhostNote::printOn( ostream& os ) const { SimpleNote::printListsOn( os ); } //-- GhostNote //