import { Fraction } from "../../Common/DataObjects/Fraction" ; import { VerticalSourceStaffEntryContainer } from "./VerticalSourceStaffEntryContainer" ; import { Staff } from "./Staff" ; import { AbstractNotationInstruction } from "./Instructions/AbstractNotationInstruction" ; import { VoiceEntry } from "./VoiceEntry" ; import { Note } from "./Note" ; import { StaffEntryLink } from "./StaffEntryLink" ; import { ChordSymbolContainer } from "./ChordSymbolContainer" ; import { ClefInstruction } from "./Instructions/ClefInstruction" ; import { KeyInstruction } from "./Instructions/KeyInstruction" ; import { RhythmInstruction } from "./Instructions/RhythmInstruction" ; /**
 * A [[SourceStaffEntry]] is a container spanning all the [[VoiceEntry]]s at one timestamp for one [[StaffLine]].
 */ export class SourceStaffEntry { constructor ( verticalContainerParent , parentStaff ) { this . verticalContainerParent = verticalContainerParent ; this . parentStaff = parentStaff ; } private parentStaff : Staff ; private verticalContainerParent : VerticalSourceStaffEntryContainer ; private voiceEntries : VoiceEntry [ ] = [ ] ; private staffEntryLink : StaffEntryLink ; private instructions : AbstractNotationInstruction [ ] = [ ] ; private chordSymbolContainers : ChordSymbolContainer [ ] = [ ] ; public get ParentStaff ( ) : Staff { return this . parentStaff ; } public get VerticalContainerParent ( ) : VerticalSourceStaffEntryContainer { return this . verticalContainerParent ; } public get Timestamp ( ) : Fraction { if ( this . VerticalContainerParent ) { return this . VerticalContainerParent . Timestamp ; } return undefined ; } public get AbsoluteTimestamp ( ) : Fraction { if ( this . VerticalContainerParent ) { return Fraction . plus ( this . VerticalContainerParent . ParentMeasure . AbsoluteTimestamp , this . VerticalContainerParent . Timestamp ) ; } return undefined ; } public get VoiceEntries ( ) : VoiceEntry [ ] { return this . voiceEntries ; } public set VoiceEntries ( value ) { this . voiceEntries = value ; } public get Link ( ) : StaffEntryLink { return this . staffEntryLink ; } public set Link ( value ) { this . staffEntryLink = value ; } public get Instructions ( ) : AbstractNotationInstruction [ ] { return this . instructions ; } public set Instructions ( value ) { this . instructions = value ; } public get ChordContainers ( ) : ChordSymbolContainer [ ] { return this . chordSymbolContainers ; } public set ChordContainers ( value ) { this . chordSymbolContainers = value ; } public removeAllInstructionsOfTypeClefInstruction ( ) { let i = 0 ; let ret = 0 ; while ( i < this . instructions . length ) { if ( this . instructions [ i ] instanceof ClefInstruction ) { this . instructions . splice ( i , 1 ) ; ret ++ ; } else { i ++ ; } } return ret ; } returns { boolean } public removeFirstInstructionOfTypeClefInstruction ( ) { for ( let i = 0 ; i < this . instructions . length ; i ++ ) { if ( this . instructions [ i ] instanceof ClefInstruction ) { this . instructions . splice ( i , 1 ) ; return true ; } } return false ; } public removeAllInstructionsOfTypeKeyInstruction ( ) { let i = 0 ; let ret = 0 ; while ( i < this . instructions . length ) { if ( this . instructions [ i ] instanceof KeyInstruction ) { this . instructions . splice ( i , 1 ) ; ret ++ ; } else { i ++ ; } } return ret ; } returns { boolean } public removeFirstInstructionOfTypeKeyInstruction ( ) { for ( let i = 0 ; i < this . instructions . length ; i ++ ) { if ( this . instructions [ i ] instanceof KeyInstruction ) { this . instructions . splice ( i , 1 ) ; return true ; } } return false ; } public removeAllInstructionsOfTypeRhythmInstruction ( ) { let i = 0 ; let ret = 0 ; while ( i < this . instructions . length ) { if ( this . instructions [ i ] instanceof RhythmInstruction ) { this . instructions . splice ( i , 1 ) ; ret ++ ; } else { i ++ ; } } return ret ; } public removeFirstInstructionOfTypeRhythmInstruction ( ) { for ( let i = 0 ; i < this . instructions . length ; i ++ ) { if ( this . instructions [ i ] instanceof RhythmInstruction ) { this . instructions . splice ( i , 1 ) ; return true ; } } return false ; } returns { Fraction } public calculateMinNoteLength ( ) { let duration = new Fraction ( Number . MAX_VALUE , 1 ) ; for ( let idx = 0 , len = this . VoiceEntries . length ; idx < len ; ++ idx ) { const voiceEntry = this . VoiceEntries [ idx ] ; for ( let idx2 = 0 , len2 = voiceEntry . Notes . length ; idx2 < len2 ; ++ idx2 ) { const note = voiceEntry . Notes [ idx2 ] ; if ( note . Length . lt ( duration ) ) { duration = note . Length ; } } } return duration ; } public calculateMaxNoteLength ( ) { let duration = new Fraction ( 0 , 1 ) ; for ( let idx = 0 , len = this . VoiceEntries . length ; idx < len ; ++ idx ) { const voiceEntry = this . VoiceEntries [ idx ] ; for ( let idx2 = 0 , len2 = voiceEntry . Notes . length ; idx2 < len2 ; ++ idx2 ) { const note = voiceEntry . Notes [ idx2 ] ; if ( note . NoteTie ) { const tieRestDuration = Fraction . createFromFraction ( note . Length ) ; let addFollowingNotes = false ; for ( const n of note . NoteTie . Notes ) { if ( n === note ) { addFollowingNotes = true ; continue ; } if ( addFollowingNotes ) { tieRestDuration . Add ( n . Length ) ; } } if ( duration . lt ( tieRestDuration ) ) { duration = tieRestDuration ; } } else if ( duration . lt ( note . Length ) ) { duration = note . Length ; } } } return duration ; } public hasNotes ( ) { for ( let idx = 0 , len = this . VoiceEntries . length ; idx < len ; ++ idx ) { const voiceEntry = this . VoiceEntries [ idx ] ; if ( voiceEntry . Notes . length > 0 ) { return true ; } } return false ; } public hasTie ( ) { for ( let idx = 0 , len = this . VoiceEntries . length ; idx < len ; ++ idx ) { const voiceEntry = this . VoiceEntries [ idx ] ; if ( voiceEntry . hasTie ( ) ) { return true ; } } return false ; } public findLinkedNotes ( linkedNotes ) { for ( let idx = 0 , len = this . voiceEntries . length ; idx < len ; ++ idx ) { const voiceEntry = this . voiceEntries [ idx ] ; for ( let idx2 = 0 , len2 = voiceEntry . Notes . length ; idx2 < len2 ; ++ idx2 ) { const note = voiceEntry . Notes [ idx2 ] ; if ( note . ParentStaffEntry === this ) { linkedNotes . push ( note ) ; } } } } public get hasOnlyRests ( ) : boolean { for ( const voiceEntry of this . voiceEntries ) { for ( const note of voiceEntry . Notes ) { if ( ! note . isRest ) { return false ; } } } return true ; } }