flutter_notemus 2.2.1 copy "flutter_notemus: ^2.2.1" to clipboard
flutter_notemus: ^2.2.1 copied to clipboard

Professional music notation rendering for Flutter. SMuFL-compliant with 2932 Bravura glyphs, beams, dynamics, articulations, and JSON import/export.

Flutter Notemus #

pub.dev Flutter Dart SMuFL License

Professional music notation rendering for Flutter with SMuFL-compliant engraving, Bravura glyph support, and a first-party notation-to-MIDI pipeline.



Table of Contents #


Current Status #

  • Current package release target: 2.2.1
  • Previous pub.dev baseline before the new generation: 0.1.0
  • Core notation rendering is production-ready.
  • MIDI mapping and .mid export are available in the package.
  • Android native audio backend is active; other native targets are configured and tracked as pending.

Open Pending Work #

All pending work is tracked as GitHub issues:


Highlights #

Core notation #

  • Notes from whole through 1024th durations
  • Rests for all supported durations
  • Accidentals (natural, sharp, flat, double sharp, double flat)
  • Automatic ledger lines

Clefs #

  • Treble, bass, alto, tenor, percussion, tablature
  • Octave-transposing clef variants (8va, 8vb, 15ma, 15mb)

Rhythm and layout #

  • Proportional rhythmic spacing
  • Auto and manual beaming
  • Tuplet support
  • Collision-aware layout
  • Multi-measure and multi-system rendering

Symbols and expression #

  • Dynamics and hairpins
  • Articulations
  • Ornaments
  • Tempo marks and text
  • Ties and slurs
  • Volta brackets, repeat symbols, and structural barlines
  • Octave markings

Multi-staff and polyphony #

  • Multiple voices in a single staff (MultiVoiceMeasure)
  • Multi-staff score support (Score, StaffGroup)
  • Grand staff scenarios (piano)
  • SATB-style aligned staff rendering

Import and interoperability #

  • JSON parser
  • MusicXML parser (score-partwise and score-timewise)
  • MEI parser
  • Unified normalization to the same internal model

MIDI pipeline #

  • Notation-to-MIDI mapping from Staff and Score
  • Repeat and volta expansion for playback timeline
  • Tuplet/polyphony/tie-aware event generation
  • Metronome track generation
  • Standard MIDI file export (MidiFileWriter)

Installation #

Add dependency to your pubspec.yaml:

dependencies:
  flutter_notemus: ^2.2.1

Install packages:

flutter pub get

Required Initialization #

Load Bravura and SMuFL metadata before rendering any score:

import 'package:flutter/services.dart';
import 'package:flutter_notemus/flutter_notemus.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final loader = FontLoader('Bravura');
  loader.addFont(
    rootBundle.load('packages/flutter_notemus/assets/smufl/Bravura.otf'),
  );
  await loader.load();

  await SmuflMetadata().load();

  runApp(const MyApp());
}

Quick Start #

import 'package:flutter/material.dart';
import 'package:flutter_notemus/flutter_notemus.dart';

class SimpleScorePage extends StatelessWidget {
  const SimpleScorePage({super.key});

  @override
  Widget build(BuildContext context) {
    final staff = Staff();
    final measure = Measure();

    measure.add(Clef(clefType: ClefType.treble));
    measure.add(TimeSignature(numerator: 4, denominator: 4));
    measure.add(Note(
      pitch: const Pitch(step: 'C', octave: 5),
      duration: const Duration(DurationType.quarter),
    ));
    measure.add(Note(
      pitch: const Pitch(step: 'E', octave: 5),
      duration: const Duration(DurationType.quarter),
    ));
    measure.add(Note(
      pitch: const Pitch(step: 'G', octave: 5),
      duration: const Duration(DurationType.quarter),
    ));
    measure.add(Note(
      pitch: const Pitch(step: 'C', octave: 6),
      duration: const Duration(DurationType.quarter),
    ));

    staff.add(measure);

    return Scaffold(
      body: SizedBox(
        height: 180,
        child: MusicScore(staff: staff),
      ),
    );
  }
}

API Guide #

MusicScore Widget #

MusicScore(
  staff: staff,
  staffSpace: 12.0,
  theme: const MusicScoreTheme(),
)

Pitch and Notes #

Note(
  pitch: const Pitch(step: 'G', octave: 4),
  duration: const Duration(DurationType.quarter),
  articulations: [ArticulationType.staccato],
  tie: TieType.start,
  slur: SlurType.start,
  beam: BeamType.start,
)

Accidentals are encoded directly in Pitch:

const Pitch(step: 'F', octave: 5, alter: 1.0);   // sharp
const Pitch(step: 'B', octave: 4, alter: -1.0);  // flat
const Pitch(step: 'C', octave: 5, alter: 2.0);   // double sharp
const Pitch(step: 'D', octave: 4, alter: -2.0);  // double flat

Durations #

const Duration(DurationType.whole);
const Duration(DurationType.half);
const Duration(DurationType.quarter);
const Duration(DurationType.eighth);
const Duration(DurationType.sixteenth);
const Duration(DurationType.thirtySecond);
const Duration(DurationType.sixtyFourth);
const Duration(DurationType.oneHundredTwentyEighth);

Dotted durations:

const Duration(DurationType.quarter, dots: 1);
const Duration(DurationType.half, dots: 2);

Rests #

Rest(duration: const Duration(DurationType.whole));
Rest(duration: const Duration(DurationType.half));
Rest(duration: const Duration(DurationType.eighth));

Measures and Staff #

final staff = Staff();
final measure = Measure();

measure.add(Clef(clefType: ClefType.treble));
measure.add(TimeSignature(numerator: 3, denominator: 4));
measure.add(Note(
  pitch: const Pitch(step: 'C', octave: 5),
  duration: const Duration(DurationType.quarter),
));

staff.add(measure);

Clefs #

Clef(clefType: ClefType.treble);
Clef(clefType: ClefType.treble8vb);
Clef(clefType: ClefType.bass);
Clef(clefType: ClefType.alto);
Clef(clefType: ClefType.tenor);
Clef(clefType: ClefType.percussion);
Clef(clefType: ClefType.tab6);

Key Signatures #

KeySignature(0);   // C major / A minor
KeySignature(2);   // D major (2 sharps)
KeySignature(-3);  // E-flat major (3 flats)

Time Signatures #

TimeSignature(numerator: 4, denominator: 4);
TimeSignature(numerator: 3, denominator: 4);
TimeSignature(numerator: 6, denominator: 8);

Barlines #

Barline(type: BarlineType.single);
Barline(type: BarlineType.double);
Barline(type: BarlineType.final_);
Barline(type: BarlineType.repeatForward);
Barline(type: BarlineType.repeatBackward);
Barline(type: BarlineType.repeatBoth);

Chords #

Chord(
  notes: [
    Note(pitch: const Pitch(step: 'C', octave: 4), duration: const Duration(DurationType.half)),
    Note(pitch: const Pitch(step: 'E', octave: 4), duration: const Duration(DurationType.half)),
    Note(pitch: const Pitch(step: 'G', octave: 4), duration: const Duration(DurationType.half)),
  ],
  duration: const Duration(DurationType.half),
);

Ties and Slurs #

Note(
  pitch: const Pitch(step: 'C', octave: 5),
  duration: const Duration(DurationType.half),
  tie: TieType.start,
);

Note(
  pitch: const Pitch(step: 'D', octave: 5),
  duration: const Duration(DurationType.quarter),
  slur: SlurType.start,
);

Articulations #

Note(
  pitch: const Pitch(step: 'G', octave: 4),
  duration: const Duration(DurationType.quarter),
  articulations: [
    ArticulationType.staccato,
    ArticulationType.accent,
    ArticulationType.tenuto,
    ArticulationType.marcato,
  ],
);

Dynamics #

Dynamic(type: DynamicType.piano);
Dynamic(type: DynamicType.mezzoForte);
Dynamic(type: DynamicType.forte);
Dynamic(type: DynamicType.crescendo);
Dynamic(type: DynamicType.diminuendo);

Ornaments #

Ornament(type: OrnamentType.trill);
Ornament(type: OrnamentType.mordent);
Ornament(type: OrnamentType.turn);
Ornament(type: OrnamentType.fermata);

Tempo Marks #

TempoMark(
  bpm: 120,
  beatUnit: DurationType.quarter,
  text: 'Allegro',
);

Grace Notes #

GraceNote(
  pitch: const Pitch(step: 'D', octave: 5),
  type: GraceNoteType.acciaccatura,
);

Tuplets #

Tuplet(
  actualNotes: 3,
  normalNotes: 2,
  elements: [
    Note(pitch: const Pitch(step: 'C', octave: 5), duration: const Duration(DurationType.eighth)),
    Note(pitch: const Pitch(step: 'D', octave: 5), duration: const Duration(DurationType.eighth)),
    Note(pitch: const Pitch(step: 'E', octave: 5), duration: const Duration(DurationType.eighth)),
  ],
);

Beams #

Note(
  pitch: const Pitch(step: 'E', octave: 5),
  duration: const Duration(DurationType.eighth),
  beam: BeamType.start,
);

Octave Markings #

OctaveMark(type: OctaveType.ottava);
OctaveMark(type: OctaveType.ottavaBassa);
OctaveMark(type: OctaveType.quindicesima);
OctaveMark(type: OctaveType.quindicesimaBassa);

Volta Brackets #

VoltaBracket(number: 1, length: 220);
VoltaBracket(number: 2, length: 180, hasOpenEnd: true);

Polyphony and Multi-Voice #

final measure = MultiVoiceMeasure();

final voice1 = Voice.voice1();
voice1.add(Clef(clefType: ClefType.treble));
voice1.add(TimeSignature(numerator: 4, denominator: 4));
voice1.add(Note(
  pitch: const Pitch(step: 'E', octave: 5),
  duration: const Duration(DurationType.quarter),
));

final voice2 = Voice.voice2();
voice2.add(Note(
  pitch: const Pitch(step: 'C', octave: 4),
  duration: const Duration(DurationType.half),
));

measure.addVoice(voice1);
measure.addVoice(voice2);

Repeats #

Barline(type: BarlineType.repeatForward);
Barline(type: BarlineType.repeatBackward);
Barline(type: BarlineType.repeatBoth);

Playing Techniques #

PlayingTechnique(type: TechniqueType.pizzicato);
PlayingTechnique(type: TechniqueType.colLegno);
PlayingTechnique(type: TechniqueType.sulTasto);
PlayingTechnique(type: TechniqueType.sulPonticello);

Breath and Caesura #

Breath();
Breath(type: BreathType.caesura);
Breath(type: BreathType.shortBreath);

Import from JSON, MusicXML, and MEI #

final jsonStaff = JsonMusicParser.parseStaff(jsonString);
final musicXmlStaff = MusicXMLParser.parseMusicXML(musicXmlString);
final meiStaff = MEIParser.parseMEI(meiString);

final autoDetected = NotationParser.parseStaff(sourceString);

MIDI Mapping and Export #

import 'dart:io';
import 'package:flutter_notemus/midi.dart';

Future<void> exportMidi(Staff staff) async {
  final sequence = MidiMapper.fromStaff(
    staff,
    options: const MidiGenerationOptions(
      ticksPerQuarter: 960,
      defaultBpm: 120,
      includeMetronome: true,
    ),
  );

  final bytes = MidiFileWriter.write(sequence);
  await File('score.mid').writeAsBytes(bytes, flush: true);
}

Native integration APIs:

  • MidiNativeAudioBackend
  • MethodChannelMidiNativeAudioBackend
  • MidiNativeSequenceBridge

Themes and Styling #

MusicScore(
  staff: staff,
  theme: const MusicScoreTheme(
    staffLineColor: Colors.black,
    noteheadColor: Colors.black,
    stemColor: Colors.black,
    clefColor: Colors.black,
    barlineColor: Colors.black,
    dynamicColor: Colors.black,
    tieColor: Colors.black,
    slurColor: Colors.black,
    textColor: Colors.black,
  ),
)

Reference JSON Format #

{
  "measures": [
    {
      "clef": "treble",
      "timeSignature": { "numerator": 4, "denominator": 4 },
      "keySignature": 0,
      "elements": [
        { "type": "note", "step": "C", "octave": 5, "duration": "quarter" },
        { "type": "note", "step": "E", "octave": 5, "duration": "quarter" },
        { "type": "note", "step": "G", "octave": 5, "duration": "quarter" },
        { "type": "rest", "duration": "quarter" }
      ]
    }
  ]
}

Architecture #

flutter_notemus/
├── lib/
│   ├── flutter_notemus.dart        # Public entry point
│   ├── midi.dart                   # Public MIDI entry point
│   ├── core/                       # Music model
│   └── src/
│       ├── midi/                   # MIDI mapping/export/native bridge
│       ├── layout/                 # Layout and spacing
│       ├── rendering/              # Renderers and positioning
│       ├── smufl/                  # Metadata and glyph references
│       ├── parsers/                # JSON, MusicXML, MEI parsers
│       └── theme/                  # Theme and style system
├── assets/smufl/                   # Bravura + metadata
├── android/ios/macos/linux/windows # Plugin/native targets
└── example/                        # Demo application

Rendering flow:

Staff/Score -> LayoutEngine -> PositionedElements -> StaffRenderer -> Canvas

Development Checklist #

Typical local validation:

dart analyze
flutter test
flutter pub publish --dry-run

License #

  • Project code: Apache License 2.0 (LICENSE)
  • Third-party assets and references: THIRD_PARTY_LICENSES.md
2
likes
160
points
35
downloads
screenshot

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Professional music notation rendering for Flutter. SMuFL-compliant with 2932 Bravura glyphs, beams, dynamics, articulations, and JSON import/export.

Homepage
Repository (GitHub)
View/report issues

Topics

#flutter #music #notation #rendering #smufl

License

Apache-2.0 (license)

Dependencies

collection, flutter, flutter_web_plugins, pdf, printing, xml

More

Packages that depend on flutter_notemus

Packages that implement flutter_notemus