#music-theory #midi #chord #scale #notes #score #pitch

no-std bin+lib staff

Music theory library with midi, notes, chords, scales, and more

13 releases (breaking)

0.11.0 Sep 18, 2023
0.9.0 Dec 25, 2022
0.8.0 Dec 20, 2022
0.5.0 Nov 22, 2022

#2 in #pitch

43 downloads per month

MIT license

2.5K SLoC


crate documentation


Music theory and score rendering library with midi, notes, chords, scales, and more.


use staff::{midi, Chord, Pitch};

let chord = Chord::from_midi(
    midi!(C, 4),
    [midi!(E, 3), midi!(G, 3), midi!(C, 4)]

assert_eq!(chord.to_string(), "C/E");

let pitches = [Pitch::E, Pitch::G, Pitch::C];


  • render: Enable render module
    • svg: Enable rendering to SVG
  • synth: Enable synth module for
  • serde: Impl Deserialize and Serialize for many crate types


Music theory library with midi, notes, chords, scales, and more

Feature flags

Staff uses a set of feature flags to reduce the amount of compiled code. It is possible to just enable certain features over others. By default, staff does not enable any features but allows one to enable a subset for their use case. Below is a list of the available feature flags. You may also notice above each function, struct and trait there is listed one or more feature flags that are required for that item to be used. If you are new to staff it is recommended that you use the full feature flag which will enable all public APIs. Beware though that this will pull in many extra dependencies that you may not need.

  • full: Enables all features listed below.
  • std: Enables std, otherwise this crate will use #![no_std]
  • parse Enables the staff::parse module.
  • fretboard Enables the staff::fretboard module.
  • render Enables the staff::render module.


Create a C Major (1st inversion) chord and iterate over its notes.

use staff::{midi, Chord, Pitch};

// C/E
let notes = [midi!(E, 3), midi!(G, 3), midi!(C, 4)];
let chord = Chord::from_midi(midi!(C, 4), notes).unwrap();

assert_eq!(chord.to_string(), "C/E");


Create a C Major scale and iterate over its notes.

use staff::{midi, Note, Scale};

// C major
let scale = Scale::major(midi!(C, 4));

    midi!(C, 4),
    midi!(D, 4),
    midi!(E, 4),
    midi!(F, 4),
    midi!(G, 4),
    midi!(A, 4),
    midi!(B, 4),


~54K SLoC