UNPKG

webdaw-modules

Version:

a set of modules for building a web-based DAW

88 lines (80 loc) 2.89 kB
/* This method parses the SVG document as rendered by OSMD and stores the graphical representations of the notes in an array; notes are stored per measure (bar) in a sub-array so we end up with an array the size of the number of bars, containing an array that contain the notes in that bar. I use the following paths: - openSheetMusicDisplay.GraphicSheet.MeasureList[0][0].staffEntries[0].graphicalVoiceEntries[0].notes[0]; - openSheetMusicDisplay.GraphicSheet.MeasureList[0][0].parentMusicSystem More info: https://github.com/opensheetmusicdisplay/opensheetmusicdisplay/issues/549 */ import { from } from "rxjs"; import { map, reduce, tap } from "rxjs/operators"; import { OpenSheetMusicDisplay, GraphicalStaffEntry, GraphicalNote, VexFlowGraphicalNote, MusicSystem, } from "opensheetmusicdisplay"; type TypeStave = { staffEntries: GraphicalStaffEntry[]; }; export type GraphicalNoteData = { // vfnote: Vex.Flow.Note; element: SVGElement; ticks: number; noteNumber: number; bar: number; parentMusicSystem: MusicSystem; }; export interface VexFlowStaveNote extends Vex.Flow.StaveNote { attrs: { el: SVGElement; }; } export const getGraphicalNotesPerMeasure = ( osmd: OpenSheetMusicDisplay, ppq: number ): Promise<GraphicalNoteData[][]> => // from(osmd["graphic"].measureList) from(osmd.GraphicSheet.MeasureList) .pipe( // tap(m => { console.log(m); }), map((staves: any, i) => { return staves.map((s: TypeStave) => { const parentMusicSystem = staves[0].parentMusicSystem; return s.staffEntries.map(se => { return se.graphicalVoiceEntries.map(ve => { // return ve.notes; return ve.notes.map((n: GraphicalNote) => { const relPosInMeasure = n.sourceNote["voiceEntry"].timestamp.realValue; // const relPosInMeasure = n.sourceNote.voiceEntry.timestamp.realValue; const vfnote = (n as VexFlowGraphicalNote).vfnote[0]; return { element: (vfnote as VexFlowStaveNote).attrs.el, ticks: i * ppq * 4 + relPosInMeasure * ppq * 4, noteNumber: n.sourceNote.halfTone + 12, // heartbeat uses a different MIDI note number mapping bar: i + 1, parentMusicSystem, // necessary to get the y-position if the note in the score }; }); }); }); }); }), // tap(console.log), reduce((acc: any[], val) => { const flat: GraphicalNoteData[] = val.flat(3); flat.sort((a, b) => { if (a.ticks < b.ticks) { return -1; } else if (a.ticks > b.ticks) { return 1; } return 0; }); acc.push(flat); return acc; }, []) ) .toPromise();