Menu
Architectural decision Record 0008: VECTOR PATH DESCRIPTORS
ADR-0008: Implementation of Vector Path Descriptors (VPDs)
Status
Accepted
Context
FrankenScore deals with complex, hierarchical musical structures that need to be efficiently referenced, manipulated, and communicated between different parts of the system. We need a way to uniquely identify and address specific elements within a musical score, from high-level structures like instruments and staves down to individual notes and articulations. This addressing system needs to be compact, efficient, and flexible enough to handle both the musical and visual hierarchies of a score.
Decision
We will implement Vector Path Descriptors (VPDs) as the primary method for addressing and referencing elements within FrankenScore's musical structures.
Rationale
VPD Structure and Examples
VPDs are vectors that describe a path to a specific element within the nested structure of a FrankenScore piece. They use a combination of keywords and indices to navigate the piece structure. In API calls, VPDs are used as the first argument, followed by a Piece or PieceID, and then any additional arguments.
Basic VPD Structure
Accepted
Context
FrankenScore deals with complex, hierarchical musical structures that need to be efficiently referenced, manipulated, and communicated between different parts of the system. We need a way to uniquely identify and address specific elements within a musical score, from high-level structures like instruments and staves down to individual notes and articulations. This addressing system needs to be compact, efficient, and flexible enough to handle both the musical and visual hierarchies of a score.
Decision
We will implement Vector Path Descriptors (VPDs) as the primary method for addressing and referencing elements within FrankenScore's musical structures.
Rationale
- Consistency: VPDs provide a uniform way to reference elements across different parts of the codebase.
- Efficiency: They allow for compact representation of paths, which is especially useful in communication between frontend and backend.
- Flexibility: VPDs can easily accommodate both musical and visual hierarchies.
- Scalability: As the project grows, VPDs make it easier to add new operations without changing the fundamental way of addressing elements.
- Transaction support: VPDs work seamlessly with FrankenScore's transaction system, ensuring operations are performed within the context of the current piece transaction.
- Integration with existing tools: VPDs can be easily used with libraries like Specter for powerful data structure traversal and manipulation.
VPD Structure and Examples
VPDs are vectors that describe a path to a specific element within the nested structure of a FrankenScore piece. They use a combination of keywords and indices to navigate the piece structure. In API calls, VPDs are used as the first argument, followed by a Piece or PieceID, and then any additional arguments.
Basic VPD Structure
Examples
1. Accessing a specific measure
1. Accessing a specific measure
This VPD points to the 4th measure of the first voice of the first staff of the second instrument of the first musician.
2. Accessing a layout element
2. Accessing a layout element
This points to the 4th measure view of the first staff view of the second system view of the third page view of the first layout.
3. Compact form for brevity:
3. Compact form for brevity:
4. Accessing items within a measure:
5. Nested structures (e.g., tuplets):
Usage Examples
1. Adding an articulation:
This adds a staccato articulation to all notes in the specified measure.
2. Getting a specific note
2. Getting a specific note
This retrieves the third item in the specified measure.
3. Updating a layout element:
3. Updating a layout element:
This sets the staff spacing for the second system view of the third page view in the first layout to 20.
4. Querying all pitches in a measure:
4. Querying all pitches in a measure:
This returns all pitch items in the specified measure.
5. Setting a property of a specific element:
5. Setting a property of a specific element:
This sets the duration of the third and fourth items in the specified measure to a double-dotted quarter note and a sixteenth, respectively.
Consequences
Positive:
Negative:
Implementation Approach
Alternatives Considered
Notes
Consequences
Positive:
- Unified addressing scheme across the entire application.
- Simplified API for accessing and modifying score elements.
- Efficient communication of element references between frontend and backend.
- Easier implementation of operations like copy/paste, drag-and-drop, and undo/redo.
- Seamless integration with FrankenScore's transaction system.
Negative:
- Learning curve for developers to understand and use VPDs effectively.
- Potential for invalid paths if not properly validated.
- May require custom serialization/deserialization for persistence and network communication.
Implementation Approach
- Define a clear syntax for VPDs, including support for both verbose and compact forms.
- Implement core functions for creating, validating, and resolving VPDs.
- Integrate VPDs with Specter for efficient traversal and manipulation of score structures.
- Develop a system for partial VPDs to handle relative addressing within nested structures.
- Implement serialization and deserialization methods for VPDs, ensuring compatibility with the chosen inter-process communication system (gRPC).
- Create utility functions for common VPD operations (e.g., parent path, child paths, sibling paths).
- Implement a caching mechanism for frequently accessed paths to improve performance.
- Develop comprehensive testing suites for VPD creation, resolution, and manipulation.
- Extend the `retrieve` function to handle new selectors for measure contents.
- Create helper functions for common operations on measure contents, such as filtering items by type or applying a predicate.
- Update API functions to use the pattern of (function-name vpd piece-or-id ...other-args).
- Update documentation to explain how to use VPDs, including the extended syntax for measure contents.
Alternatives Considered
- String-based Paths: Rejected due to less efficient parsing and higher verbosity.
- Integer-based Indexing: Rejected due to lack of clarity and difficulty in representing complex hierarchies.
- Object References: Rejected due to issues with serialization and communication between frontend and backend.
Notes
- We should develop clear guidelines for when to use verbose vs. compact VPD forms.
- Consider implementing a VPD parser that can convert between string representations and vector forms for easier manual input and debugging.
- Explore the possibility of using VPDs in user-facing features, such as a command palette or scripting interface, to allow advanced users direct access to score elements.
- Pay special attention to performance optimizations for very large scores.
- Carefully design the system for handling dynamic structures within measures (e.g., nested tuplets, grace notes).
- Consider potential extensions for future musical concepts or structures.
- Develop debugging tools that can visualize VPDs within the context of a score, aiding in development and troubleshooting.
- Regularly benchmark VPD operations against direct object manipulation to ensure there's no significant performance hit.
- Implement robust error handling for invalid paths, both for developer usability and to prevent potential security issues.
- Ensure that all API functions consistently use the pattern of (function-name vpd piece-or-id ...other-args) for clarity and consistency.
|
FrankenScore is a modern, open-source music notation software designed to handle complex musical scores with ease. It is designed to be a flexible and powerful music notation software tool providing professional, extremely high-quality results. The core functionality includes inputting music notation, formatting scores and their parts, and printing them. Additional features can be added as plugins, allowing for a modular and customizable user experience.
|