UNPKG

webdaw-modules

Version:

a set of modules for building a web-based DAW

243 lines (225 loc) 7.06 kB
import { OpenSheetMusicDisplay, GraphicalMeasure, GraphicalStaffEntry, GraphicalVoiceEntry, GraphicalNote, VerticalGraphicalStaffEntryContainer, } from "opensheetmusicdisplay"; export type MusicSystemData = { index: number; x: number; y: number; }; export type NoteData = { index: number; x: number; y: number; width: number; height: number; center: { x: number; y: number }; ticks: number; noteNumber: number; isRestFlag: boolean; noteLength: { numerator: number; denominator: number; wholeValue: number; realValue: number }; measureIndex: number; staffIndex: number; }; export type StaveData = { index: number; measureIndex: number; timestamp: { numerator: number; denominator: number; wholeValue: number; realValue: number; }; ticks: number; x: number; y: number; width: number; height: number; notes: NoteData[]; }; 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 = (entryContainer: VerticalGraphicalStaffEntryContainer): NoteData[] => { const notes: NoteData[] = []; (entryContainer as any).staffEntries.forEach( (staffEntry: GraphicalStaffEntry, staffIndex: number) => { staffEntry.graphicalVoiceEntries.forEach(voiceEntry => { const measureIndex = (voiceEntry.parentStaffEntry.parentMeasure as any).measureNumber; voiceEntry.notes.forEach((note: GraphicalNote) => { const { boundingBox: { absolutePosition: { x, y }, borderLeft, }, sourceNote, } = note as any; const { numerator, denominator, wholeValue, realValue } = note.graphicalNoteLength as any; const relPosInMeasure = (note.sourceNote as any).voiceEntry.timestamp.realValue; const data: NoteData = { center: { x: x * 10, y: 0 }, x: (x + borderLeft) * 10, y: y * 10, ticks: measureIndex * ppq * 4 + relPosInMeasure * ppq * 4, noteNumber: sourceNote.halfTone + 12, isRestFlag: sourceNote.isRestFlag, noteLength: { numerator, denominator, wholeValue, realValue }, }; notes.push(data); }); }); } ); return notes; }; const getStaveData = (measure: GraphicalMeasure, measureIndex: number): StaveData[] => { const staveData = measure.staffEntries.map( (staffEntry: GraphicalStaffEntry, staffIndex: number) => { const { boundingBox: { absolutePosition: { x, y }, size: { width, height }, borderTop, borderBottom, borderLeft, }, } = staffEntry as any; const notes: NoteData[] = []; staffEntry.graphicalVoiceEntries.forEach(voiceEntry => { voiceEntry.notes.forEach((note: GraphicalNote, noteIndex: number) => { 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 data: NoteData = { 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, noteLength: { numerator, denominator, wholeValue, realValue }, staffIndex, measureIndex, }; notes.push(data); }); }); const timestamp = staffEntry.relInMeasureTimestamp; const ticks = measureIndex * ppq * 4 + timestamp.RealValue * ppq * 4; return { notes, index: staffIndex, ticks, timestamp: { numerator: timestamp.Numerator, denominator: timestamp.Denominator, realValue: timestamp.RealValue, wholeValue: timestamp.WholeValue, }, measureIndex, x: (x + borderLeft) * 10, y: (y + borderTop) * 10, width: width * 10, height: height * 10, } as StaveData; } ); return staveData; }; const getData = (entryContainer: VerticalGraphicalStaffEntryContainer, containerIndex: number) => { return { containerIndex, notes: getNoteData(entryContainer), measures: getMeasureData(entryContainer), staves: getStaveData(entryContainer), musicSystem: getMusicSystemData(entryContainer), }; }; export const getEntries = (osmd: OpenSheetMusicDisplay, ppq: number = 960): OSMDEntityData[] => { const entityData: OSMDEntityData[] = []; osmd.GraphicSheet.VerticalGraphicalStaffEntryContainers.forEach( (entryContainer: VerticalGraphicalStaffEntryContainer, containerIndex: number) => { entityData.push(getData(entryContainer, containerIndex)); } ); return entityData; }; export const firstTest = (osmd: OpenSheetMusicDisplay, ppq: number = 960): StaveData[][] => { const entries: StaveData[][] = []; osmd.GraphicSheet.MeasureList.forEach((staves: GraphicalMeasure[], measureIndex: number) => { staves.forEach(staff => { const s = getStaveData(staff, measureIndex); entries.push(s); }); }); return entries; };