瀏覽代碼

feat(transpose) Cherrypicking transpose updates (#733)
Make TransposeCalculator exported member so it can be accessed
Various fixes to get transpose functionality working

Justin Litten 5 年之前
父節點
當前提交
8357fd4e9c

+ 13 - 3
src/MusicalScore/Graphical/AccidentalCalculator.ts

@@ -26,6 +26,8 @@ export class AccidentalCalculator {
 
     /**
      * 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(): void {
         this.currentInMeasureNoteAlterationsDict.clear();
@@ -72,10 +74,16 @@ export class AccidentalCalculator {
                 } else {
                     this.currentInMeasureNoteAlterationsDict.remove(pitchKey);
                 }
+
+                if (pitch.Accidental === AccidentalEnum.NONE) {
+                    // If an AccidentalEnum.NONE is given, it would not be rendered.
+                    // We need here to convert to a AccidentalEnum.NATURAL:
+                    pitch = new Pitch(pitch.FundamentalNote, pitch.Octave, AccidentalEnum.NATURAL);
+                }
                 MusicSheetCalculator.symbolFactory.addGraphicalAccidental(graphicalNote, pitch);
             }
-        } else {
-            if (pitch.Accidental !== AccidentalEnum.NONE && pitch.Accidental !== AccidentalEnum.NATURAL) {
+        } else { // pitchkey not in measure dict:
+            if (pitch.Accidental !== AccidentalEnum.NONE) {
                 if (!isInCurrentAlterationsToKeyList) {
                     this.currentAlterationsComparedToKeyInstructionList.push(pitchKey);
                 }
@@ -83,6 +91,8 @@ export class AccidentalCalculator {
                 MusicSheetCalculator.symbolFactory.addGraphicalAccidental(graphicalNote, pitch);
             } else {
                 if (isInCurrentAlterationsToKeyList) {
+                    // we need here a AccidentalEnum.NATURAL now to get it rendered - AccidentalEnum.NONE would not be rendered
+                    pitch = new Pitch(pitch.FundamentalNote, pitch.Octave, AccidentalEnum.NATURAL);
                     this.currentAlterationsComparedToKeyInstructionList.splice(this.currentAlterationsComparedToKeyInstructionList.indexOf(pitchKey), 1);
                     MusicSheetCalculator.symbolFactory.addGraphicalAccidental(graphicalNote, pitch);
                 }
@@ -91,7 +101,7 @@ export class AccidentalCalculator {
     }
 
     private reactOnKeyInstructionChange(): void {
-        const noteEnums: NoteEnum[] = KeyInstruction.getNoteEnumList(this.activeKeyInstruction);
+        const noteEnums: NoteEnum[] = this.activeKeyInstruction.AlteratedNotes;
         let keyAccidentalType: AccidentalEnum;
         if (this.activeKeyInstruction.Key > 0) {
             keyAccidentalType = AccidentalEnum.SHARP;

+ 2 - 2
src/MusicalScore/Graphical/MusicSystemBuilder.ts

@@ -442,7 +442,7 @@ export class MusicSystemBuilder {
                 if (abstractNotationInstruction instanceof ClefInstruction) {
                     currentClef = <ClefInstruction>abstractNotationInstruction;
                 } else if (abstractNotationInstruction instanceof KeyInstruction) {
-                    currentKey = <KeyInstruction>abstractNotationInstruction;
+                    currentKey = KeyInstruction.copy(<KeyInstruction>abstractNotationInstruction);
                 } else if (abstractNotationInstruction instanceof RhythmInstruction) {
                     currentRhythm = <RhythmInstruction>abstractNotationInstruction;
                 }
@@ -453,7 +453,7 @@ export class MusicSystemBuilder {
                 currentClef = this.activeClefs[visibleStaffIdx];
             }
             if (currentKey === undefined) {
-                currentKey = this.activeKeys[visibleStaffIdx];
+                currentKey = KeyInstruction.copy(this.activeKeys[visibleStaffIdx]);
             }
             if (isFirstSourceMeasure && currentRhythm === undefined) {
                 currentRhythm = this.activeRhythm[visibleStaffIdx];

+ 22 - 12
src/MusicalScore/Graphical/VexFlow/VexFlowGraphicalNote.ts

@@ -7,6 +7,7 @@ import {Pitch} from "../../../Common/DataObjects/Pitch";
 import {Fraction} from "../../../Common/DataObjects/Fraction";
 import {OctaveEnum, OctaveShift} from "../../VoiceData/Expressions/ContinuousExpressions/OctaveShift";
 import { GraphicalVoiceEntry } from "../GraphicalVoiceEntry";
+import { KeyInstruction } from "../../VoiceData/Instructions/KeyInstruction";
 
 /**
  * The VexFlow version of a [[GraphicalNote]].
@@ -38,18 +39,27 @@ export class VexFlowGraphicalNote extends GraphicalNote {
      * This is called by VexFlowGraphicalSymbolFactory.addGraphicalAccidental.
      * @param pitch
      */
-    public setPitch(pitch: Pitch): void {
-        if (this.vfnote) {
-            const acc: string = Pitch.accidentalVexflow(pitch.Accidental);
-            if (acc) {
-                alert(acc);
-                this.vfnote[0].addAccidental(this.vfnote[1], new Vex.Flow.Accidental(acc));
-            }
-        } else {
-            // revert octave shift, as the placement of the note is independent of octave brackets
-            const drawPitch: Pitch = OctaveShift.getPitchFromOctaveShift(pitch, this.octaveShift);
-            this.vfpitch = VexFlowConverter.pitch(this, drawPitch);
-        }
+    public setAccidental(pitch: Pitch): void {
+        // if (this.vfnote) {
+        //     let pitchAcc: AccidentalEnum = pitch.Accidental;
+        //     const acc: string = Pitch.accidentalVexflow(pitch.Accidental);
+        //     if (acc) {
+        //         alert(acc);
+        //         this.vfnote[0].addAccidental(this.vfnote[1], new Vex.Flow.Accidental(acc));
+        //     }
+        // } else {
+        // revert octave shift, as the placement of the note is independent of octave brackets
+        const drawPitch: Pitch = OctaveShift.getPitchFromOctaveShift(pitch, this.octaveShift);
+        // recalculate the pitch, and this time don't ignore the accidental:
+        this.vfpitch = VexFlowConverter.pitch(this, drawPitch);
+        //}
+    }
+    public Transpose(keyInstruction: KeyInstruction, activeClef: ClefInstruction, halfTones: number, octaveEnum: OctaveEnum): Pitch {
+        const tranposedPitch: Pitch = super.Transpose(keyInstruction, activeClef, halfTones, octaveEnum);
+        const drawPitch: Pitch = OctaveShift.getPitchFromOctaveShift(tranposedPitch, this.octaveShift);
+        this.vfpitch = VexFlowConverter.pitch(this, drawPitch);
+        this.vfpitch[1] = undefined;
+        return drawPitch;
     }
 
     /**

+ 1 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowGraphicalSymbolFactory.ts

@@ -131,7 +131,7 @@ export class VexFlowGraphicalSymbolFactory implements IGraphicalSymbolFactory {
     public addGraphicalAccidental(graphicalNote: GraphicalNote, pitch: Pitch): void {
         const note: VexFlowGraphicalNote = (graphicalNote as VexFlowGraphicalNote);
         // accidental is added in setPitch
-        note.setPitch(pitch);
+        note.setAccidental(pitch);
     }
 
     /**

+ 0 - 1
src/MusicalScore/Interfaces/ITransposeCalculator.ts

@@ -4,5 +4,4 @@ import {KeyInstruction} from "../VoiceData/Instructions/KeyInstruction";
 export interface ITransposeCalculator {
     transposePitch(pitch: Pitch, currentKeyInstruction: KeyInstruction, halftones: number): Pitch;
     transposeKey(keyInstruction: KeyInstruction, transpose: number): void;
-    getTransposedKeyString(keyInstruction: KeyInstruction, halftone: number): string;
 }

+ 17 - 18
src/MusicalScore/VoiceData/Instructions/KeyInstruction.ts

@@ -12,6 +12,7 @@ export class KeyInstruction extends AbstractNotationInstruction {
         super(sourceStaffEntry);
         this.Key = key;
         this.mode = mode;
+        this.alteratedNotes = this.calcAlteratedNotes();
     }
 
     private static sharpPositionList: NoteEnum[] = [NoteEnum.F, NoteEnum.C, NoteEnum.G, NoteEnum.D, NoteEnum.A, NoteEnum.E, NoteEnum.B];
@@ -19,27 +20,13 @@ export class KeyInstruction extends AbstractNotationInstruction {
 
     private keyType: number;
     private mode: KeyEnum;
+    private alteratedNotes: NoteEnum[];
 
     public static copy(keyInstruction: KeyInstruction): KeyInstruction {
         const newKeyInstruction: KeyInstruction = new KeyInstruction(keyInstruction.parent, keyInstruction.Key, keyInstruction.Mode);
         return newKeyInstruction;
     }
 
-    public static getNoteEnumList(instruction: KeyInstruction): NoteEnum[] {
-        const enums: NoteEnum[] = [];
-        if (instruction.keyType > 0) {
-            for (let i: number = 0; i < instruction.keyType; i++) {
-                enums.push(KeyInstruction.sharpPositionList[i]);
-            }
-        }
-        if (instruction.keyType < 0) {
-            for (let i: number = 0; i < Math.abs(instruction.keyType); i++) {
-                enums.push(KeyInstruction.flatPositionList[i]);
-            }
-        }
-        return enums;
-    }
-
     public static getAllPossibleMajorKeyInstructions(): KeyInstruction[] {
         const keyInstructionList: KeyInstruction[] = [];
         for (let keyType: number = -7; keyType < 7; keyType++) {
@@ -55,6 +42,7 @@ export class KeyInstruction extends AbstractNotationInstruction {
 
     public set Key(value: number) {
         this.keyType = value;
+        this.alteratedNotes = this.calcAlteratedNotes();
     }
 
     public get Mode(): KeyEnum {
@@ -65,7 +53,11 @@ export class KeyInstruction extends AbstractNotationInstruction {
         this.mode = value;
     }
 
-    public getFundamentalNotesOfAccidentals(): NoteEnum[] {
+    public get AlteratedNotes(): NoteEnum[] {
+        return this.alteratedNotes;
+    }
+
+    private calcAlteratedNotes(): NoteEnum[] {
         const noteList: NoteEnum[] = [];
         if (this.keyType > 0) {
             for (let i: number = 0; i < this.keyType; i++) {
@@ -79,10 +71,17 @@ export class KeyInstruction extends AbstractNotationInstruction {
         return noteList;
     }
 
+    public willAlterateNote(note: NoteEnum): boolean {
+        if (this.alteratedNotes.indexOf(note) >= 0) {
+            return true;
+        }
+        return false;
+    }
+
     public getAlterationForPitch(pitch: Pitch): AccidentalEnum {
-        if (this.keyType > 0 && KeyInstruction.sharpPositionList.indexOf(pitch.FundamentalNote) <= this.keyType) {
+        if (this.keyType > 0 && this.alteratedNotes.indexOf(pitch.FundamentalNote) <= this.keyType) {
             return AccidentalEnum.SHARP;
-        } else if (this.keyType < 0 && KeyInstruction.flatPositionList.indexOf(pitch.FundamentalNote) <= Math.abs(this.keyType)) {
+        } else if (this.keyType < 0 && this.alteratedNotes.indexOf(pitch.FundamentalNote) <= Math.abs(this.keyType)) {
             return AccidentalEnum.FLAT;
         }
         return AccidentalEnum.NONE;

+ 9 - 1
src/OpenSheetMusicDisplay/OpenSheetMusicDisplay.ts

@@ -22,7 +22,7 @@ import { AutoColorSet, GraphicalMusicPage } from "../MusicalScore";
 import jspdf = require("jspdf-yworks/dist/jspdf.min");
 import svg2pdf = require("svg2pdf.js/dist/svg2pdf.min");
 import { MusicPartManagerIterator } from "../MusicalScore/MusicParts";
-
+import { ITransposeCalculator } from "../MusicalScore/Interfaces";
 /**
  * The main class and control point of OpenSheetMusicDisplay.<br>
  * It can display MusicXML sheet music files in an HTML element container.<br>
@@ -888,6 +888,14 @@ export class OpenSheetMusicDisplay {
         return this.followCursor;
     }
 
+    public set TransposeCalculator(calculator: ITransposeCalculator) {
+        MusicSheetCalculator.transposeCalculator = calculator;
+    }
+
+    public get TransposeCalculator(): ITransposeCalculator {
+        return MusicSheetCalculator.transposeCalculator;
+    }
+
     public get Sheet(): MusicSheet {
         return this.sheet;
     }