import { Fraction } from "../Common/DataObjects/Fraction" ; import { MusicPartManager } from "./MusicParts/MusicPartManager" ; import { SourceMeasure } from "./VoiceData/SourceMeasure" ; import { Repetition } from "./MusicSource/Repetition" ; import { DynamicsContainer } from "./VoiceData/HelperObjects/DynamicsContainer" ; import { InstrumentalGroup } from "./InstrumentalGroup" ; import { Instrument } from "./Instrument" ; import { Label } from "./Label" ; import { Staff } from "./VoiceData/Staff" ; import { MusicPartManagerIterator } from "./MusicParts/MusicPartManagerIterator" ; import { VerticalSourceStaffEntryContainer } from "./VoiceData/VerticalSourceStaffEntryContainer" ; import { Voice } from "./VoiceData/Voice" ; import { MusicSheetErrors } from "../Common/DataObjects/MusicSheetErrors" ; import { MultiTempoExpression } from "./VoiceData/Expressions/MultiTempoExpression" ; import { EngravingRules } from "./Graphical/EngravingRules" ; import { NoteState } from "./Graphical/DrawingEnums" ; import { Note } from "./VoiceData/Note" ; import { VoiceEntry } from "./VoiceData/VoiceEntry" ; import log from "loglevel" ; export class PlaybackSettings { public rhythm : Fraction ; } /**
 * This is the representation of a complete piece of sheet music.
 * It includes the contents of a MusicXML file after the reading.
 * Notes: the musicsheet might not need the Rules, e.g. in the testframework. The EngravingRules Constructor
 * fails when no FontInfo exists, which needs a TextMeasurer
 */ export class MusicSheet { constructor ( ) { this . playbackSettings = new PlaybackSettings ( ) ; this . playbackSettings . rhythm = new Fraction ( 4 , 4 , 0 , false ) ; this . userStartTempoInBPM = 100 ; this . pageWidth = 120 ; this . MusicPartManager = new MusicPartManager ( this ) ; this . hasBPMInfo = false ; } public static defaultTitle : string = "[no title given]" ; public userStartTempoInBPM : number ; public pageWidth : number ; private idString : string = "random idString, not initialized" ; private sourceMeasures : SourceMeasure [ ] = [ ] ; private repetitions : Repetition [ ] = [ ] ; private dynListStaves : DynamicsContainer [ ] [ ] = [ ] ; private timestampSortedDynamicExpressionsList : DynamicsContainer [ ] = [ ] ; private timestampSortedTempoExpressionsList : MultiTempoExpression [ ] = [ ] ; private instrumentalGroups : InstrumentalGroup [ ] = [ ] ; /** The parts in the sheet, e.g. piano left hand, or piano right hand, or violin. */ private instruments : Instrument [ ] = [ ] ; private playbackSettings : PlaybackSettings ; private path : string ; private title : Label ; private subtitle : Label ; private composer : Label ; private lyricist : Label ; private musicPartManager : MusicPartManager = undefined ; private musicSheetErrors : MusicSheetErrors = new MusicSheetErrors ( ) ; private staves : Staff [ ] = [ ] ; private selectionStart : Fraction ; private selectionEnd : Fraction ; private transpose : number = 0 ; private defaultStartTempoInBpm : number = 0 ; private drawErroneousMeasures : boolean = false ; private hasBeenOpenedForTheFirstTime : boolean = false ; private currentEnrolledPosition : Fraction = new Fraction ( 0 , 1 ) ; private rules : EngravingRules ; private hasBPMInfo : boolean ; param staff returns { number } public static getIndexFromStaff ( staff ) { return staff . idInMusicSheet ; } public get SourceMeasures ( ) : SourceMeasure [ ] { return this . sourceMeasures ; } public set SourceMeasures ( value ) { this . sourceMeasures = value ; } public get Repetitions ( ) : Repetition [ ] { return this . repetitions ; } public set Repetitions ( value ) { this . repetitions = value ; } public get DynListStaves ( ) : DynamicsContainer [ ] [ ] { return this . dynListStaves ; } public get TimestampSortedTempoExpressionsList ( ) : MultiTempoExpression [ ] { return this . timestampSortedTempoExpressionsList ; } public get TimestampSortedDynamicExpressionsList ( ) : DynamicsContainer [ ] { return this . timestampSortedDynamicExpressionsList ; } public get InstrumentalGroups ( ) : InstrumentalGroup [ ] { return this . instrumentalGroups ; } public get Parts ( ) : Instrument [ ] { return this . instruments ; } public get Instruments ( ) : Instrument [ ] { return this . instruments ; } public get SheetPlaybackSetting ( ) : PlaybackSettings { return this . playbackSettings ; } public set SheetPlaybackSetting ( value ) { this . playbackSettings = value ; } public get DrawErroneousMeasures ( ) : boolean { return this . drawErroneousMeasures ; } public set DrawErroneousMeasures ( value ) { this . drawErroneousMeasures = value ; } public get HasBeenOpenedForTheFirstTime ( ) : boolean { return this . hasBeenOpenedForTheFirstTime ; } public set HasBeenOpenedForTheFirstTime ( value ) { this . hasBeenOpenedForTheFirstTime = value ; } public InitializeStartTempoInBPM ( startTempo ) { this . userStartTempoInBPM = startTempo ; } public get DefaultStartTempoInBpm ( ) : number { return this . defaultStartTempoInBpm ; } public set DefaultStartTempoInBpm ( value ) { this . defaultStartTempoInBpm = value ; this . InitializeStartTempoInBPM ( value ) ; } public get Path ( ) : string { return this . path ; } public set Path ( value ) { this . path = value ; } public get Staves ( ) : Staff [ ] { return this . staves ; } public get TitleString ( ) : string { if ( this . title ) { return this . title . text ; } else { return "" ; } } public set TitleString ( value ) { this . Title = new Label ( value ) ; } public get SubtitleString ( ) : string { if ( this . subtitle ) { return this . subtitle . text ; } else { return "" ; } } public set SubtitleString ( value ) { this . Subtitle = new Label ( value ) ; } public get ComposerString ( ) : string { if ( this . composer ) { return this . composer . text ; } else { return "" ; } } public set ComposerString ( value ) { this . Composer = new Label ( value ) ; } public get LyricistString ( ) : string { if ( this . lyricist ) { return this . lyricist . text ; } else { return "" ; } } public set LyricistString ( value ) { this . Lyricist = new Label ( value ) ; } public get Title ( ) : Label { return this . title ; } public set Title ( value ) { this . title = value ; } public get Subtitle ( ) : Label { return this . subtitle ; } public set Subtitle ( value ) { this . subtitle = value ; } public get Composer ( ) : Label { return this . composer ; } public set Composer ( value ) { this . composer = value ; } public get Lyricist ( ) : Label { return this . lyricist ; } public set Lyricist ( value ) { this . lyricist = value ; } public get Rules ( ) : EngravingRules { if ( ! this . rules ) { log . debug ( "warning: sheet.Rules was undefined. Creating new EngravingRules." ) ; this . rules = new EngravingRules ( ) ; } return this . rules ; } public set Rules ( value ) { this . rules = value ; } public get SheetErrors ( ) : MusicSheetErrors { return this . musicSheetErrors ; } public get SelectionStart ( ) : Fraction { return this . selectionStart ; } public set SelectionStart ( value ) { this . selectionStart = value . clone ( ) ; this . currentEnrolledPosition = value . clone ( ) ; } public get SelectionEnd ( ) : Fraction { return this . selectionEnd ; } public set SelectionEnd ( value ) { this . selectionEnd = value ; } public set HasBPMInfo ( value ) { this . hasBPMInfo = value ; } public get HasBPMInfo ( ) : boolean { return this . hasBPMInfo ; } public addMeasure ( measure ) { this . sourceMeasures . push ( measure ) ; measure . measureListIndex = this . sourceMeasures . length - 1 ; } public checkForInstrumentWithNoVoice ( ) { for ( let idx = 0 , len = this . instruments . length ; idx < len ; ++ idx ) { const instrument = this . instruments [ idx ] ; if ( instrument . Voices . length === 0 ) { const voice = new Voice ( instrument , 1 ) ; instrument . Voices . push ( voice ) ; } } } param staffIndexInMusicSheet returns { Staff } public getStaffFromIndex ( staffIndexInMusicSheet ) { return this . staves [ staffIndexInMusicSheet ] ; } public fillStaffList ( ) { let i = 0 ; for ( let idx = 0 , len = this . instruments . length ; idx < len ; ++ idx ) { const instrument = this . instruments [ idx ] ; for ( let idx2 = 0 , len2 = instrument . Staves . length ; idx2 < len2 ; ++ idx2 ) { const staff = instrument . Staves [ idx2 ] ; staff . idInMusicSheet = i ; this . staves . push ( staff ) ; i ++ ; } } } public get MusicPartManager ( ) : MusicPartManager { return this . musicPartManager ; } public set MusicPartManager ( value ) { this . musicPartManager = value ; } public getCompleteNumberOfStaves ( ) { let num = 0 ; for ( let idx = 0 , len = this . instruments . length ; idx < len ; ++ idx ) { const instrument = this . instruments [ idx ] ; num += instrument . Staves . length ; } return num ; } param start param end returns { SourceMeasure [ ] } public getListOfMeasuresFromIndeces ( start , end ) { const measures = [ ] ; for ( let i = start ; i <= end ; i ++ ) { measures . push ( this . sourceMeasures [ i ] ) ; } return measures ; } param measure public getNextSourceMeasure ( measure ) { const index = this . sourceMeasures . indexOf ( measure ) ; if ( index === this . sourceMeasures . length - 1 ) { return measure ; } return this . sourceMeasures [ index + 1 ] ; } /**
     * Returns the first SourceMeasure of MusicSheet.
     */ public getFirstSourceMeasure ( ) { return this . sourceMeasures [ 0 ] ; } /**
     * Returns the last SourceMeasure of MusicSheet.
     */ public getLastSourceMeasure ( ) { return this . sourceMeasures [ this . sourceMeasures . length - 1 ] ; } public resetAllNoteStates ( ) { const iterator = this . MusicPartManager . getIterator ( ) ; while ( ! iterator . EndReached && iterator . CurrentVoiceEntries ) { for ( let idx = 0 , len = iterator . CurrentVoiceEntries . length ; idx < len ; ++ idx ) { const voiceEntry = iterator . CurrentVoiceEntries [ idx ] ; for ( let idx2 = 0 , len2 = voiceEntry . Notes . length ; idx2 < len2 ; ++ idx2 ) { const note = voiceEntry . Notes [ idx2 ] ; note . state = NoteState . Normal ; } } iterator . moveToNext ( ) ; } } public getMusicSheetInstrumentIndex ( instrument ) { return this . Instruments . indexOf ( instrument ) ; } public getGlobalStaffIndexOfFirstStaff ( instrument ) { const instrumentIndex = this . getMusicSheetInstrumentIndex ( instrument ) ; let staffLineIndex = 0 ; for ( let i = 0 ; i < instrumentIndex ; i ++ ) { staffLineIndex += this . Instruments [ i ] . Staves . length ; } return staffLineIndex ; } param index param value public setRepetitionNewUserNumberOfRepetitions ( index , value ) { let repIndex = 0 ; for ( let i = 0 ; i < this . repetitions . length ; i ++ ) { if ( this . repetitions [ i ] instanceof Repetition ) { if ( index === repIndex ) { this . repetitions [ i ] . UserNumberOfRepetitions = value ; break ; } else { repIndex ++ ; } } } } param index returns { any } public getRepetitionByIndex ( index ) { let repIndex = 0 ; for ( let i = 0 ; i < this . repetitions . length ; i ++ ) { if ( this . repetitions [ i ] instanceof Repetition ) { if ( index === repIndex ) { return < Repetition > this . repetitions [ i ] ; } repIndex ++ ; } } return undefined ; } public CompareTo ( other ) { return this . Title . text . localeCompare ( other . Title . text ) ; } public getExpressionsStartTempoInBPM ( ) { if ( this . TimestampSortedTempoExpressionsList . length > 0 ) { const me = this . TimestampSortedTempoExpressionsList [ 0 ] ; if ( me . InstantaneousTempo ) { return me . InstantaneousTempo . TempoInBpm ; } else if ( me . ContinuousTempo ) { return me . ContinuousTempo . StartTempo ; } } return this . userStartTempoInBPM ; } public get Errors ( ) : { [ n ] : string [ ] ; } { return this . musicSheetErrors . measureErrors ; } public get FirstMeasureNumber ( ) : number { try { return this . getFirstSourceMeasure ( ) . MeasureNumber ; } catch ( ex ) { log . info ( "MusicSheet.FirstMeasureNumber: " , ex ) ; return 0 ; } } public get LastMeasureNumber ( ) : number { try { return this . getLastSourceMeasure ( ) . MeasureNumber ; } catch ( ex ) { log . info ( "MusicSheet.LastMeasureNumber: " , ex ) ; return 0 ; } } public get CurrentEnrolledPosition ( ) : Fraction { return this . currentEnrolledPosition . clone ( ) ; } public set CurrentEnrolledPosition ( value ) { this . currentEnrolledPosition = value . clone ( ) ; } public get Transpose ( ) : number { return this . transpose ; } public set Transpose ( value ) { this . transpose = value ; } public get FullNameString ( ) : string { return this . ComposerString + " " + this . TitleString ; } public get IdString ( ) : string { return this . idString ; } public set IdString ( value ) { this . idString = value ; } public getEnrolledSelectionStartTimeStampWorkaround ( ) { const iter = this . MusicPartManager . getIterator ( this . SelectionStart ) ; return Fraction . createFromFraction ( iter . CurrentEnrolledTimestamp ) ; } public get SheetEndTimestamp ( ) : Fraction { const lastMeasure = this . getLastSourceMeasure ( ) ; return Fraction . plus ( lastMeasure . AbsoluteTimestamp , lastMeasure . Duration ) ; } param timeStamp returns { SourceMeasure } public getSourceMeasureFromTimeStamp ( timeStamp ) { for ( let idx = 0 , len = this . sourceMeasures . length ; idx < len ; ++ idx ) { const sm = this . sourceMeasures [ idx ] ; for ( let idx2 = 0 , len2 = sm . VerticalSourceStaffEntryContainers . length ; idx2 < len2 ; ++ idx2 ) { const vssec = sm . VerticalSourceStaffEntryContainers [ idx2 ] ; if ( timeStamp . Equals ( vssec . getAbsoluteTimestamp ( ) ) ) { return sm ; } } } return this . findSourceMeasureFromTimeStamp ( timeStamp ) ; } public findSourceMeasureFromTimeStamp ( timestamp ) { for ( const sm of this . sourceMeasures ) { if ( sm . AbsoluteTimestamp . lte ( timestamp ) && timestamp . lt ( Fraction . plus ( sm . AbsoluteTimestamp , sm . Duration ) ) ) { return sm ; } } } public getVisibleInstruments ( ) { const visInstruments = [ ] ; for ( let idx = 0 , len = this . Instruments . length ; idx < len ; ++ idx ) { const instrument = this . Instruments [ idx ] ; if ( instrument . Voices . length > 0 && instrument . Voices [ 0 ] . Visible ) { visInstruments . push ( instrument ) ; } } return visInstruments ; } }