Skip to main content

acorde_core/
lib.rs

1//! Platform-agnostic music score data model and command engine (undo/redo), with zero I/O
2//! and zero rendering. Pairs with [`acorde-io`](https://docs.rs/acorde-io) for MusicXML/MIDI/ABC
3//! parsing and [`acorde-layout`](https://docs.rs/acorde-layout) for logical score layout.
4
5pub mod model;
6
7pub use model::arrange::{
8    AccordionAnalysis, AccordionBassMode, AccordionDroneOptions, AccordionDroneResult,
9    AccordionInversion, AccordionLossPolicy, AccordionMelodicVoice, AccordionPattern,
10    AccordionReductionDiagnostic, AccordionReductionOptions, AccordionReductionResult,
11    AccordionSourceMapping, AccordionSwingPolicy, ArrangeResult, GuidedAccordionOptions,
12    GuidedAccordionResult, GuidedArrangeDiagnostic, LayeredAccordionOptions,
13    LayeredAccordionResult, PartCandidate, PositionedAccordionChord, analyze_for_accordion,
14    arrange_for_accordion, arrange_for_accordion_with_options, arrange_with_drone,
15    arrange_with_explicit_chords, arrange_with_layers,
16};
17pub use model::arrange_presets::{
18    AccordionLayerConfig, AccordionLayerResult, AccordionLayerShuffleOptions,
19    AccordionPresetCapabilities, AccordionPresetConfig, AccordionPresetDescription,
20    AccordionPresetResult, AccordionPresetSelection, AccordionPreviousConfig,
21    AccordionShuffleOptions, accordion_preset_capabilities, arrange_accordion_layers,
22    arrange_accordion_preset, arrange_from_resolved_layers, arrange_from_resolved_preset,
23    shuffle_accordion_layers, shuffle_accordion_preset,
24};
25pub use model::authored_chords::{
26    AuthoredChordAnnotation, AuthoredChordDiagnostic, AuthoredChordOptions, AuthoredChordResult,
27    annotate_from_authored_chords,
28};
29pub use model::change_hint::{ChangeHint, ChangeScope};
30pub use model::chord_plan::{
31    BeatFraction, CHORD_PLAN_CONTRACT_VERSION, ChordPlan, ChordPlanCoverage, ChordPlanDiagnostic,
32    ChordPlanEntry, ChordPlanExtractionMode, ChordPlanExtractionOptions, ChordPlanExtractionResult,
33    ChordPlanOrigin, ChordPlanPosition, ChordPlanPresetResult, ChordPlanSource,
34    chord_plan_to_preset_selection, extract_chord_plan,
35};
36pub use model::chord_proposals::{
37    CHORD_PROPOSAL_CONTRACT_VERSION, ChordChangedSpan, ChordProposalArrangementResult,
38    ChordProposalCandidate, ChordProposalDiagnostic, ChordProposalRequest, ChordProposalResult,
39    ResolvedChordProposal, arrange_from_chord_proposal, suggest_chord_plans,
40};
41pub use model::commands::{
42    AddHairpinCmd, AddMeasureCmd, AddNoteCmd, AddPartCmd, AddPedalCmd, AddPitchCmd, AddSpannerCmd,
43    AddStaffCmd, BatchCmd, Command, CommandStack, CycleEnharmonicSpellingCmd, DeleteMeasureCmd,
44    DeleteNoteCmd, DeletePartCmd, DeleteStaffCmd, DurationScale, ExchangeVoicesCmd,
45    ExplodeChordPitchesCmd, ExplodeVoicesCmd, ImplodeStavesCmd, JoinMeasuresCmd,
46    MoveOrCopyVoiceRangeCmd, NewScoreCmd, PasteRangeCmd, PasteScoreFragmentCmd, PasteVoiceCmd,
47    RealizeChordSymbolsCmd, RemoveScoreViewCmd, RemoveSpannerCmd, RemoveTrailingEmptyMeasuresCmd,
48    ReorderPartsCmd, ResequenceRehearsalMarksCmd, RespellScoreCmd, RespellScoreToKeyCmd,
49    RespellStaffRegionCmd, ScaleVoiceRangeCmd, ScoreFragmentPastePolicy, SetArpeggioCmd,
50    SetBarlineCmd, SetChordSymbolCmd, SetClefCmd, SetCrossStaffCmd, SetCueCmd, SetDurationCmd,
51    SetDynamicCmd, SetExpressionTextCmd, SetFiguredBassCmd, SetFingeringCmd, SetFingeringsCmd,
52    SetGlissandoCmd, SetGraceCmd, SetGuitarBendAlterCmd, SetGuitarBendCurveCmd,
53    SetGuitarTechniqueCmd, SetHarmonyRangeCmd, SetHarpPedalDiagramsCmd, SetHiddenCmd,
54    SetInstrumentDefinitionCmd, SetInstrumentIdCmd, SetKeySignatureCmd, SetLyricCmd,
55    SetMeasureInstrumentChangeCmd, SetMeasureTablatureChangeCmd, SetMeasureTextCmd, SetMetadataCmd,
56    SetMidMeasureClefsCmd, SetMidiInstrumentCmd, SetMultiRestCmd, SetNavigationMarkCmd,
57    SetNoteHeadCmd, SetNotePlacementCmd, SetObjectStyleOverridesCmd, SetOttavaCmd, SetPageBreakCmd,
58    SetPartGroupCmd, SetPartNameCmd, SetPercussionKitCmd, SetRehearsalMarkCmd,
59    SetScoreStyleOverridesCmd, SetScoreTextCmd, SetSectionBreakCmd, SetStaffPresentationCmd,
60    SetStemCmd, SetStringNumberCmd, SetSystemBreakCmd, SetSystemBreakIntervalCmd,
61    SetTabPositionCmd, SetTablatureConfigCmd, SetTechniqueTextCmd, SetTempoAtMeasureCmd,
62    SetTempoCmd, SetTimeSignatureCmd, SetTransposeCmd, SetTupletCmd, SetUnpitchedCmd, SetVoltaCmd,
63    SplitMeasureCmd, ToggleArticulationCmd, ToggleSlurCmd, ToggleTieCmd, ToggleTrillLineCmd,
64    TransposeStaffRegionCmd, TupletScalePolicy, UnrollRepeatsCmd, UpdateSpannerCmd,
65    UpsertScoreViewCmd, command_key, command_label,
66};
67pub use model::duration::Duration;
68pub use model::engine::{EngineHistory, HistoryConflict, HistoryRelation, ScoreEngine};
69pub use model::fragment::{
70    MIN_SUPPORTED_SCORE_FRAGMENT_CONTRACT_VERSION, SCORE_FRAGMENT_CONTRACT_VERSION, ScoreFragment,
71    ScoreFragmentCrossStaffTarget, ScoreFragmentDiagnostic, ScoreFragmentMeasure,
72    ScoreFragmentMeasureAttributes, ScoreFragmentSelection, ScoreFragmentVoice,
73    extract_score_fragment,
74};
75pub use model::gm::{drum_name, program_name};
76pub use model::harmony::{detect_chord, roman_numeral};
77pub use model::interval::{Interval, IntervalQuality};
78pub use model::musical_diff::{
79    MusicalChange, MusicalChangeKind, MusicalComparisonDiagnostic, MusicalComparisonOptions,
80    MusicalComparisonResult, NoteCorrespondence, StructurePolicy, VoiceAddr, VoiceCorrespondence,
81    compare_musical_positions,
82};
83pub use model::notation::{
84    AccidentalDisplay, Articulation, Barline, BeamState, ChordBarre, ChordDefinition,
85    ChordDefinitionMember, ChordDegree, ChordSymbol, Clef, CrossStaff, Dynamic, FiguredBassFigure,
86    FingeringSelectionPolicy, GuitarTechnique, HairpinKind, KeySignature, Lyric, NoteHead,
87    OttavaKind, StyledText, TabPosition, TablatureConfig, TextStyle, TimeSignature, TimeSymbol,
88    TupletBoundary, TupletInfo, VerseLyric,
89};
90pub use model::omr::{
91    MAX_OMR_ANNOTATIONS, MAX_OMR_EVENTS_PER_MEASURE, MAX_OMR_MEASURES, MAX_OMR_PAGES,
92    OMR_PROPOSAL_CONTRACT_VERSION, OmrCommandPlan, OmrDiagnostic, OmrDiagnosticKind,
93    OmrMeasureProposal, OmrMeasureTarget, OmrNoteAnnotation, OmrNoteAnnotationProposal,
94    OmrNoteTarget, OmrPage, OmrProposal, OmrRegion, OmrRhythmicEvent, OmrUnresolvedItem,
95};
96pub use model::pitch::{Pitch, Step};
97pub use model::playback::{
98    DynamicTimeline, MAX_PLAYBACK_COMPARISON_EVENTS, MAX_TAB_PERFORMANCE_EVENTS, MetronomeConfig,
99    OFFLINE_RENDER_CONTRACT_VERSION, OfflineRenderDiagnostic, OfflineRenderDiagnosticKind,
100    OfflineRenderFormat, OfflineRenderFrameEvent, OfflineRenderManifest,
101    OfflineRenderMeasureAddress, OfflineRenderNavigationPolicy, OfflineRenderRequest,
102    OfflineRenderResult, OfflineRenderScope, OfflineRenderSemanticEventKind,
103    OfflineRenderSemanticFrameEvent, PLAYBACK_COMPARISON_CONTRACT_VERSION,
104    PLAYBACK_ROUTING_CONTRACT_VERSION, PLAYBACK_TIMING_CORPUS_CONTRACT_VERSION, PlaybackAuxSend,
105    PlaybackBusRoute, PlaybackEffectRoute, PlaybackEvent, PlaybackOptions, PlaybackPosition,
106    PlaybackRealizationProfile, PlaybackRoutingConfig, PlaybackRoutingManifest, PlaybackTimingCase,
107    PlaybackTimingCaseReport, PlaybackTimingCorpusReport, PlaybackTimingMismatch,
108    PlaybackTimingReport, PlaybackTimingTolerance, TAB_PERFORMANCE_CONTRACT_VERSION,
109    TAB_ROUND_TRIP_CONTRACT_VERSION, TablaturePerformanceDiagnostic, TablaturePerformanceEvent,
110    TablaturePerformanceReport, TablatureRoundTripDiagnostic, TablatureRoundTripReport,
111    build_offline_render_manifest, build_playback_routing_manifest, compare_playback_timing,
112    compute_playback_position, evaluate_playback_timing_corpus, project_tablature_performance,
113    tablature_round_trip_report, to_playback_events, to_playback_events_bounded,
114};
115pub use model::repeat::measure_sequence;
116pub use model::scale::{Scale, ScaleKind};
117pub use model::score::{
118    GuitarBendPoint, HarpPedalDiagram, HarpPedalPosition, InstrumentDefinition, InstrumentRange,
119    Measure, MeasureLength, MetronomeMark, MidMeasureClef, MidiAftertouch, MidiControlChange,
120    MidiPitchBend, MidiProgramChange, NotationSpanner, NotationSpannerKind, Note, NoteAddr,
121    ObjectStyleOverride, ObjectStyleTarget, Part, PartGroup, PartGroupSymbol, PercussionInstrument,
122    RegionalTranspositionTarget, RespellPolicy, Score, ScoreChange, ScoreMetadata, ScorePatch,
123    ScoreSettings, ScoreStats, ScoreTemplate, ScoreView, ScoreViewLayoutOverrides, Staff,
124    StaffGroup, StaffKind, StaffNoteheadScheme, StaffPresentation, StyleImportProvenance,
125    TablatureFretMarkStyle, TablatureRhythmDisplay, ViewStaffKindOverride, ViewStaffRef, ViewStyle,
126    ViewStyleOverride, ViewStyleProperty, ViewTranspositionPolicy, VoltaBracket, apply_patch,
127    assign_tablature_positions, compute_beams, diff, measure_beats_remaining,
128    optimize_tablature_positions, respell_score, respell_score_to_key, respell_staff_region,
129    score_duration_secs, score_duration_secs_region, score_patch, suggested_stem_up, transpose,
130    transpose_checked, transpose_staff_region_checked, tuplet_group_ranges, voice_duration_beats,
131};
132pub use model::structural_plan::{
133    STRUCTURAL_CHANGE_PLAN_CONTRACT_VERSION, StructuralChangeDiagnostic,
134    StructuralChangeDiagnosticKind, StructuralChangePlan, StructuralMeasureStructure,
135    plan_structural_change,
136};
137pub use model::validate::{
138    GuitarBendCurveValidationReason, InstrumentDefinitionValidationReason, InstrumentRangeKind,
139    ObjectStyleValidationReason, PercussionInstrumentValidationReason, ScoreViewValidationReason,
140    SpannerEndpoint, StaffPresentationValidationReason, TablatureValidationReason, ValidationError,
141    ValidationReport, ValidationWarning, validate,
142};
143
144/// Current Score JSON schema version produced by this crate.
145pub const SCORE_SCHEMA_VERSION: u32 = 1;
146
147#[derive(Debug, thiserror::Error)]
148pub enum Error {
149    #[error("part index {0} out of range")]
150    PartNotFound(usize),
151    #[error("staff index {0} out of range")]
152    StaffNotFound(usize),
153    #[error("measure index {0} out of range")]
154    MeasureNotFound(usize),
155    #[error("note index {0} out of range")]
156    NoteNotFound(usize),
157    #[error("voice index {0} out of range")]
158    VoiceOutOfRange(usize),
159    #[error("{0}")]
160    InvalidCommand(String),
161    #[error("nothing to undo")]
162    NothingToUndo,
163    #[error("nothing to redo")]
164    NothingToRedo,
165    #[error("clipboard is empty")]
166    ClipboardEmpty,
167    #[error("cannot delete the last staff of a part")]
168    CannotDeleteLastStaff,
169    #[error("invalid patch: {0}")]
170    InvalidPatch(String),
171    #[error("score failed structural validation")]
172    InvalidScore,
173    #[error("engine history base score does not match the supplied score")]
174    HistoryBaseMismatch,
175    #[error("engine history is not a safe append-only extension")]
176    HistoryNotAppendable,
177    #[error("invalid playback comparison tolerance")]
178    InvalidPlaybackComparison,
179    #[error("invalid offline render request")]
180    InvalidOfflineRenderRequest,
181    #[error("invalid playback routing configuration")]
182    InvalidPlaybackRouting,
183    #[error("invalid playback timing corpus")]
184    InvalidPlaybackTimingCorpus,
185    #[error("playback comparison contains too many events ({0})")]
186    PlaybackComparisonTooLarge(usize),
187    #[error("tablature performance projection contains too many events ({0})")]
188    TabPerformanceTooLarge(usize),
189    #[error("tablature round-trip serialization failed: {0}")]
190    TabRoundTripSerialization(String),
191}