UNPKG

webdaw-modules

Version:

a set of modules for building a web-based DAW

139 lines (129 loc) 4.36 kB
import { MusicSystem } from "opensheetmusicdisplay"; import { GraphicalNoteData } from "./getGraphicalNotesPerMeasure"; import { MIDINoteGeneric } from "../createNotes"; import { RepeatData } from "../musicxml/parser"; /* This method maps the notes in the SVG document of the score to MIDI notes in the sequencer */ type NoteMappingMIDIToGraphical = { [index: string]: { // vfnote: Vex.Flow.Note; element: SVGElement; musicSystem: MusicSystem; }; }; type NoteMappingGraphicalToMIDI = { [index: string]: MIDINoteGeneric; }; export const mapMIDINoteIdToGraphicalNotePerTrack = ( graphicalNotesPerBarPerTrack: GraphicalNoteData[][][], repeats: RepeatData[], notes: MIDINoteGeneric[] ): { score: number; midiToGraphical: NoteMappingMIDIToGraphical; graphicalToMidi: NoteMappingGraphicalToMIDI; }[] => { const notesPerTrack: { [id: string]: MIDINoteGeneric[] } = {}; const trackIds: string[] = []; notes.forEach(note => { const trackId = note.noteOn.trackId; if (trackId !== undefined) { if (typeof notesPerTrack[trackId] === "undefined") { notesPerTrack[trackId] = []; trackIds.push(trackId); } notesPerTrack[trackId].push(note); } }); const tmp: MIDINoteGeneric[][] = []; trackIds.forEach(id => { tmp.push(notesPerTrack[id]); }); // console.log(tmp); // console.log(graphicalNotesPerBarPerTrack); const numMIDITracks = tmp.length; const numGraphicalTracks = graphicalNotesPerBarPerTrack.length; const mappings = []; // console.log(numMIDITracks, numGraphicalTracks); for (let i = 0; i < numGraphicalTracks; i++) { for (let j = 0; j < numMIDITracks; j++) { mappings.push(getMappingPerTrack(graphicalNotesPerBarPerTrack[i], tmp[j], repeats)); } } mappings.sort((a, b) => b.score - a.score); // console.log(mappings); return mappings; }; const getMappingPerTrack = ( graphicalNotes: GraphicalNoteData[][], midiNotes: MIDINoteGeneric[], repeats: RepeatData[] ): { midiToGraphical: NoteMappingMIDIToGraphical; graphicalToMidi: NoteMappingGraphicalToMIDI; score: number; } => { let barIndex = -1; let barOffset = 1; let repeatIndex = 0; let numMatch = 0; const hasRepeated: { [index: number]: boolean } = {}; const numBars = graphicalNotes.length; // const numNotes = graphicalNotes.reduce((acc, val) => { // acc += val.length; // return acc; // }, 0); const numNotes = midiNotes.length; // console.log(numNotes); const midiToGraphical: NoteMappingMIDIToGraphical = {}; const graphicalToMidi: NoteMappingGraphicalToMIDI = {}; // console.log(graphicalNotes); while (true) { barIndex++; // console.log(barIndex, repeatIndex, hasRepeated[repeatIndex], repeats[repeatIndex][1]); if (repeats.length && barIndex === repeats[repeatIndex].end) { if (hasRepeated[repeatIndex] !== true) { barIndex = repeats[repeatIndex].start - 1; // console.log('REPEAT START', barIndex) hasRepeated[repeatIndex] = true; barOffset += repeats[repeatIndex].end - repeats[repeatIndex].start + 1; // ticksOffset += (repeats[repeatIndex][1] - repeats[repeatIndex][0]) * song.numerator * ppq; } else { // console.log('REPEAT END', barIndex, repeatIndex); repeatIndex++; if (repeatIndex === repeats.length || barIndex === numBars) { break; } } } else { // console.log("CONTINUE", barIndex, numBars, repeats); if (barIndex === numBars) { break; } } try { const filteredMidi = midiNotes.filter(e => e.noteOn.bar === barIndex + barOffset); graphicalNotes[barIndex].forEach(bd => { const { element, noteNumber, bar, parentMusicSystem } = bd; for (let j = 0; j < filteredMidi.length; j++) { const note = filteredMidi[j]; if (!midiToGraphical[note.id] && note.noteOn.bar == bar + barOffset - 1 && note.noteOn.noteNumber == noteNumber) { numMatch += 1; midiToGraphical[note.id] = { element, musicSystem: parentMusicSystem }; graphicalToMidi[element.id] = note; // filtered.splice(j, 1); break; } } }); } catch (e) { break; } } return { midiToGraphical, graphicalToMidi, score: numMatch / numNotes, }; };