musicxml-io 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/accessors/index.d.mts +280 -2
- package/dist/accessors/index.d.ts +280 -2
- package/dist/accessors/index.js +1299 -1
- package/dist/accessors/index.mjs +1251 -1
- package/dist/index-DCty0U8p.d.ts +377 -0
- package/dist/index-nCaclfqu.d.mts +377 -0
- package/dist/index.d.mts +6 -184
- package/dist/index.d.ts +6 -184
- package/dist/index.js +2087 -309
- package/dist/index.mjs +2039 -308
- package/dist/operations/index.d.mts +2 -92
- package/dist/operations/index.d.ts +2 -92
- package/dist/operations/index.js +1580 -150
- package/dist/operations/index.mjs +1562 -148
- package/dist/query/index.d.mts +1 -1
- package/dist/query/index.d.ts +1 -1
- package/dist/query/index.js +0 -1
- package/dist/query/index.mjs +0 -1
- package/dist/{types-DC_TnJu_.d.ts → types-Dp9zcgIg.d.mts} +298 -3
- package/dist/{types-DC_TnJu_.d.mts → types-Dp9zcgIg.d.ts} +298 -3
- package/package.json +6 -2
- package/dist/accessors/index.js.map +0 -1
- package/dist/accessors/index.mjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/operations/index.js.map +0 -1
- package/dist/operations/index.mjs.map +0 -1
- package/dist/query/index.js.map +0 -1
- package/dist/query/index.mjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/operations/index.ts","../../src/utils/index.ts"],"sourcesContent":["import type {\n Score,\n Measure,\n NoteEntry,\n Pitch,\n KeySignature,\n TimeSignature,\n} from '../types';\nimport { STEPS, STEP_SEMITONES, getMeasureEndPosition } from '../utils';\n\n/**\n * Deep clone a score\n */\nfunction cloneScore(score: Score): Score {\n return JSON.parse(JSON.stringify(score));\n}\n\n/**\n * Transpose a pitch by a number of semitones\n */\nfunction transposePitch(pitch: Pitch, semitones: number): Pitch {\n const currentSemitone = STEP_SEMITONES[pitch.step] + (pitch.alter ?? 0) + pitch.octave * 12;\n const targetSemitone = currentSemitone + semitones;\n\n const targetOctave = Math.floor(targetSemitone / 12);\n const targetPitchClass = ((targetSemitone % 12) + 12) % 12;\n\n // Find the closest natural step with smallest alteration\n let bestStep: Pitch['step'] = 'C';\n let bestAlter = 99; // Start with large value so any real alter is smaller\n\n for (const step of STEPS) {\n const stepSemitone = STEP_SEMITONES[step];\n // Calculate the alteration needed to reach target from this step\n let diff = targetPitchClass - stepSemitone;\n\n // Normalize to range -6 to +6 for smallest alteration\n if (diff > 6) diff -= 12;\n if (diff < -6) diff += 12;\n\n // Only consider alterations within -2 to +2 (double flat to double sharp)\n if (diff >= -2 && diff <= 2) {\n if (Math.abs(diff) < Math.abs(bestAlter)) {\n bestStep = step;\n bestAlter = diff;\n }\n }\n }\n\n return {\n step: bestStep,\n octave: targetOctave,\n alter: bestAlter !== 0 ? bestAlter : undefined,\n };\n}\n\n/**\n * Transpose all notes in a score by a number of semitones\n */\nexport function transpose(score: Score, semitones: number): Score {\n if (semitones === 0) return score;\n\n const result = cloneScore(score);\n\n for (const part of result.parts) {\n for (const measure of part.measures) {\n for (const entry of measure.entries) {\n if (entry.type === 'note' && entry.pitch) {\n entry.pitch = transposePitch(entry.pitch, semitones);\n }\n }\n }\n }\n\n return result;\n}\n\n/**\n * Options for adding a note\n */\nexport interface AddNoteOptions {\n partIndex: number;\n measureIndex: number;\n staff?: number;\n voice: number;\n position: number;\n note: Omit<NoteEntry, 'type' | 'voice' | 'staff'>;\n}\n\n/**\n * Add a note to a measure\n * Automatically handles backup/forward insertion\n */\nexport function addNote(score: Score, options: AddNoteOptions): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n const newNote: NoteEntry = {\n type: 'note',\n voice: options.voice,\n staff: options.staff,\n ...options.note,\n };\n\n // Find the current position at the end of the measure using shared utility\n const currentPosition = getMeasureEndPosition(measure);\n\n // Calculate backup/forward needed\n const positionDiff = options.position - currentPosition;\n\n if (positionDiff < 0) {\n // Need to backup\n measure.entries.push({\n type: 'backup',\n duration: -positionDiff,\n });\n } else if (positionDiff > 0) {\n // Need to forward\n measure.entries.push({\n type: 'forward',\n duration: positionDiff,\n voice: options.voice,\n staff: options.staff,\n });\n }\n\n measure.entries.push(newNote);\n\n return result;\n}\n\n/**\n * Delete a note from a measure\n */\nexport function deleteNote(score: Score, options: {\n partIndex: number;\n measureIndex: number;\n noteIndex: number;\n}): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n // Find the note by counting only notes\n let noteCount = 0;\n let entryIndex = -1;\n\n for (let i = 0; i < measure.entries.length; i++) {\n if (measure.entries[i].type === 'note') {\n if (noteCount === options.noteIndex) {\n entryIndex = i;\n break;\n }\n noteCount++;\n }\n }\n\n if (entryIndex !== -1) {\n measure.entries.splice(entryIndex, 1);\n }\n\n return result;\n}\n\n/**\n * Change key signature from a specific measure\n */\nexport function changeKey(\n score: Score,\n key: KeySignature,\n options: { fromMeasure: string | number }\n): Score {\n const result = cloneScore(score);\n const targetMeasure = String(options.fromMeasure);\n\n for (const part of result.parts) {\n for (const measure of part.measures) {\n if (measure.number === targetMeasure) {\n if (!measure.attributes) {\n measure.attributes = {};\n }\n measure.attributes.key = key;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Change time signature from a specific measure\n */\nexport function changeTime(\n score: Score,\n time: TimeSignature,\n options: { fromMeasure: string | number }\n): Score {\n const result = cloneScore(score);\n const targetMeasure = String(options.fromMeasure);\n\n for (const part of result.parts) {\n for (const measure of part.measures) {\n if (measure.number === targetMeasure) {\n if (!measure.attributes) {\n measure.attributes = {};\n }\n measure.attributes.time = time;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Insert a new measure after a specific measure number\n */\nexport function insertMeasure(\n score: Score,\n options: {\n afterMeasure: string | number;\n copyAttributes?: boolean;\n }\n): Score {\n const result = cloneScore(score);\n const targetMeasure = String(options.afterMeasure);\n\n for (const part of result.parts) {\n const insertIndex = part.measures.findIndex((m) => m.number === targetMeasure);\n if (insertIndex === -1) continue;\n\n // Parse target measure number and increment for new measure\n const numericPart = parseInt(targetMeasure, 10);\n const newMeasureNumber = String(isNaN(numericPart) ? insertIndex + 2 : numericPart + 1);\n\n // Create new empty measure\n const newMeasure: Measure = {\n number: newMeasureNumber,\n entries: [],\n };\n\n // Copy attributes if requested\n if (options.copyAttributes) {\n const sourceMeasure = part.measures[insertIndex];\n if (sourceMeasure.attributes) {\n newMeasure.attributes = { ...sourceMeasure.attributes };\n }\n }\n\n // Insert the new measure\n part.measures.splice(insertIndex + 1, 0, newMeasure);\n\n // Update measure numbers for subsequent measures\n for (let i = insertIndex + 2; i < part.measures.length; i++) {\n const currentNum = parseInt(part.measures[i].number, 10);\n if (!isNaN(currentNum)) {\n part.measures[i].number = String(currentNum + 1);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Delete a measure\n */\nexport function deleteMeasure(score: Score, measureNumber: string | number): Score {\n const result = cloneScore(score);\n const targetMeasure = String(measureNumber);\n\n for (const part of result.parts) {\n const deleteIndex = part.measures.findIndex((m) => m.number === targetMeasure);\n if (deleteIndex === -1) continue;\n\n // Remove the measure\n part.measures.splice(deleteIndex, 1);\n\n // Update measure numbers for subsequent measures\n for (let i = deleteIndex; i < part.measures.length; i++) {\n const currentNum = parseInt(part.measures[i].number, 10);\n if (!isNaN(currentNum)) {\n part.measures[i].number = String(currentNum - 1);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Set divisions for a measure\n */\nexport function setDivisions(\n score: Score,\n options: {\n partIndex: number;\n measureIndex: number;\n divisions: number;\n }\n): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n if (!measure.attributes) {\n measure.attributes = {};\n }\n measure.attributes.divisions = options.divisions;\n\n return result;\n}\n\n/**\n * Add a chord note (note that sounds simultaneously with the previous note)\n */\nexport function addChordNote(\n score: Score,\n options: {\n partIndex: number;\n measureIndex: number;\n afterNoteIndex: number;\n pitch: Pitch;\n }\n): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n // Find the note by counting only notes\n let noteCount = 0;\n let entryIndex = -1;\n let targetNote: NoteEntry | null = null;\n\n for (let i = 0; i < measure.entries.length; i++) {\n const entry = measure.entries[i];\n if (entry.type === 'note') {\n if (noteCount === options.afterNoteIndex) {\n entryIndex = i;\n targetNote = entry;\n break;\n }\n noteCount++;\n }\n }\n\n if (entryIndex !== -1 && targetNote) {\n const chordNote: NoteEntry = {\n type: 'note',\n pitch: options.pitch,\n duration: targetNote.duration,\n voice: targetNote.voice,\n staff: targetNote.staff,\n chord: true,\n noteType: targetNote.noteType,\n dots: targetNote.dots,\n };\n\n measure.entries.splice(entryIndex + 1, 0, chordNote);\n }\n\n return result;\n}\n\n/**\n * Modify a note's pitch\n */\nexport function modifyNotePitch(\n score: Score,\n options: {\n partIndex: number;\n measureIndex: number;\n noteIndex: number;\n pitch: Pitch;\n }\n): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n // Find the note by counting only notes\n let noteCount = 0;\n\n for (const entry of measure.entries) {\n if (entry.type === 'note') {\n if (noteCount === options.noteIndex) {\n entry.pitch = options.pitch;\n break;\n }\n noteCount++;\n }\n }\n\n return result;\n}\n\n/**\n * Modify a note's duration\n */\nexport function modifyNoteDuration(\n score: Score,\n options: {\n partIndex: number;\n measureIndex: number;\n noteIndex: number;\n duration: number;\n noteType?: NoteEntry['noteType'];\n dots?: number;\n }\n): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n // Find the note by counting only notes\n let noteCount = 0;\n\n for (const entry of measure.entries) {\n if (entry.type === 'note') {\n if (noteCount === options.noteIndex) {\n entry.duration = options.duration;\n if (options.noteType !== undefined) {\n entry.noteType = options.noteType;\n }\n if (options.dots !== undefined) {\n entry.dots = options.dots;\n }\n break;\n }\n noteCount++;\n }\n }\n\n return result;\n}\n","import type { Pitch, Measure, MeasureEntry, NoteEntry } from '../types';\n\n// Pitch constants\nexport const STEPS: Pitch['step'][] = ['C', 'D', 'E', 'F', 'G', 'A', 'B'];\nexport const STEP_SEMITONES: Record<Pitch['step'], number> = {\n 'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11,\n};\n\n/** Convert pitch to semitone value (MIDI-like) */\nexport function pitchToSemitone(pitch: Pitch): number {\n return pitch.octave * 12 + STEP_SEMITONES[pitch.step] + (pitch.alter ?? 0);\n}\n\n// Position tracking for measure iteration\nexport interface PositionState {\n position: number;\n lastNonChordPosition: number;\n}\n\nexport function createPositionState(): PositionState {\n return { position: 0, lastNonChordPosition: 0 };\n}\n\n/** Update position state for entry, returns position before update */\nexport function updatePositionForEntry(state: PositionState, entry: MeasureEntry): number {\n const pos = state.position;\n switch (entry.type) {\n case 'note': {\n const note = entry as NoteEntry;\n if (!note.chord) {\n state.lastNonChordPosition = state.position;\n state.position += note.duration;\n }\n return note.chord ? state.lastNonChordPosition : pos;\n }\n case 'backup':\n state.position -= entry.duration;\n state.lastNonChordPosition = state.position;\n return pos;\n case 'forward':\n state.position += entry.duration;\n state.lastNonChordPosition = state.position;\n return pos;\n default:\n return pos;\n }\n}\n\n/** Get absolute position of a note within a measure */\nexport function getAbsolutePositionForNote(note: NoteEntry, measure: Measure): number {\n const state = createPositionState();\n for (const entry of measure.entries) {\n if (entry === note) return entry.chord ? state.lastNonChordPosition : state.position;\n updatePositionForEntry(state, entry);\n }\n return state.position;\n}\n\n/** Get position at end of measure */\nexport function getMeasureEndPosition(measure: Measure): number {\n const state = createPositionState();\n for (const entry of measure.entries) updatePositionForEntry(state, entry);\n return state.position;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/index.ts","../../src/operations/index.ts"],"sourcesContent":["import type { Pitch, Measure, MeasureEntry, NoteEntry } from '../types';\n\n// Pitch constants\nexport const STEPS: Pitch['step'][] = ['C', 'D', 'E', 'F', 'G', 'A', 'B'];\nexport const STEP_SEMITONES: Record<Pitch['step'], number> = {\n 'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11,\n};\n\n/** Convert pitch to semitone value (MIDI-like) */\nexport function pitchToSemitone(pitch: Pitch): number {\n return pitch.octave * 12 + STEP_SEMITONES[pitch.step] + (pitch.alter ?? 0);\n}\n\n// Position tracking for measure iteration\nexport interface PositionState {\n position: number;\n lastNonChordPosition: number;\n}\n\nexport function createPositionState(): PositionState {\n return { position: 0, lastNonChordPosition: 0 };\n}\n\n/** Update position state for entry, returns position before update */\nexport function updatePositionForEntry(state: PositionState, entry: MeasureEntry): number {\n const pos = state.position;\n switch (entry.type) {\n case 'note': {\n const note = entry as NoteEntry;\n if (!note.chord) {\n state.lastNonChordPosition = state.position;\n state.position += note.duration;\n }\n return note.chord ? state.lastNonChordPosition : pos;\n }\n case 'backup':\n state.position -= entry.duration;\n state.lastNonChordPosition = state.position;\n return pos;\n case 'forward':\n state.position += entry.duration;\n state.lastNonChordPosition = state.position;\n return pos;\n default:\n return pos;\n }\n}\n\n/** Get absolute position of a note within a measure */\nexport function getAbsolutePositionForNote(note: NoteEntry, measure: Measure): number {\n const state = createPositionState();\n for (const entry of measure.entries) {\n if (entry === note) return entry.chord ? state.lastNonChordPosition : state.position;\n updatePositionForEntry(state, entry);\n }\n return state.position;\n}\n\n/** Get position at end of measure */\nexport function getMeasureEndPosition(measure: Measure): number {\n const state = createPositionState();\n for (const entry of measure.entries) updatePositionForEntry(state, entry);\n return state.position;\n}\n","import type {\n Score,\n Measure,\n NoteEntry,\n Pitch,\n KeySignature,\n TimeSignature,\n} from '../types';\nimport { STEPS, STEP_SEMITONES, getMeasureEndPosition } from '../utils';\n\n/**\n * Deep clone a score\n */\nfunction cloneScore(score: Score): Score {\n return JSON.parse(JSON.stringify(score));\n}\n\n/**\n * Transpose a pitch by a number of semitones\n */\nfunction transposePitch(pitch: Pitch, semitones: number): Pitch {\n const currentSemitone = STEP_SEMITONES[pitch.step] + (pitch.alter ?? 0) + pitch.octave * 12;\n const targetSemitone = currentSemitone + semitones;\n\n const targetOctave = Math.floor(targetSemitone / 12);\n const targetPitchClass = ((targetSemitone % 12) + 12) % 12;\n\n // Find the closest natural step with smallest alteration\n let bestStep: Pitch['step'] = 'C';\n let bestAlter = 99; // Start with large value so any real alter is smaller\n\n for (const step of STEPS) {\n const stepSemitone = STEP_SEMITONES[step];\n // Calculate the alteration needed to reach target from this step\n let diff = targetPitchClass - stepSemitone;\n\n // Normalize to range -6 to +6 for smallest alteration\n if (diff > 6) diff -= 12;\n if (diff < -6) diff += 12;\n\n // Only consider alterations within -2 to +2 (double flat to double sharp)\n if (diff >= -2 && diff <= 2) {\n if (Math.abs(diff) < Math.abs(bestAlter)) {\n bestStep = step;\n bestAlter = diff;\n }\n }\n }\n\n return {\n step: bestStep,\n octave: targetOctave,\n alter: bestAlter !== 0 ? bestAlter : undefined,\n };\n}\n\n/**\n * Transpose all notes in a score by a number of semitones\n */\nexport function transpose(score: Score, semitones: number): Score {\n if (semitones === 0) return score;\n\n const result = cloneScore(score);\n\n for (const part of result.parts) {\n for (const measure of part.measures) {\n for (const entry of measure.entries) {\n if (entry.type === 'note' && entry.pitch) {\n entry.pitch = transposePitch(entry.pitch, semitones);\n }\n }\n }\n }\n\n return result;\n}\n\n/**\n * Options for adding a note\n */\nexport interface AddNoteOptions {\n partIndex: number;\n measureIndex: number;\n staff?: number;\n voice: number;\n position: number;\n note: Omit<NoteEntry, 'type' | 'voice' | 'staff'>;\n}\n\n/**\n * Add a note to a measure\n * Automatically handles backup/forward insertion\n */\nexport function addNote(score: Score, options: AddNoteOptions): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n const newNote: NoteEntry = {\n type: 'note',\n voice: options.voice,\n staff: options.staff,\n ...options.note,\n };\n\n // Find the current position at the end of the measure using shared utility\n const currentPosition = getMeasureEndPosition(measure);\n\n // Calculate backup/forward needed\n const positionDiff = options.position - currentPosition;\n\n if (positionDiff < 0) {\n // Need to backup\n measure.entries.push({\n type: 'backup',\n duration: -positionDiff,\n });\n } else if (positionDiff > 0) {\n // Need to forward\n measure.entries.push({\n type: 'forward',\n duration: positionDiff,\n voice: options.voice,\n staff: options.staff,\n });\n }\n\n measure.entries.push(newNote);\n\n return result;\n}\n\n/**\n * Delete a note from a measure\n */\nexport function deleteNote(score: Score, options: {\n partIndex: number;\n measureIndex: number;\n noteIndex: number;\n}): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n // Find the note by counting only notes\n let noteCount = 0;\n let entryIndex = -1;\n\n for (let i = 0; i < measure.entries.length; i++) {\n if (measure.entries[i].type === 'note') {\n if (noteCount === options.noteIndex) {\n entryIndex = i;\n break;\n }\n noteCount++;\n }\n }\n\n if (entryIndex !== -1) {\n measure.entries.splice(entryIndex, 1);\n }\n\n return result;\n}\n\n/**\n * Change key signature from a specific measure\n */\nexport function changeKey(\n score: Score,\n key: KeySignature,\n options: { fromMeasure: string | number }\n): Score {\n const result = cloneScore(score);\n const targetMeasure = String(options.fromMeasure);\n\n for (const part of result.parts) {\n for (const measure of part.measures) {\n if (measure.number === targetMeasure) {\n if (!measure.attributes) {\n measure.attributes = {};\n }\n measure.attributes.key = key;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Change time signature from a specific measure\n */\nexport function changeTime(\n score: Score,\n time: TimeSignature,\n options: { fromMeasure: string | number }\n): Score {\n const result = cloneScore(score);\n const targetMeasure = String(options.fromMeasure);\n\n for (const part of result.parts) {\n for (const measure of part.measures) {\n if (measure.number === targetMeasure) {\n if (!measure.attributes) {\n measure.attributes = {};\n }\n measure.attributes.time = time;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Insert a new measure after a specific measure number\n */\nexport function insertMeasure(\n score: Score,\n options: {\n afterMeasure: string | number;\n copyAttributes?: boolean;\n }\n): Score {\n const result = cloneScore(score);\n const targetMeasure = String(options.afterMeasure);\n\n for (const part of result.parts) {\n const insertIndex = part.measures.findIndex((m) => m.number === targetMeasure);\n if (insertIndex === -1) continue;\n\n // Parse target measure number and increment for new measure\n const numericPart = parseInt(targetMeasure, 10);\n const newMeasureNumber = String(isNaN(numericPart) ? insertIndex + 2 : numericPart + 1);\n\n // Create new empty measure\n const newMeasure: Measure = {\n number: newMeasureNumber,\n entries: [],\n };\n\n // Copy attributes if requested\n if (options.copyAttributes) {\n const sourceMeasure = part.measures[insertIndex];\n if (sourceMeasure.attributes) {\n newMeasure.attributes = { ...sourceMeasure.attributes };\n }\n }\n\n // Insert the new measure\n part.measures.splice(insertIndex + 1, 0, newMeasure);\n\n // Update measure numbers for subsequent measures\n for (let i = insertIndex + 2; i < part.measures.length; i++) {\n const currentNum = parseInt(part.measures[i].number, 10);\n if (!isNaN(currentNum)) {\n part.measures[i].number = String(currentNum + 1);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Delete a measure\n */\nexport function deleteMeasure(score: Score, measureNumber: string | number): Score {\n const result = cloneScore(score);\n const targetMeasure = String(measureNumber);\n\n for (const part of result.parts) {\n const deleteIndex = part.measures.findIndex((m) => m.number === targetMeasure);\n if (deleteIndex === -1) continue;\n\n // Remove the measure\n part.measures.splice(deleteIndex, 1);\n\n // Update measure numbers for subsequent measures\n for (let i = deleteIndex; i < part.measures.length; i++) {\n const currentNum = parseInt(part.measures[i].number, 10);\n if (!isNaN(currentNum)) {\n part.measures[i].number = String(currentNum - 1);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Set divisions for a measure\n */\nexport function setDivisions(\n score: Score,\n options: {\n partIndex: number;\n measureIndex: number;\n divisions: number;\n }\n): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n if (!measure.attributes) {\n measure.attributes = {};\n }\n measure.attributes.divisions = options.divisions;\n\n return result;\n}\n\n/**\n * Add a chord note (note that sounds simultaneously with the previous note)\n */\nexport function addChordNote(\n score: Score,\n options: {\n partIndex: number;\n measureIndex: number;\n afterNoteIndex: number;\n pitch: Pitch;\n }\n): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n // Find the note by counting only notes\n let noteCount = 0;\n let entryIndex = -1;\n let targetNote: NoteEntry | null = null;\n\n for (let i = 0; i < measure.entries.length; i++) {\n const entry = measure.entries[i];\n if (entry.type === 'note') {\n if (noteCount === options.afterNoteIndex) {\n entryIndex = i;\n targetNote = entry;\n break;\n }\n noteCount++;\n }\n }\n\n if (entryIndex !== -1 && targetNote) {\n const chordNote: NoteEntry = {\n type: 'note',\n pitch: options.pitch,\n duration: targetNote.duration,\n voice: targetNote.voice,\n staff: targetNote.staff,\n chord: true,\n noteType: targetNote.noteType,\n dots: targetNote.dots,\n };\n\n measure.entries.splice(entryIndex + 1, 0, chordNote);\n }\n\n return result;\n}\n\n/**\n * Modify a note's pitch\n */\nexport function modifyNotePitch(\n score: Score,\n options: {\n partIndex: number;\n measureIndex: number;\n noteIndex: number;\n pitch: Pitch;\n }\n): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n // Find the note by counting only notes\n let noteCount = 0;\n\n for (const entry of measure.entries) {\n if (entry.type === 'note') {\n if (noteCount === options.noteIndex) {\n entry.pitch = options.pitch;\n break;\n }\n noteCount++;\n }\n }\n\n return result;\n}\n\n/**\n * Modify a note's duration\n */\nexport function modifyNoteDuration(\n score: Score,\n options: {\n partIndex: number;\n measureIndex: number;\n noteIndex: number;\n duration: number;\n noteType?: NoteEntry['noteType'];\n dots?: number;\n }\n): Score {\n const result = cloneScore(score);\n const part = result.parts[options.partIndex];\n if (!part) return result;\n\n const measure = part.measures[options.measureIndex];\n if (!measure) return result;\n\n // Find the note by counting only notes\n let noteCount = 0;\n\n for (const entry of measure.entries) {\n if (entry.type === 'note') {\n if (noteCount === options.noteIndex) {\n entry.duration = options.duration;\n if (options.noteType !== undefined) {\n entry.noteType = options.noteType;\n }\n if (options.dots !== undefined) {\n entry.dots = options.dots;\n }\n break;\n }\n noteCount++;\n }\n }\n\n return result;\n}\n"],"mappings":"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","names":[]}
|
package/dist/query/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/query/index.ts","../../src/utils/index.ts"],"sourcesContent":["import type {\n Score,\n Part,\n Measure,\n MeasureAttributes,\n NoteEntry,\n Pitch,\n} from '../types';\nimport { pitchToSemitone } from '../utils';\n\n/**\n * Get a specific measure from the score\n */\nexport function getMeasure(score: Score, options: { part: number; measure: string | number }): Measure | undefined {\n const part = score.parts[options.part];\n if (!part) return undefined;\n const targetMeasure = String(options.measure);\n\n return part.measures.find((m) => m.number === targetMeasure);\n}\n\n/**\n * Get measure by index\n */\nexport function getMeasureByIndex(score: Score, options: { part: number; measureIndex: number }): Measure | undefined {\n const part = score.parts[options.part];\n if (!part) return undefined;\n\n return part.measures[options.measureIndex];\n}\n\n/**\n * Get the total number of measures in a score\n */\nexport function getMeasureCount(score: Score): number {\n if (score.parts.length === 0) return 0;\n return score.parts[0].measures.length;\n}\n\n/**\n * Get the divisions value at a specific measure\n * Searches backwards from the specified measure to find the most recent divisions\n */\nexport function getDivisions(score: Score, options: { part: number; measure: string | number }): number {\n const part = score.parts[options.part];\n if (!part) return 1;\n const targetMeasure = parseInt(String(options.measure), 10);\n if (isNaN(targetMeasure)) return 1;\n\n for (let i = 0; i < part.measures.length; i++) {\n const m = part.measures[i];\n const mNum = parseInt(m.number, 10);\n if (!isNaN(mNum) && mNum > targetMeasure) break;\n\n if (m.attributes?.divisions !== undefined) {\n // Continue searching for a more recent value\n }\n }\n\n // Search from the beginning up to the specified measure\n let divisions = 1;\n for (const m of part.measures) {\n const mNum = parseInt(m.number, 10);\n if (!isNaN(mNum) && mNum > targetMeasure) break;\n if (m.attributes?.divisions !== undefined) {\n divisions = m.attributes.divisions;\n }\n }\n\n return divisions;\n}\n\n/**\n * Get the current attributes at a specific measure\n * Merges all attribute changes from measure 1 to the specified measure\n */\nexport function getAttributesAtMeasure(score: Score, options: { part: number; measure: string | number }): MeasureAttributes {\n const part = score.parts[options.part];\n if (!part) return {};\n const targetMeasure = parseInt(String(options.measure), 10);\n\n const result: MeasureAttributes = {};\n\n for (const m of part.measures) {\n const mNum = parseInt(m.number, 10);\n if (!isNaN(targetMeasure) && !isNaN(mNum) && mNum > targetMeasure) break;\n\n if (m.attributes) {\n if (m.attributes.divisions !== undefined) result.divisions = m.attributes.divisions;\n if (m.attributes.time !== undefined) result.time = m.attributes.time;\n if (m.attributes.key !== undefined) result.key = m.attributes.key;\n if (m.attributes.clef !== undefined) result.clef = m.attributes.clef;\n if (m.attributes.staves !== undefined) result.staves = m.attributes.staves;\n if (m.attributes.transpose !== undefined) result.transpose = m.attributes.transpose;\n }\n }\n\n return result;\n}\n\n/**\n * Pitch range filter\n */\nexport interface PitchRange {\n min?: Pitch;\n max?: Pitch;\n}\n\n/**\n * Find notes filter\n */\nexport interface FindNotesFilter {\n pitchRange?: PitchRange;\n voice?: number;\n staff?: number;\n noteType?: string;\n hasTie?: boolean;\n}\n\n/**\n * Find notes matching specific criteria\n */\nexport function findNotes(score: Score, filter: FindNotesFilter): NoteEntry[] {\n const results: NoteEntry[] = [];\n\n for (const part of score.parts) {\n for (const measure of part.measures) {\n for (const entry of measure.entries) {\n if (entry.type !== 'note') continue;\n\n // Filter by pitch range\n if (filter.pitchRange && entry.pitch) {\n const noteValue = pitchToSemitone(entry.pitch);\n\n if (filter.pitchRange.min) {\n const minValue = pitchToSemitone(filter.pitchRange.min);\n if (noteValue < minValue) continue;\n }\n\n if (filter.pitchRange.max) {\n const maxValue = pitchToSemitone(filter.pitchRange.max);\n if (noteValue > maxValue) continue;\n }\n }\n\n // Filter by voice\n if (filter.voice !== undefined && entry.voice !== filter.voice) continue;\n\n // Filter by staff\n if (filter.staff !== undefined && (entry.staff ?? 1) !== filter.staff) continue;\n\n // Filter by note type\n if (filter.noteType !== undefined && entry.noteType !== filter.noteType) continue;\n\n // Filter by tie\n if (filter.hasTie !== undefined) {\n const hasTie = entry.tie !== undefined;\n if (filter.hasTie !== hasTie) continue;\n }\n\n results.push(entry);\n }\n }\n }\n\n return results;\n}\n\n/**\n * Get the total duration of the score in divisions\n */\nexport function getDuration(score: Score): number {\n if (score.parts.length === 0) return 0;\n\n const part = score.parts[0];\n let totalDuration = 0;\n let divisions = 1;\n\n for (const measure of part.measures) {\n if (measure.attributes?.divisions !== undefined) {\n divisions = measure.attributes.divisions;\n }\n\n // Calculate measure duration based on time signature or actual notes\n let measureDuration = 0;\n\n for (const entry of measure.entries) {\n if (entry.type === 'note' && !entry.chord) {\n measureDuration = Math.max(measureDuration, entry.duration);\n }\n }\n\n // Use time signature to calculate expected duration if available\n const attrs = getAttributesAtMeasure(score, { part: 0, measure: measure.number });\n if (attrs.time) {\n const beats = parseInt(attrs.time.beats, 10) || 4;\n const expectedDuration = (beats / attrs.time.beatType) * 4 * divisions;\n measureDuration = Math.max(measureDuration, expectedDuration);\n }\n\n totalDuration += measureDuration;\n }\n\n return totalDuration;\n}\n\n/**\n * Get part by ID\n */\nexport function getPartById(score: Score, id: string): Part | undefined {\n return score.parts.find((p) => p.id === id);\n}\n\n/**\n * Get part index by ID\n */\nexport function getPartIndex(score: Score, id: string): number {\n return score.parts.findIndex((p) => p.id === id);\n}\n\n/**\n * Check if the score has multiple staves (e.g., piano grand staff)\n */\nexport function hasMultipleStaves(score: Score, partIndex: number = 0): boolean {\n const part = score.parts[partIndex];\n if (!part) return false;\n\n for (const measure of part.measures) {\n if (measure.attributes?.staves !== undefined && measure.attributes.staves > 1) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Get the number of staves for a part\n */\nexport function getStaveCount(score: Score, partIndex: number = 0): number {\n const part = score.parts[partIndex];\n if (!part) return 1;\n\n for (const measure of part.measures) {\n if (measure.attributes?.staves !== undefined) {\n return measure.attributes.staves;\n }\n }\n\n return 1;\n}\n\n/**\n * Round-trip metrics for measuring preservation fidelity\n */\nexport interface RoundtripMetrics {\n notesOriginal: number;\n notesPreserved: number;\n measuresOriginal: number;\n measuresPreserved: number;\n partsOriginal: number;\n partsPreserved: number;\n preservationRate: number;\n}\n\n/**\n * Compare two scores and calculate round-trip preservation metrics\n */\nexport function measureRoundtrip(original: Score, exported: Score): RoundtripMetrics {\n const notesOriginal = countNotes(original);\n const notesExported = countNotes(exported);\n const notesPreserved = Math.min(notesOriginal, notesExported);\n\n const measuresOriginal = getMeasureCount(original);\n const measuresExported = getMeasureCount(exported);\n const measuresPreserved = Math.min(measuresOriginal, measuresExported);\n\n const partsOriginal = original.parts.length;\n const partsExported = exported.parts.length;\n const partsPreserved = Math.min(partsOriginal, partsExported);\n\n // Calculate preservation rate based on notes (most granular)\n const preservationRate = notesOriginal > 0\n ? notesPreserved / notesOriginal\n : 1;\n\n return {\n notesOriginal,\n notesPreserved,\n measuresOriginal,\n measuresPreserved,\n partsOriginal,\n partsPreserved,\n preservationRate,\n };\n}\n\n/**\n * Count total notes in a score\n */\nexport function countNotes(score: Score): number {\n let count = 0;\n\n for (const part of score.parts) {\n for (const measure of part.measures) {\n for (const entry of measure.entries) {\n if (entry.type === 'note') {\n count++;\n }\n }\n }\n }\n\n return count;\n}\n\n/**\n * Compare two scores for structural equality\n */\nexport function scoresEqual(a: Score, b: Score): boolean {\n // Check parts count\n if (a.parts.length !== b.parts.length) return false;\n\n for (let i = 0; i < a.parts.length; i++) {\n const partA = a.parts[i];\n const partB = b.parts[i];\n\n if (partA.measures.length !== partB.measures.length) return false;\n\n for (let j = 0; j < partA.measures.length; j++) {\n const measureA = partA.measures[j];\n const measureB = partB.measures[j];\n\n if (measureA.number !== measureB.number) return false;\n\n // Compare entries count\n const notesA = measureA.entries.filter(e => e.type === 'note');\n const notesB = measureB.entries.filter(e => e.type === 'note');\n\n if (notesA.length !== notesB.length) return false;\n\n // Compare each note\n for (let k = 0; k < notesA.length; k++) {\n const noteA = notesA[k] as NoteEntry;\n const noteB = notesB[k] as NoteEntry;\n\n if (!pitchesEqual(noteA.pitch, noteB.pitch)) return false;\n if (noteA.duration !== noteB.duration) return false;\n if (noteA.voice !== noteB.voice) return false;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Compare two pitches for equality\n */\nfunction pitchesEqual(a: Pitch | undefined, b: Pitch | undefined): boolean {\n if (a === undefined && b === undefined) return true;\n if (a === undefined || b === undefined) return false;\n return a.step === b.step && a.octave === b.octave && (a.alter ?? 0) === (b.alter ?? 0);\n}\n","import type { Pitch, Measure, MeasureEntry, NoteEntry } from '../types';\n\n// Pitch constants\nexport const STEPS: Pitch['step'][] = ['C', 'D', 'E', 'F', 'G', 'A', 'B'];\nexport const STEP_SEMITONES: Record<Pitch['step'], number> = {\n 'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11,\n};\n\n/** Convert pitch to semitone value (MIDI-like) */\nexport function pitchToSemitone(pitch: Pitch): number {\n return pitch.octave * 12 + STEP_SEMITONES[pitch.step] + (pitch.alter ?? 0);\n}\n\n// Position tracking for measure iteration\nexport interface PositionState {\n position: number;\n lastNonChordPosition: number;\n}\n\nexport function createPositionState(): PositionState {\n return { position: 0, lastNonChordPosition: 0 };\n}\n\n/** Update position state for entry, returns position before update */\nexport function updatePositionForEntry(state: PositionState, entry: MeasureEntry): number {\n const pos = state.position;\n switch (entry.type) {\n case 'note': {\n const note = entry as NoteEntry;\n if (!note.chord) {\n state.lastNonChordPosition = state.position;\n state.position += note.duration;\n }\n return note.chord ? state.lastNonChordPosition : pos;\n }\n case 'backup':\n state.position -= entry.duration;\n state.lastNonChordPosition = state.position;\n return pos;\n case 'forward':\n state.position += entry.duration;\n state.lastNonChordPosition = state.position;\n return pos;\n default:\n return pos;\n }\n}\n\n/** Get absolute position of a note within a measure */\nexport function getAbsolutePositionForNote(note: NoteEntry, measure: Measure): number {\n const state = createPositionState();\n for (const entry of measure.entries) {\n if (entry === note) return entry.chord ? state.lastNonChordPosition : state.position;\n updatePositionForEntry(state, entry);\n }\n return state.position;\n}\n\n/** Get position at end of measure */\nexport function getMeasureEndPosition(measure: Measure): number {\n const state = createPositionState();\n for (const entry of measure.entries) updatePositionForEntry(state, entry);\n return state.position;\n}\n"],"mappings":"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","names":[]}
|
package/dist/query/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/index.ts","../../src/query/index.ts"],"sourcesContent":["import type { Pitch, Measure, MeasureEntry, NoteEntry } from '../types';\n\n// Pitch constants\nexport const STEPS: Pitch['step'][] = ['C', 'D', 'E', 'F', 'G', 'A', 'B'];\nexport const STEP_SEMITONES: Record<Pitch['step'], number> = {\n 'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11,\n};\n\n/** Convert pitch to semitone value (MIDI-like) */\nexport function pitchToSemitone(pitch: Pitch): number {\n return pitch.octave * 12 + STEP_SEMITONES[pitch.step] + (pitch.alter ?? 0);\n}\n\n// Position tracking for measure iteration\nexport interface PositionState {\n position: number;\n lastNonChordPosition: number;\n}\n\nexport function createPositionState(): PositionState {\n return { position: 0, lastNonChordPosition: 0 };\n}\n\n/** Update position state for entry, returns position before update */\nexport function updatePositionForEntry(state: PositionState, entry: MeasureEntry): number {\n const pos = state.position;\n switch (entry.type) {\n case 'note': {\n const note = entry as NoteEntry;\n if (!note.chord) {\n state.lastNonChordPosition = state.position;\n state.position += note.duration;\n }\n return note.chord ? state.lastNonChordPosition : pos;\n }\n case 'backup':\n state.position -= entry.duration;\n state.lastNonChordPosition = state.position;\n return pos;\n case 'forward':\n state.position += entry.duration;\n state.lastNonChordPosition = state.position;\n return pos;\n default:\n return pos;\n }\n}\n\n/** Get absolute position of a note within a measure */\nexport function getAbsolutePositionForNote(note: NoteEntry, measure: Measure): number {\n const state = createPositionState();\n for (const entry of measure.entries) {\n if (entry === note) return entry.chord ? state.lastNonChordPosition : state.position;\n updatePositionForEntry(state, entry);\n }\n return state.position;\n}\n\n/** Get position at end of measure */\nexport function getMeasureEndPosition(measure: Measure): number {\n const state = createPositionState();\n for (const entry of measure.entries) updatePositionForEntry(state, entry);\n return state.position;\n}\n","import type {\n Score,\n Part,\n Measure,\n MeasureAttributes,\n NoteEntry,\n Pitch,\n} from '../types';\nimport { pitchToSemitone } from '../utils';\n\n/**\n * Get a specific measure from the score\n */\nexport function getMeasure(score: Score, options: { part: number; measure: string | number }): Measure | undefined {\n const part = score.parts[options.part];\n if (!part) return undefined;\n const targetMeasure = String(options.measure);\n\n return part.measures.find((m) => m.number === targetMeasure);\n}\n\n/**\n * Get measure by index\n */\nexport function getMeasureByIndex(score: Score, options: { part: number; measureIndex: number }): Measure | undefined {\n const part = score.parts[options.part];\n if (!part) return undefined;\n\n return part.measures[options.measureIndex];\n}\n\n/**\n * Get the total number of measures in a score\n */\nexport function getMeasureCount(score: Score): number {\n if (score.parts.length === 0) return 0;\n return score.parts[0].measures.length;\n}\n\n/**\n * Get the divisions value at a specific measure\n * Searches backwards from the specified measure to find the most recent divisions\n */\nexport function getDivisions(score: Score, options: { part: number; measure: string | number }): number {\n const part = score.parts[options.part];\n if (!part) return 1;\n const targetMeasure = parseInt(String(options.measure), 10);\n if (isNaN(targetMeasure)) return 1;\n\n for (let i = 0; i < part.measures.length; i++) {\n const m = part.measures[i];\n const mNum = parseInt(m.number, 10);\n if (!isNaN(mNum) && mNum > targetMeasure) break;\n\n if (m.attributes?.divisions !== undefined) {\n // Continue searching for a more recent value\n }\n }\n\n // Search from the beginning up to the specified measure\n let divisions = 1;\n for (const m of part.measures) {\n const mNum = parseInt(m.number, 10);\n if (!isNaN(mNum) && mNum > targetMeasure) break;\n if (m.attributes?.divisions !== undefined) {\n divisions = m.attributes.divisions;\n }\n }\n\n return divisions;\n}\n\n/**\n * Get the current attributes at a specific measure\n * Merges all attribute changes from measure 1 to the specified measure\n */\nexport function getAttributesAtMeasure(score: Score, options: { part: number; measure: string | number }): MeasureAttributes {\n const part = score.parts[options.part];\n if (!part) return {};\n const targetMeasure = parseInt(String(options.measure), 10);\n\n const result: MeasureAttributes = {};\n\n for (const m of part.measures) {\n const mNum = parseInt(m.number, 10);\n if (!isNaN(targetMeasure) && !isNaN(mNum) && mNum > targetMeasure) break;\n\n if (m.attributes) {\n if (m.attributes.divisions !== undefined) result.divisions = m.attributes.divisions;\n if (m.attributes.time !== undefined) result.time = m.attributes.time;\n if (m.attributes.key !== undefined) result.key = m.attributes.key;\n if (m.attributes.clef !== undefined) result.clef = m.attributes.clef;\n if (m.attributes.staves !== undefined) result.staves = m.attributes.staves;\n if (m.attributes.transpose !== undefined) result.transpose = m.attributes.transpose;\n }\n }\n\n return result;\n}\n\n/**\n * Pitch range filter\n */\nexport interface PitchRange {\n min?: Pitch;\n max?: Pitch;\n}\n\n/**\n * Find notes filter\n */\nexport interface FindNotesFilter {\n pitchRange?: PitchRange;\n voice?: number;\n staff?: number;\n noteType?: string;\n hasTie?: boolean;\n}\n\n/**\n * Find notes matching specific criteria\n */\nexport function findNotes(score: Score, filter: FindNotesFilter): NoteEntry[] {\n const results: NoteEntry[] = [];\n\n for (const part of score.parts) {\n for (const measure of part.measures) {\n for (const entry of measure.entries) {\n if (entry.type !== 'note') continue;\n\n // Filter by pitch range\n if (filter.pitchRange && entry.pitch) {\n const noteValue = pitchToSemitone(entry.pitch);\n\n if (filter.pitchRange.min) {\n const minValue = pitchToSemitone(filter.pitchRange.min);\n if (noteValue < minValue) continue;\n }\n\n if (filter.pitchRange.max) {\n const maxValue = pitchToSemitone(filter.pitchRange.max);\n if (noteValue > maxValue) continue;\n }\n }\n\n // Filter by voice\n if (filter.voice !== undefined && entry.voice !== filter.voice) continue;\n\n // Filter by staff\n if (filter.staff !== undefined && (entry.staff ?? 1) !== filter.staff) continue;\n\n // Filter by note type\n if (filter.noteType !== undefined && entry.noteType !== filter.noteType) continue;\n\n // Filter by tie\n if (filter.hasTie !== undefined) {\n const hasTie = entry.tie !== undefined;\n if (filter.hasTie !== hasTie) continue;\n }\n\n results.push(entry);\n }\n }\n }\n\n return results;\n}\n\n/**\n * Get the total duration of the score in divisions\n */\nexport function getDuration(score: Score): number {\n if (score.parts.length === 0) return 0;\n\n const part = score.parts[0];\n let totalDuration = 0;\n let divisions = 1;\n\n for (const measure of part.measures) {\n if (measure.attributes?.divisions !== undefined) {\n divisions = measure.attributes.divisions;\n }\n\n // Calculate measure duration based on time signature or actual notes\n let measureDuration = 0;\n\n for (const entry of measure.entries) {\n if (entry.type === 'note' && !entry.chord) {\n measureDuration = Math.max(measureDuration, entry.duration);\n }\n }\n\n // Use time signature to calculate expected duration if available\n const attrs = getAttributesAtMeasure(score, { part: 0, measure: measure.number });\n if (attrs.time) {\n const beats = parseInt(attrs.time.beats, 10) || 4;\n const expectedDuration = (beats / attrs.time.beatType) * 4 * divisions;\n measureDuration = Math.max(measureDuration, expectedDuration);\n }\n\n totalDuration += measureDuration;\n }\n\n return totalDuration;\n}\n\n/**\n * Get part by ID\n */\nexport function getPartById(score: Score, id: string): Part | undefined {\n return score.parts.find((p) => p.id === id);\n}\n\n/**\n * Get part index by ID\n */\nexport function getPartIndex(score: Score, id: string): number {\n return score.parts.findIndex((p) => p.id === id);\n}\n\n/**\n * Check if the score has multiple staves (e.g., piano grand staff)\n */\nexport function hasMultipleStaves(score: Score, partIndex: number = 0): boolean {\n const part = score.parts[partIndex];\n if (!part) return false;\n\n for (const measure of part.measures) {\n if (measure.attributes?.staves !== undefined && measure.attributes.staves > 1) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Get the number of staves for a part\n */\nexport function getStaveCount(score: Score, partIndex: number = 0): number {\n const part = score.parts[partIndex];\n if (!part) return 1;\n\n for (const measure of part.measures) {\n if (measure.attributes?.staves !== undefined) {\n return measure.attributes.staves;\n }\n }\n\n return 1;\n}\n\n/**\n * Round-trip metrics for measuring preservation fidelity\n */\nexport interface RoundtripMetrics {\n notesOriginal: number;\n notesPreserved: number;\n measuresOriginal: number;\n measuresPreserved: number;\n partsOriginal: number;\n partsPreserved: number;\n preservationRate: number;\n}\n\n/**\n * Compare two scores and calculate round-trip preservation metrics\n */\nexport function measureRoundtrip(original: Score, exported: Score): RoundtripMetrics {\n const notesOriginal = countNotes(original);\n const notesExported = countNotes(exported);\n const notesPreserved = Math.min(notesOriginal, notesExported);\n\n const measuresOriginal = getMeasureCount(original);\n const measuresExported = getMeasureCount(exported);\n const measuresPreserved = Math.min(measuresOriginal, measuresExported);\n\n const partsOriginal = original.parts.length;\n const partsExported = exported.parts.length;\n const partsPreserved = Math.min(partsOriginal, partsExported);\n\n // Calculate preservation rate based on notes (most granular)\n const preservationRate = notesOriginal > 0\n ? notesPreserved / notesOriginal\n : 1;\n\n return {\n notesOriginal,\n notesPreserved,\n measuresOriginal,\n measuresPreserved,\n partsOriginal,\n partsPreserved,\n preservationRate,\n };\n}\n\n/**\n * Count total notes in a score\n */\nexport function countNotes(score: Score): number {\n let count = 0;\n\n for (const part of score.parts) {\n for (const measure of part.measures) {\n for (const entry of measure.entries) {\n if (entry.type === 'note') {\n count++;\n }\n }\n }\n }\n\n return count;\n}\n\n/**\n * Compare two scores for structural equality\n */\nexport function scoresEqual(a: Score, b: Score): boolean {\n // Check parts count\n if (a.parts.length !== b.parts.length) return false;\n\n for (let i = 0; i < a.parts.length; i++) {\n const partA = a.parts[i];\n const partB = b.parts[i];\n\n if (partA.measures.length !== partB.measures.length) return false;\n\n for (let j = 0; j < partA.measures.length; j++) {\n const measureA = partA.measures[j];\n const measureB = partB.measures[j];\n\n if (measureA.number !== measureB.number) return false;\n\n // Compare entries count\n const notesA = measureA.entries.filter(e => e.type === 'note');\n const notesB = measureB.entries.filter(e => e.type === 'note');\n\n if (notesA.length !== notesB.length) return false;\n\n // Compare each note\n for (let k = 0; k < notesA.length; k++) {\n const noteA = notesA[k] as NoteEntry;\n const noteB = notesB[k] as NoteEntry;\n\n if (!pitchesEqual(noteA.pitch, noteB.pitch)) return false;\n if (noteA.duration !== noteB.duration) return false;\n if (noteA.voice !== noteB.voice) return false;\n }\n }\n }\n\n return true;\n}\n\n/**\n * Compare two pitches for equality\n */\nfunction pitchesEqual(a: Pitch | undefined, b: Pitch | undefined): boolean {\n if (a === undefined && b === undefined) return true;\n if (a === undefined || b === undefined) return false;\n return a.step === b.step && a.octave === b.octave && (a.alter ?? 0) === (b.alter ?? 0);\n}\n"],"mappings":"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","names":[]}
|