UNPKG

webdaw-modules

Version:

a set of modules for building a web-based DAW

147 lines (138 loc) 4.96 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[]; }; type GraphicalNoteData = { // vfnote: Vex.Flow.Note; element: SVGElement; ticks: number; noteNumber: number; bar: number; parentMusicSystem: MusicSystem; }; interface VexFlowStaveNote extends Vex.Flow.StaveNote { attrs: { el: SVGElement; }; } export const getGraphicalNotesPerMeasurePerTrack = ( osmd: OpenSheetMusicDisplay, ppq: number ): GraphicalNoteData[][][] => { const tracks: any[] = []; osmd.GraphicSheet.MeasureList.forEach((measure, measureNumber) => { // console.log(measure); // const [staves] = measure; measure.forEach((staff, staffNo) => { // console.log(staff); if (typeof tracks[staffNo] === "undefined") { tracks[staffNo] = []; } if (typeof tracks[staffNo][measureNumber] === "undefined") { tracks[staffNo][measureNumber] = []; } const parentMusicSystem = staff["parentMusicSystem"]; // private prop so we need to trick typescript const staffEntries = staff.staffEntries; staffEntries.forEach(entry => { // console.log(entry); entry.graphicalVoiceEntries.forEach(ve => { ve.notes.forEach(note => { // console.log(note); if (note.sourceNote.halfTone > 0) { const relPosInMeasure = note.sourceNote["voiceEntry"].timestamp.realValue; const vfnote = (note as VexFlowGraphicalNote).vfnote[0]; // console.log(vfnote, relPosInMeasure); tracks[staffNo][measureNumber].push({ element: (vfnote as VexFlowStaveNote).attrs.el, ticks: measureNumber * ppq * 4 + relPosInMeasure * ppq * 4, noteNumber: note.sourceNote.halfTone + 12, // heartbeat uses a different MIDI note number mapping bar: measureNumber + 1, parentMusicSystem, // necessary to get the y-position if the note in the score }); } }); }); }); }); }); /* tracks.forEach(track => { track.forEach((measure: GraphicalNoteData[][]) => { // console.log(measure); // measure.sort((a, b) => { // if (a.ticks < b.ticks) { // return -1; // } else if (a.ticks > b.ticks) { // return 1; // } // return 0; // }); }); }); */ // console.log(tracks); return tracks; }; 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();