omr library

Reusable optical-music-recognition API — the CrispEmbed FFI engine plus the pure-Dart parsers, in one import.

This is the OMR pipeline factored out of the crisp_notation omr command so any Dart program can drive it: the CLI and Flutter desktop (macOS / Windows / Linux), i.e. anywhere dart:ffi is available. It does not work on the web (Dart/Flutter web has no dart:ffi, and CrispEmbed's WASM build does not expose the OMR engines — that would be an upstream change).

Typical use:

import 'package:crisp_notation_cli/omr.dart';

final modelPath = await resolveOmrModel('smt-grandstaff'); // download+cache
final engine = CrispEmbedOmrEngine.load(modelPath);       // needs libcrispembed
try {
  final tokens = engine.recognizeSync(decodeOmrImage('scan.png'));
  final score = switch (omrDialectOf(tokens)) {
    OmrDialect.bekern => bekernToGrandStaff(tokens), // → GrandStaff
    OmrDialect.semantic => scoreFromSemantic(tokens), // → Score
    OmrDialect.lilyNotes => scoreFromLilyNotes(tokens), // → Score
  };
  // … render / export `score` with crisp_notation_core.
} finally {
  engine.dispose();
}

For a full-page scan, split it first with segmentStaffSystems and recognise each crop. Requires libcrispembed at runtime (see CrispEmbedOmrEngine.load).

Classes

CrispEmbedOmrEngine
An OmrEngine backed by CrispEmbed's SMT model through FFI.
OmrEngine
An optical-music-recognition engine: a staff image → bekern tokens.
OmrImage
A pixel buffer for OmrEngine.recognize: row-major width×height, with channels bytes per pixel (1 = gray, 3 = RGB, 4 = RGBA). The engine applies its own grayscale/invert/resize preprocessing.

Enums

OmrDialect
Which OMR token dialect an engine returned.

Constants

omrModelRegistry → const Map<String, (String, String)>
Known OMR models by short name → (Hugging Face repo, GGUF file). Used by resolveOmrModel to auto-download a model when a name (not a path) is given.

Functions

bekernToGrandStaff(String bekern) → GrandStaff
bekern tokens → two-staff GrandStaff.
bekernToKern(String bekern) String
Converts a space-joined bekern token sequence (as returned by the SMT OMR engine) into a Humdrum **kern document.
bekernToScore(String bekern) → Score
bekern tokens → single-staff Score (first spine).
bekernToStaffSystem(String bekern) → StaffSystem
bekern tokens → StaffSystem (one staff per spine).
decodeImageFile(String path) → Image
Decodes a PNG/JPEG/BMP image file to an img.Image. Throws OmrEngineException if it cannot be decoded.
decodeOmrImage(String path) OmrImage
Decodes a PNG/JPEG/BMP image file into an OmrImage (RGBA) for recognition.
omrDialectOf(String tokens) OmrDialect
Sniffs which dialect tokens are, so a caller can pick the right parser without knowing which engine (SMT / TrOMR / Flova) produced them: semantic uses note-/clef-/…- prefixes; bekern uses <t>/<s>/<b>/**kern; Flova is bare LilyPond notes.
omrImageOf(Image image) OmrImage
Converts a decoded image to an RGBA OmrImage for recognition.
resolveOmrModel(String model, {String? cacheDir, void onStatus(String)?}) Future<String>
Resolves model to a local GGUF path: an existing file path is returned as-is; a registered name (see omrModelRegistry) is downloaded from Hugging Face to cacheDir (default $XDG_CACHE_HOME/crisp_notation/omr) if not already cached, and the cached path returned. onStatus receives progress lines.
scoreFromLilyNotes(String notes) → Score
Parses a LilyPond simple-notes string (Flova OMR output) into a single-staff Score. Throws FormatException if no notes/rests are found.
scoreFromSemantic(String semantic) → Score
Parses a TrOMR semantic token stream into a single-staff Score.
segmentStaffSystems(Image image, {double inkFraction = 0.04, int minGapRows = 12, int minBandRows = 16, int padRows = 10}) List<Image>
Splits a full-page staff image into individual staff-system crops by horizontal-projection band detection: a row is "ink" if at least inkFraction of its pixels are dark; maximal ink bands separated by ≥ minGapRows blank rows become separate systems (bands shorter than minBandRows are dropped as noise), each padded by padRows. Returns the whole image (a single element) when it can't find a clean multi-system split — so single-system input is unchanged.

Exceptions / Errors

OmrEngineException
Raised when the OMR engine cannot load, initialise, or recognise.