瀏覽代碼

Fixing VF notes' duration

Andrea Condoluci 9 年之前
父節點
當前提交
dd4505f415

+ 5 - 5
external/vexflow/vexflow.d.ts

@@ -7,8 +7,8 @@ declare namespace Vex {
 
       public hasMinTotalWidth: boolean;
       public minTotalWidth: number;
-      public joinVoices(voices: Vex.Flow.Voice[]): void;
-
+      public joinVoices(voices: Voice[]): void;
+      public format(voices: Voice[], width: number): void;
       public preCalculateMinTotalWidth(voices: Voice[]): number;
     }
 
@@ -63,7 +63,7 @@ declare namespace Vex {
       public getSpacingBetweenLines(): number;
       public getNumLines(): number;
       public getLineForY(y: number): number;
-      public getModifiers(pos: any, cat: any): Vex.Flow.Clef[]; // FIXME
+      public getModifiers(pos: any, cat: any): Clef[]; // FIXME
       public setContext(ctx: any): Stave;
       public addModifier(mod: any, pos: any): void;
       public draw(): void;
@@ -88,8 +88,8 @@ declare namespace Vex {
       public x: number;
       public stave: Stave;
 
-      public getBoundingBox(): Vex.Flow.BoundingBox;
-      public setStave(stave: Vex.Flow.Stave): void;
+      public getBoundingBox(): BoundingBox;
+      public setStave(stave: Stave): void;
     }
 
     export class Renderer {

+ 1 - 0
src/MusicalScore/Graphical/MusicSheetDrawer.ts

@@ -4,6 +4,7 @@ import {StaffLine} from "./StaffLine";
 import {RectangleF2D} from "../../Common/DataObjects/RectangleF2D";
 import {MusicSystem} from "./MusicSystem";
 import {GraphicalMusicPage} from "./GraphicalMusicPage";
+import {VexFlowMeasure} from "./VexFlow/VexFlowMeasure";
 
 export class MusicSheetDrawer {
     private graphicalMusicSheet: GraphicalMusicSheet;

+ 40 - 14
src/MusicalScore/Graphical/VexFlow/VexFlowConverter.ts

@@ -11,6 +11,9 @@ import {AccidentalEnum} from "../../../Common/DataObjects/pitch";
 import {NoteEnum} from "../../../Common/DataObjects/pitch";
 
 import Vex = require("vexflow");
+import Clef = Vex.Flow.Clef;
+import {VexFlowGraphicalNote} from "./VexFlowGraphicalNote";
+import {GraphicalNote} from "../GraphicalNote";
 
 export class VexFlowConverter {
     private static majorMap: {[_: number]: string; } = {
@@ -23,8 +26,22 @@ export class VexFlowConverter {
     };
 
     public static duration(fraction: Fraction): string {
-        // FIXME TODO
-        return "q";
+        let dur: number = fraction.RealValue;
+        switch (dur) {
+            case 0.25:
+                return "q";
+            case 0.5:
+                return "h";
+            case 1:
+                return "w";
+            case 0.125:
+                return "8";
+            case 0.0625:
+                return "16";
+            // FIXME TODO
+            default:
+                return "16";
+        }
     }
 
     /**
@@ -33,12 +50,9 @@ export class VexFlowConverter {
      * @param pitch
      * @returns {string[]}
      */
-    public static pitch(pitch: Pitch): [string, string] {
-        if (pitch.FundamentalNote === undefined) {
-            return ["", ""];
-        }
+    public static pitch(pitch: Pitch, octaveOffset: number): [string, string] {
         let fund: string = NoteEnum[pitch.FundamentalNote].toLowerCase();
-        let octave: number = pitch.Octave;
+        let octave: number = pitch.Octave + octaveOffset;
         let acc: string = "";
 
         switch (pitch.Accidental) {
@@ -61,12 +75,18 @@ export class VexFlowConverter {
         return [fund + acc + "/" + octave, acc];
     }
 
-    public static StaveNote(voiceEntry: VoiceEntry): Vex.Flow.StaveNote {
+    public static StaveNote(notes: GraphicalNote[], octaveOffset: number): Vex.Flow.StaveNote {
         let keys: string[] = [];
-        let duration: string = VexFlowConverter.duration(voiceEntry.Notes[0].Length);
+        let duration: string = VexFlowConverter.duration(notes[0].sourceNote.Length);
         let accidentals: string[] = [];
-        for (let note of voiceEntry.Notes) {
-            let res: [string, string] = VexFlowConverter.pitch(note.Pitch);
+        for (let note of notes) {
+            let res: [string, string] = (note as VexFlowGraphicalNote).vfpitch;
+            if (res === undefined) {
+                keys = ["b/4"];
+                accidentals = [];
+                duration += "r";
+                break;
+            }
             keys.push(res[0]);
             accidentals.push(res[1]);
         }
@@ -127,14 +147,20 @@ export class VexFlowConverter {
         if (key === undefined) {
             return undefined;
         }
+        let ret: string;
         switch (key.Mode) {
             case KeyEnum.none:
-                return undefined;
+                ret = undefined;
+                break;
             case KeyEnum.minor:
-                return VexFlowConverter.minorMap[key.Key];
+                ret = VexFlowConverter.minorMap[key.Key] + "m";
+                break;
             case KeyEnum.major:
-                return VexFlowConverter.majorMap[key.Key] + "m";
+                ret = VexFlowConverter.majorMap[key.Key];
+                break;
             default:
         }
+        //console.log("keySignature", key, ret);
+        return ret;
     }
 }

+ 10 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowGraphicalNote.ts

@@ -1,9 +1,18 @@
 import {GraphicalNote} from "../GraphicalNote";
 import {Note} from "../../VoiceData/Note";
 import {GraphicalStaffEntry} from "../GraphicalStaffEntry";
+import {ClefInstruction} from "../../VoiceData/Instructions/ClefInstruction";
+import {VexFlowConverter} from "./VexFlowConverter";
 
 export class VexFlowGraphicalNote extends GraphicalNote {
-    constructor(note: Note, parent: GraphicalStaffEntry) {
+    constructor(note: Note, parent: GraphicalStaffEntry, activeClef: ClefInstruction) {
         super(note, parent);
+        if (note.Pitch) {
+            this.vfpitch = VexFlowConverter.pitch(note.Pitch, activeClef.OctaveOffset);
+        } else {
+            this.vfpitch = undefined;
+        }
     }
+
+    public vfpitch: [string, string];
 }

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

@@ -17,6 +17,7 @@ import {OctaveEnum} from "../../VoiceData/Expressions/ContinuousExpressions/octa
 import {GraphicalNote} from "../GraphicalNote";
 import {Pitch} from "../../../Common/DataObjects/pitch";
 import {TechnicalInstruction} from "../../VoiceData/Instructions/TechnicalInstruction";
+import {VexFlowGraphicalNote} from "./VexFlowGraphicalNote";
 
 export class VexFlowGraphicalSymbolFactory implements IGraphicalSymbolFactory {
     /**
@@ -94,8 +95,7 @@ export class VexFlowGraphicalSymbolFactory implements IGraphicalSymbolFactory {
      */
     public createNote(note: Note, numberOfDots: number, graphicalStaffEntry: GraphicalStaffEntry,
                       activeClef: ClefInstruction, octaveShift: OctaveEnum = OctaveEnum.NONE): GraphicalNote {
-        let gn: GraphicalNote = new GraphicalNote(note, graphicalStaffEntry);
-        return gn;
+        return new VexFlowGraphicalNote(note, graphicalStaffEntry, activeClef);
     }
 
     /**

+ 10 - 3
src/MusicalScore/Graphical/VexFlow/VexFlowMeasure.ts

@@ -21,7 +21,9 @@ export class VexFlowMeasure extends StaffMeasure {
         //this.duration = this.parentSourceMeasure.Duration;
     }
 
+    public octaveOffset: number = 3; // FIXME
     public voices: { [voiceID: number]: Vex.Flow.Voice; };
+    public formatVoices: (width: number) => void;
     private stave: Vex.Flow.Stave;
     //private duration: Fraction;
 
@@ -67,6 +69,7 @@ export class VexFlowMeasure extends StaffMeasure {
      * @param clef
      */
     public addClefAtBegin(clef: ClefInstruction): void {
+        this.octaveOffset = clef.OctaveOffset;
         let vfclef: string = VexFlowConverter.Clef(clef);
         this.stave.addClef(vfclef, undefined, undefined, Vex.Flow.Modifier.Position.BEGIN);
         this.increaseBeginInstructionWidth();
@@ -132,7 +135,13 @@ export class VexFlowMeasure extends StaffMeasure {
         // modifiers like clefs. In PS, width is the total width of the stave.
         // @Andrea: The following could be improved by storing the values in this object.
         //          Now it calls .format() implicitly.
-        this.stave.setWidth(width - this.beginInstructionsWidth - this.endInstructionsWidth);
+        //
+        console.log("stave size", width, width - this.beginInstructionsWidth - this.endInstructionsWidth);
+        this.stave.setWidth(Math.floor(width));
+        if (this.formatVoices) {
+            this.formatVoices(width - this.beginInstructionsWidth - this.endInstructionsWidth);
+            this.formatVoices = undefined;
+        }
     }
 
     /**
@@ -141,8 +150,6 @@ export class VexFlowMeasure extends StaffMeasure {
      * (multiply the minimal positions with the scaling factor, considering the BeginInstructionsWidth)
      */
     public layoutSymbols(): void {
-        // This is already done in the MusicSystemBuilder!
-        //this.setWidth(this.minimumStaffEntriesWidth * this.staffEntriesScaleFactor);
         this.stave.format();
     }
 

+ 4 - 0
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetCalculator.ts

@@ -81,7 +81,11 @@ export class VexFlowMusicSheetCalculator extends MusicSheetCalculator {
         let width: number = formatter.preCalculateMinTotalWidth(allVoices);
         for (let measure of measures) {
             measure.minimumStaffEntriesWidth = width;
+            (measure as VexFlowMeasure).formatVoices = undefined;
         }
+        (measures[0] as VexFlowMeasure).formatVoices = (w: number) => {
+            formatter.format(allVoices, w);
+        };
         return width;
     }
 

+ 8 - 1
src/MusicalScore/Graphical/VexFlow/VexFlowMusicSheetDrawer.ts

@@ -2,6 +2,7 @@ import {MusicSheetDrawer} from "../MusicSheetDrawer";
 import {RectangleF2D} from "../../../Common/DataObjects/RectangleF2D";
 import {StaffMeasure} from "../StaffMeasure";
 import {VexFlowMeasure} from "./VexFlowMeasure";
+import {GraphicalMusicSheet} from "../GraphicalMusicSheet";
 /**
  * Created by Matthias on 22.06.2016.
  */
@@ -9,13 +10,19 @@ export class VexFlowMusicSheetDrawer extends MusicSheetDrawer {
     constructor() {
         super();
     }
+    public drawSheet(graphicalMusicSheet: GraphicalMusicSheet): void {
+        let h1: Element = document.createElement("h1");
+        h1.textContent = "VexFlowMusicSheetDrawer Output";
+        document.body.appendChild(h1);
+        super.drawSheet(graphicalMusicSheet);
+    }
 
     protected drawMeasure(measure: StaffMeasure): void {
         //let vfMeasure: VexFlowMeasure = <VexFlowMeasure> measure;
         //throw new Error("not implemented");
         let canvas: HTMLCanvasElement = document.createElement("canvas");
         document.body.appendChild(canvas);
-        canvas.width = canvas.height = 100;
+        canvas.width = canvas.height = 200;
         return (measure as VexFlowMeasure).draw(canvas);
     }
 

+ 6 - 4
src/MusicalScore/Graphical/VexFlow/VexFlowStaffEntry.ts

@@ -9,12 +9,14 @@ export class VexFlowStaffEntry extends GraphicalStaffEntry {
 
         // Generate Vex.Flow.StaveNotes
         let vfnotes: { [id: number]: Vex.Flow.StaveNote; } = {};
-        for (let voiceEntry of this.sourceStaffEntry.VoiceEntries) {
-            console.log("NEVER HERE!");
-            vfnotes[voiceEntry.ParentVoice.VoiceId] = VexFlowConverter.StaveNote(voiceEntry);
+        for (let note of this.notes) {
+            vfnotes[note[0].sourceNote.ParentVoiceEntry.ParentVoice.VoiceId] = VexFlowConverter.StaveNote(
+                note,
+                (this.parentMeasure as VexFlowMeasure).octaveOffset
+            );
         }
         this.vfnotes = vfnotes;
-        console.log("vfnotes generated", vfnotes, "==>", this.sourceStaffEntry.VoiceEntries);
+        console.log("vfnotes generated", vfnotes);
     }
 
     public vfnotes: { [id: number]: Vex.Flow.StaveNote; };