Skip to content

MJRasicci/Motif

Repository files navigation

Motif

Motif is a .NET 10 music score library built around a mutable, format-agnostic Score domain model. The current production extension is Guitar Pro support via Motif.Extensions.GuitarPro, focused on GP7+ .gp archives and raw .gpif, plus a companion CLI for inspection, conversion, and round-trip diagnostics.

In the current core model, notes store a single sounding Pitch, written-versus-sounding transposition lives at the track level, exact score time uses rational ScoreTime fractions, and note duration semantics distinguish written Duration from SoundingDuration. Guitar Pro-specific fidelity state stays on attached GP extensions rather than in the core JSON shape. Canonical authored control data now lives on Score.PointControls and Score.SpanControls, timeline bars can carry explicit written Start and Duration, and linked-note techniques can use NoteArticulation.Relations instead of relying only on format-specific flags.

Current Scope

  • Read Guitar Pro GP7+ .gp archives and extract Content/score.gpif
  • Deserialize GPIF XML into a typed raw model
  • Resolve GPIF references into a clean domain graph: Score -> Tracks -> Staves -> StaffMeasures -> Voices -> Beats -> Notes
  • Preserve score-wide timeline and navigation state on Score.TimelineBars
  • Rebuild derived playback order with ScoreNavigation
  • Write edited scores back to .gpif, GP7+ .gp, or native .motif
  • Convert between GP7+ .gp, .gpif, .motif, and mapped JSON with motif-cli

Projects

Project Purpose
Motif.Core Format-agnostic domain model, navigation helpers, and serialization helpers
Motif.Extensions.GuitarPro Guitar Pro GP7+ .gp / .gpif read-write support
Motif Convenience package referencing Core and Guitar Pro support
Motif.CLI (motif-cli) CLI for conversion, inspection, and batch diagnostics
Motif.SchemaExport Build-time JSON Schema exporter for native Motif artifacts

Repository Layout

Source/
  Motif/                             Convenience package
  Motif.Core/                        Core domain model and navigation helpers
  Motif.Extensions.GuitarPro/        Guitar Pro reader/writer, mapper, raw GPIF model
  Motif.CLI/                         CLI executable project
  Motif.SchemaExport/                Build-time JSON Schema exporter
Tests/
  Motif.Core.UnitTests/              Core model, navigation, and serialization tests
  Motif.Extensions.GuitarPro.UnitTests/
                                     Guitar Pro mapping, writing, and round-trip tests
  Motif.IntegrationTests/            CLI integration and regression coverage
docs/
  CLI_WORKFLOW.md                    CLI usage and batch workflows
  LIBRARY_WORKFLOW.md                Recommended library edit/write workflow

Library Quick Start

using Motif;

var score = await MotifScore.OpenAsync("song.gp", cancellationToken: cancellationToken);

score.Title = "Edited Title";

// Rebuild derived playback state after navigation-affecting edits.
ScoreNavigation.RebuildPlaybackSequence(score);

await MotifScore.SaveAsync(score, "song-edited.gp", cancellationToken);

MotifScore handles mapped JSON and native .motif archives directly, and discovers extension handlers such as Guitar Pro at runtime. .motif archives always contain manifest.json and score.json, and now preserve namespaced extensions/ and resources/ entries so format packages can round-trip supplementary data without the core archive writer knowing format details. Guitar Pro now uses those locations to carry raw GP metadata plus non-score archive files through .gp -> .motif -> .gp workflows. In the current corpus, those preserved non-score entries commonly include VERSION, Content/BinaryStylesheet, layout/config files, Content/ScoreViews/*, Content/Stylesheets/*, and in some files Content/Assets/* such as embedded WAV audio. Preservation is generic: every original .gp archive entry other than Content/score.gpif is carried forward. Older pre-GP7 Guitar Pro formats such as .gpx are intentionally unsupported today; Motif expects those files to be converted forward in Guitar Pro before import. When a score is opened from a file path, .motif manifests also record the imported format and source file name in manifest.sources, including extensionless workflows that use an explicit format hint. Mapped JSON is intentionally not a self-contained carrier for preserved archive resources, provenance, or format-specific fidelity state in v1. Use .motif when you need a portable document that can later export back with preserved contributor payload, and use MotifScore.ReattachArchiveStateFrom(...) before writing .motif, .gp, or .gpif from standalone JSON when you still have a source score available. Use GuitarProWriter directly, or resolve it through MotifScore.CreateWriter("gp"), when you need Guitar Pro-specific write diagnostics or explicit source-archive control such as the CLI --source-gp workflow.

CLI Quick Start

Run during development:

dotnet run --project Source/Motif.CLI -- <args>

Common commands:

# Export mapped JSON (default output: song.mapped.json)
dotnet run --project Source/Motif.CLI -- song.gp

# Extract raw GPIF
dotnet run --project Source/Motif.CLI -- song.gp song.score.gpif

# Convert raw GPIF to mapped JSON
dotnet run --project Source/Motif.CLI -- song.gpif song.json

# Package a score as a native .motif archive
dotnet run --project Source/Motif.CLI -- song.gp song.motif

# Read a native .motif archive back to mapped JSON
dotnet run --project Source/Motif.CLI -- song.motif song.json

# Write a new .gp archive from mapped JSON with regenerated GP state
dotnet run --project Source/Motif.CLI -- song.json output.gp

# Reattach archive context from an existing source score after standalone JSON edits
dotnet run --project Source/Motif.CLI -- edited.json restored.motif --source-score source.motif

# Preserve non-score archive entries from an existing source archive
dotnet run --project Source/Motif.CLI -- song.json output.gp --source-gp original.gp

# Batch export every .gp file under a directory to JSON
dotnet run --project Source/Motif.CLI -- \
  --batch-input-dir ./songs \
  --batch-output-dir ./json

# Batch round-trip diagnostics across a corpus
dotnet run --project Source/Motif.CLI -- \
  --batch-input-dir ./songs \
  --batch-output-dir ./analysis \
  --batch-roundtrip-diagnostics

Formats are inferred from file extensions when possible. Use --input-format and --output-format when extensions are missing or ambiguous. Boolean flags follow the same pattern everywhere: --flag, --flag=true, and --flag=false.

Known current fidelity limitations are tracked in docs/KNOWN_LIMITATIONS.md.

Supported Formats

Format Read Write Notes
gp Yes Yes Guitar Pro GP7+ ZIP archive containing Content/score.gpif
gpif Yes Yes Raw GPIF XML from the GP7+ format family
motif Yes Yes Native ZIP archive with manifest.json, score.json, and preserved namespaced extension/resource entries; use this when you need a self-contained portable document
json Yes Yes Mapped Score JSON for editing and inspection; not a self-contained carrier for contributor or fidelity payload
musicxml / mxl No No Not part of the current CLI or library surface
midi No No Not part of the current CLI or library surface

The CLI intentionally rejects unsupported formats rather than silently routing them. That includes older pre-GP7 Guitar Pro formats such as .gpx; use Guitar Pro's own conversion/export workflow first if you need to bring those files into Motif.

Testing

Run the full test suite with:

dotnet test

Coverage includes real .gp fixtures, mapping fidelity, write diagnostics, public API shape, and CLI regression tests.

Generated Schemas

Normal builds now generate JSON Schema artifacts automatically into artifacts/schema/. This includes:

  • artifacts/schema/manifest.schema.json
  • artifacts/schema/score.schema.json
  • artifacts/schema/guitarpro.schema.json

You do not need to run the old Temp/schema-export/* helpers during normal development builds.

Documentation

License

MIT

About

.NET library and CLI tool for reading and writing Guitar Pro and other musical transcription files.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages