import { AccidentalEnum } from "../../Common/DataObjects/Pitch" ; import { KeyInstruction } from "../VoiceData/Instructions/KeyInstruction" ; import { GraphicalNote } from "./GraphicalNote" ; import { Pitch } from "../../Common/DataObjects/Pitch" ; import { NoteEnum } from "../../Common/DataObjects/Pitch" ; import { Dictionary } from "typescript-collections" ; import { MusicSheetCalculator } from "./MusicSheetCalculator" ; /**
 * Compute the accidentals for notes according to the current key instruction
 */ export class AccidentalCalculator { private keySignatureNoteAlterationsDict : Dictionary < number , AccidentalEnum > = new Dictionary < number , AccidentalEnum > ( ) ; private currentAlterationsComparedToKeyInstructionList : number [ ] = [ ] ; private currentInMeasureNoteAlterationsDict : Dictionary < number , AccidentalEnum > = new Dictionary < number , AccidentalEnum > ( ) ; private activeKeyInstruction : KeyInstruction ; public get ActiveKeyInstruction ( ) : KeyInstruction { return this . activeKeyInstruction ; } public set ActiveKeyInstruction ( value ) { this . activeKeyInstruction = value ; this . reactOnKeyInstructionChange ( ) ; } /**
     * This method is called after each Measure
     * It clears the in-measure alterations dict for the next measure
     * and pre-loads with the alterations of the key signature
     */ public doCalculationsAtEndOfMeasure ( ) { this . currentInMeasureNoteAlterationsDict . clear ( ) ; this . currentAlterationsComparedToKeyInstructionList . clear ( ) ; for ( const key of this . keySignatureNoteAlterationsDict . keys ( ) ) { this . currentInMeasureNoteAlterationsDict . setValue ( key , this . keySignatureNoteAlterationsDict . getValue ( key ) ) ; } } public checkAccidental ( graphicalNote , pitch ) { if ( ! pitch ) { return ; } const pitchKey = < number > pitch . FundamentalNote + pitch . Octave * 12 ; const isInCurrentAlterationsToKeyList = this . currentAlterationsComparedToKeyInstructionList . indexOf ( pitchKey ) >= 0 ; if ( this . currentInMeasureNoteAlterationsDict . containsKey ( pitchKey ) ) { if ( isInCurrentAlterationsToKeyList ) { this . currentAlterationsComparedToKeyInstructionList . splice ( this . currentAlterationsComparedToKeyInstructionList . indexOf ( pitchKey ) , 1 ) ; } if ( this . currentInMeasureNoteAlterationsDict . getValue ( pitchKey ) !== pitch . AccidentalHalfTones ) { if ( this . keySignatureNoteAlterationsDict . containsKey ( pitchKey ) && this . keySignatureNoteAlterationsDict . getValue ( pitchKey ) !== pitch . AccidentalHalfTones ) { this . currentAlterationsComparedToKeyInstructionList . push ( pitchKey ) ; this . currentInMeasureNoteAlterationsDict . setValue ( pitchKey , pitch . AccidentalHalfTones ) ; } else if ( pitch . Accidental !== AccidentalEnum . NONE ) { this . currentInMeasureNoteAlterationsDict . remove ( pitchKey ) ; } const inMeasureAlterationAccidental = this . currentInMeasureNoteAlterationsDict . getValue ( pitchKey ) ; if ( pitch . Accidental === AccidentalEnum . NONE ) { if ( Math . abs ( inMeasureAlterationAccidental ) === 0.5 ) { pitch = new Pitch ( pitch . FundamentalNote , pitch . Octave , AccidentalEnum . NONE ) ; } else { pitch = new Pitch ( pitch . FundamentalNote , pitch . Octave , AccidentalEnum . NATURAL ) ; } } if ( this . isAlterAmbiguousAccidental ( pitch . Accidental ) && ! pitch . AccidentalXml ) { return ; } MusicSheetCalculator . symbolFactory . addGraphicalAccidental ( graphicalNote , pitch ) ; } } else { if ( pitch . Accidental !== AccidentalEnum . NONE ) { if ( ! isInCurrentAlterationsToKeyList ) { this . currentAlterationsComparedToKeyInstructionList . push ( pitchKey ) ; } this . currentInMeasureNoteAlterationsDict . setValue ( pitchKey , pitch . AccidentalHalfTones ) ; if ( this . isAlterAmbiguousAccidental ( pitch . Accidental ) && ! pitch . AccidentalXml ) { return ; } MusicSheetCalculator . symbolFactory . addGraphicalAccidental ( graphicalNote , pitch ) ; } else { if ( isInCurrentAlterationsToKeyList ) { pitch = new Pitch ( pitch . FundamentalNote , pitch . Octave , AccidentalEnum . NATURAL ) ; this . currentAlterationsComparedToKeyInstructionList . splice ( this . currentAlterationsComparedToKeyInstructionList . indexOf ( pitchKey ) , 1 ) ; MusicSheetCalculator . symbolFactory . addGraphicalAccidental ( graphicalNote , pitch ) ; } } } } private isAlterAmbiguousAccidental ( accidental ) { return accidental === AccidentalEnum . SLASHFLAT || accidental === AccidentalEnum . QUARTERTONEFLAT ; } private reactOnKeyInstructionChange ( ) { const noteEnums = this . activeKeyInstruction . AlteratedNotes ; let keyAccidentalType ; if ( this . activeKeyInstruction . Key > 0 ) { keyAccidentalType = AccidentalEnum . SHARP ; } else { keyAccidentalType = AccidentalEnum . FLAT ; } this . keySignatureNoteAlterationsDict . clear ( ) ; this . currentAlterationsComparedToKeyInstructionList . length = 0 ; for ( let octave = - 9 ; octave < 9 ; octave ++ ) { for ( let i = 0 ; i < noteEnums . length ; i ++ ) { this . keySignatureNoteAlterationsDict . setValue ( < number > noteEnums [ i ] + octave * 12 , Pitch . HalfTonesFromAccidental ( keyAccidentalType ) ) ; } } this . doCalculationsAtEndOfMeasure ( ) ; } }