/**************************************************************************** PROJECT: MusixTeX PreProcessor FILE : duration.cc AUTHOR : J. C. Nieuwenhuizen copyright (c) FlowerSoft 1995 --*/ #if defined( __TURBOC__ ) && ( __TURBOC__ >= 0x300 ) #if !defined ( __NPLET_MAX ) #define __NPLET_MAX const int NPLET_MAX = 7; #endif #else // ! turboc 3.0 const int NPLET_MAX = 7; #endif #include #include #define max( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) #define min( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) #include "string.h" #include "init.h" #include "beam.h" #include "staff.h" #include "duration.h" #include "mpp.h" // DURATION_WHOLE duration of whole note in smallest unit possible. const int DURATION_WHOLE = 64 * 3 * 5 * 7; //* 9; // should be "long", 32 bits //spacing array const int SPACING_ARRAY = 5; const char spacingArray [ SPACING_ARRAY ][ 7 ] = { "\\NOTEs", // 1 "\\NOTes", // 2 "\\NOtes", // 4 "\\Notes", // 8 "\\notes", // 16 }; const int NOTESKIP_ARRAY = 5; //const int noteSkipArray [ NOTESKIP_ARRAY ][ 7 ] = { //duration indication array const int ALPHA_ARRAY = 8; const char alphaArray [ ALPHA_ARRAY ][ 6 ] = { "wh", "h", "q", "c", "cc", "ccc", "cccc", "ccccc" }; const int nnPlet[ 9 ] = { 1, // 3, // duplet 2, // triplet 3, // quartplet 4, // quintplet 4, // sextplet 4, // septplet 4, // octplet 4, // noneplet }; int onePlet = 1; #if 0 static int threePlet = 3; static int fivePlet = 5; //static int sixPlet = 6; static int sevenPlet = 7; //static int ninePlet = 9; #endif /**************************************************************************** class Duration --*/ Duration::Duration( const Duration& duration ) : beam( duration.beam ), dots( duration.dots ), multiplicity( duration.multiplicity ), _nPlet( duration._nPlet ), xDuration( duration.xDuration ) { if ( ( multiplicity < 0 ) || ( multiplicity > 4 ) ) { error( "illegal multiplicity", __FILE__, __LINE__ ); multiplicity = 0; } } //Duration::Duration( const int x, const int d, int& n ) : Duration::Duration( const int x, const int d, int n ) : beam( NOBEAM ), dots( d ), multiplicity( 0 ), _nPlet( n ), xDuration( x ) { if ( onePlet != 1 ) { error( "illegal onePlet", __FILE__, __LINE__ ); onePlet = 1; } if ( ( xDuration == 1 ) || ( xDuration == 2 ) || ( xDuration == 4 ) || ( xDuration == 8 ) || ( xDuration == 16 ) || ( xDuration == 32 ) || ( xDuration == 64 ) ) return; #if 0 if ( x % 3 ) nPlet = &threePlet; else if ( x % 5 ) nPlet = &fivePlet; else if ( x % 7 ) nPlet = &sevenPlet; #endif if ( x % 3 ) _nPlet = 3; else if ( x % 5 ) _nPlet = 5; else if ( x % 7 ) _nPlet = 7; xDuration = DURATION_WHOLE / x; xDuration = 1 << ( ord() - 1 ); int dd = duration(); while ( ( dd < x ) & ( dots < 2 ) ) { dots++; dd = duration(); } } Duration::Duration( istream& is ) : beam( NOBEAM ), dots( 0 ), multiplicity( 0 ), _nPlet( 1 ), xDuration( 0 ) { xDuration = 4; _getFrom( is ); } Duration::Duration( Staff& staff ) : beam( ( staff.beamCount ? *staff.beam : NOBEAM ) ), dots( 0 ), multiplicity( 0 ), // nPlet( ( staff.beamCount && ( *staff.beam != NOBEAM ) ) ? // &( staff.beam->nPlet ) : &onePlet ), _nPlet( 1 ), xDuration( 0 ) { getFrom( staff ); } Duration::~Duration() { ;// monitor << "~Duration"; } const char *Duration::alpha() const { int i = ord(); i = min( max ( i - 1, 0 ), ALPHA_ARRAY - 1 ); return alphaArray[ i ]; } int Duration::duration() const { ;// monitor << "Duration::duration" << endl; int duration = 0; if ( xDuration ) { duration = DURATION_WHOLE / nPlet() * nnPlet[ nPlet() - 1 ] / xDuration; int i = dots; while ( i-- ) duration += duration / 2; } ;// monitor << xDuration << '/' << nPlet() << ':' << duration << endl; if ( ( multiplicity < 0 ) || ( multiplicity > 4 ) ) error( "illegal multiplicity", __FILE__, __LINE__ ); return duration; } int Duration::getNPletFrom( Staff& staff ) { istream& is = *staff.is; char c = is.peek(); int nPlet = 1; if ( c == '/' ) // found nPlet { is.get ( c ); is.get ( c ); if ( !isdigit( c ) ) staff.error( quoteChar( "nPlet digit expected", c ) ); nPlet = (int)( c - '0' ); if ( ( nPlet < 1 ) || ( nPlet > 9 ) ) staff.warning( quoteChar( "illegal nPlet value", c ) ); } return nPlet; } int Duration::_getFrom( istream& is ) { ;// monitor << "Duration::_getFrom" << endl; int i = getNumber( is ); if ( i ) xDuration = i; char c = is.peek(); dots = 0; while ( c == '.' && !is.eof() ) { is.get( c ); dots++; c = is.peek(); } return xDuration; } int Duration::getFrom( Staff& staff ) { ;// monitor << "Duration::getFrom" << endl; istream& is = *staff.is; // ?? xDuration = staff.xDuration; xDuration = _getFrom( is ); _nPlet = getNPletFrom( staff ); char c = is.peek(); if ( c == ',' ) // x2,4 ; x4,2 x4,2 : 4 eights // x2,16 ; x4,8 x4,8 : 16 thirtyseconds // might change to: // x2,8 ; x4,8 x4,8 : 4 eights // x2,32 ; x4,32 x4,32 : 16 thirtyseconds { is.get( c ); int i = getNumber( is ); if ( dots == 1 ) i = i * 3 / 2; if ( xDuration <= 1 ) i /= 2; if ( xDuration <= 2 ) i /= 2; if ( ( i < 2 ) || ( i > 32 ) ) staff.error( quoteString( "illegal division" , String( i ) ) ); multiplicity = log2( i ) - 1; } return 0; } int Duration::getNumber( istream& is ) { char c = is.peek(); int i = 0; while ( isdigit( c ) && !is.eof() ) { is.get(c); i = i * 10 + ( c - '0' ); c = is.peek(); } return i; } int Duration::log2( const int x ) const { int i = 0; int n = x; while ( n && ( i < 7 ) ) { n >>= 1; i++; } if ( n ) i = 0; return i; } int Duration::noteSkip() const { ;// monitor << "Duration::noteSkip: " << endl; int i = ord(); if ( !i ) i = 5; if ( ( nPlet() == 3 ) || ( nPlet() == 6 ) ) i++; i = min( max ( i - 1, 0 ), NOTESKIP_ARRAY - 1 ); // int noteSkip = noteSkipArray[ i ]; int noteSkip = NOTESKIP_ARRAY + 1 - i; #if 0 if ( ( dots || ( nPlet() == 3 ) || ( nPlet() == 6 ) ) && ( i < 6 ) ) noteSkip = ( 2 * noteSkip + 1 ) / 2; #endif ;// monitor << noteSkip << endl; return noteSkip; } int Duration::nPlet() const { #if 1 //def __TURBOC__ // just to be safe: the errorObject might // not be initialized yet by turboc! // be sure to put object.o last in link order int i = ( &beam != &NOBEAM ? beam.nPlet : _nPlet ); #else int i = ( beam != NOBEAM ? beam.nPlet : _nPlet ); #endif if ( ( i < 1 ) || ( i > NPLET_MAX ) ) error( "illegal nPlet", __FILE__, __LINE__ ); return i; } int Duration::ord() const { /* xDuration i >> 1 1 -> 1 0 2 -> 2 1 4 -> 3 2 8 -> 4 4 */ return log2( xDuration ); } void Duration::printOn( ostream& os ) const { os << xDuration << String( '.', dots ); if ( nPlet() != 1 ) os << '/' << nPlet(); } const char* Duration::spacing() const { static String s; int i = ord(); if ( !i ) i = 5; #if 0 if ( ( nPlet() == 3 ) || ( nPlet() == 6 ) ) i++; #endif i = min( max ( i - 1, 0 ), SPACING_ARRAY - 1 ); s = spacingArray[ i ]; #if 0 if ( ( dots || ( nPlet() == 3 ) || ( nPlet() == 6 ) ) && ( i < 6 ) ) s += 'p'; #else if ( nPlet() != 1 ) s += 'h'; else if ( dots ) s += 'p'; #endif return s; } //-- class Duration //