UNPKG

webdaw-modules

Version:

a set of modules for building a web-based DAW

232 lines (214 loc) 5.76 kB
import { OpenSheetMusicDisplay, GraphicalMeasure, GraphicalStaffEntry, GraphicalVoiceEntry, GraphicalNote, VerticalGraphicalStaffEntryContainer, } from "opensheetmusicdisplay"; import uniqid from "uniqid"; export type MusicSystemData = { index: number; x: number; y: number; height: number; width: number; }; export type MeasureData = { index: number; x: number; y: number; height: number; width: number; }; export type NoteData = { id: string; index: number; x: number; y: number; width: number; height: number; center: { x: number; y: number }; ticks: number; noteNumber: number; isRestFlag: boolean; isGraceNote: boolean; noteLength: { numerator: number; denominator: number; wholeValue: number; realValue: number }; measureIndex: number; staffIndex: number; containerIndex: number; multipleRestMeasures: number; }; export type StaveData = { index: number; timeStamp: { numerator: number; denominator: number; wholeValue: number; realValue: number; }; ticks: number; x: number; y: number; width: number; height: number; notes: NoteData[]; containerIndex: number; measureIndex: number; }; export type OSMDEntityData = { measureIndex: number; containerIndex: number; startX: number; // smallest x-position of all notes in this container notes: NoteData[]; // staves: StaveData[]; musicSystem: MusicSystemData; }; const ppq = 960; const getMusicSystemData = ( entryContainer: VerticalGraphicalStaffEntryContainer ): MusicSystemData => { // console.log(entryContainer); let staffEntry = (entryContainer as any).staffEntries[0]; let i = 1; while (typeof staffEntry === "undefined" && i < (entryContainer as any).staffEntries.length) { staffEntry = (entryContainer as any).staffEntries[i]; i++; } const { boundingBox: { absolutePosition: { x, y }, size: { width, height }, borderTop, borderBottom, }, id, } = (staffEntry.parentMeasure as any).parentMusicSystem as any; return { index: id, x, y, width, height, }; }; const getMeasureData = (entryContainer: VerticalGraphicalStaffEntryContainer): MeasureData[] => { const measureData: MeasureData[] = []; (entryContainer as any).staffEntries.forEach((staffEntry: GraphicalStaffEntry) => { const { boundingBox: { absolutePosition: { x, y }, size: { width, height }, borderTop, borderBottom, }, measureNumber, } = staffEntry.parentMeasure as any; measureData.push({ index: measureNumber, x: x * 10, y: y * 10, width: width * 10, height: (y + borderBottom - (y - borderTop)) * 10, }); }); return measureData; }; const getNoteData = ({ note, noteIndex, staffIndex, containerIndex, measureIndex, }: { note: GraphicalNote; noteIndex: number; staffIndex: number; containerIndex: number; measureIndex: number; }): NoteData => { const { boundingBox: { absolutePosition: { x, y }, size: { width, height }, borderLeft, }, sourceNote, } = note as any; const { numerator, denominator, wholeValue, realValue } = note.graphicalNoteLength as any; const relPosInMeasure = (note.sourceNote as any).voiceEntry.timestamp.realValue; const { sourceMeasure: { multipleRestMeasures }, } = sourceNote; const data: NoteData = { id: `note-${uniqid()}`, index: noteIndex, center: { x: x * 10, y: 0 }, x: (x + borderLeft) * 10, y: y * 10, width: width * 10, height: height * 10, ticks: measureIndex * ppq * 4 + relPosInMeasure * ppq * 4, noteNumber: sourceNote.halfTone + 12, isRestFlag: sourceNote.isRestFlag === true, isGraceNote: sourceNote.IsGraceNote === true, noteLength: { numerator, denominator, wholeValue, realValue }, staffIndex, measureIndex, multipleRestMeasures: multipleRestMeasures || 0, containerIndex, }; return data; }; const getStaveData = ( entryContainer: VerticalGraphicalStaffEntryContainer, containerIndex: number ): StaveData[] => { const staveData = (entryContainer as any).staffEntries.map( (staffEntry: GraphicalStaffEntry, staffIndex: number) => { const { boundingBox: { absolutePosition: { x, y }, size: { width, height }, borderTop, borderBottom, borderLeft, borderMarginTop, borderMarginLeft, }, } = staffEntry as any; const notes: NoteData[] = []; let measureIndex = -1; staffEntry.graphicalVoiceEntries.forEach(voiceEntry => { measureIndex = (voiceEntry.parentStaffEntry.parentMeasure as any).measureNumber; voiceEntry.notes.forEach((note: GraphicalNote, noteIndex: number) => { const n = getNoteData({ note, noteIndex, staffIndex, containerIndex, measureIndex }); notes.push(n); }); }); return { notes, index: staffIndex, measureIndex, containerIndex, // x: (x + borderLeft - borderMarginLeft) * 10, // y: (y + borderTop - borderMarginTop) * 10, x: (x + borderLeft) * 10, y: (y + borderTop) * 10, width: width * 10, height: height * 10, }; } ); return staveData; }; export const getEntities = (osmd: OpenSheetMusicDisplay, ppq: number = 960): StaveData[][] => { const staveData: StaveData[][] = []; osmd.GraphicSheet.VerticalGraphicalStaffEntryContainers.forEach( (entryContainer: VerticalGraphicalStaffEntryContainer, containerIndex: number) => { const s = getStaveData(entryContainer, containerIndex); staveData.push(s); } ); return staveData; };