{"id":32289936,"url":"https://github.com/albertms10/music_notes","last_synced_at":"2026-05-01T01:04:12.703Z","repository":{"id":43217113,"uuid":"268659038","full_name":"albertms10/music_notes","owner":"albertms10","description":"Music theory Dart library","archived":false,"fork":false,"pushed_at":"2026-04-27T11:58:12.000Z","size":2054,"stargazers_count":40,"open_issues_count":14,"forks_count":11,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-04-27T13:22:50.169Z","etag":null,"topics":["dart","education","midi","music","music-notation","music-theory"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/music_notes","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/albertms10.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-06-01T23:59:43.000Z","updated_at":"2026-04-23T11:41:16.000Z","dependencies_parsed_at":"2023-11-16T14:29:19.173Z","dependency_job_id":"9a39c014-3f98-4562-ade9-9dbe144ac38e","html_url":"https://github.com/albertms10/music_notes","commit_stats":null,"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/albertms10/music_notes","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/albertms10%2Fmusic_notes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/albertms10%2Fmusic_notes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/albertms10%2Fmusic_notes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/albertms10%2Fmusic_notes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/albertms10","download_url":"https://codeload.github.com/albertms10/music_notes/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/albertms10%2Fmusic_notes/sbom","scorecard":{"id":1237594,"data":{"date":"2025-09-13T09:16:53Z","repo":{"name":"github.com/albertms10/music_notes","commit":"6796d44e3d2ef3360d2d5c1ee6f18cc881b353f7"},"scorecard":{"version":"v5.2.1","commit":"ab2f6e92482462fe66246d9e32f642855a691dc1"},"score":7.6,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/22 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#dangerous-workflow"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#security-policy"}},{"name":"Maintained","score":10,"reason":"30 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":10,"reason":"GitHub workflow tokens follow principle of least privilege","details":["Info: topLevel 'contents' permission set to 'read': .github/workflows/analysis-ci.yaml:15","Info: topLevel permissions set to 'read-all': .github/workflows/scorecards-analysis.yaml:9","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#token-permissions"}},{"name":"Dependency-Update-Tool","score":10,"reason":"update tool detected","details":["Info: detected update tool: Dependabot: .github/dependabot.yaml:1"],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#dependency-update-tool"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":10,"reason":"all dependencies are pinned","details":["Info:   5 out of   5 GitHub-owned GitHubAction dependencies pinned","Info:   3 out of   3 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":5,"reason":"badge detected: Passing","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 29 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#sast"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#branch-protection"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#signed-releases"}},{"name":"Contributors","score":3,"reason":"project has 1 contributing companies or organizations -- score normalized to 3","details":["Info: found contributions from: volcanicinternet"],"documentation":{"short":"Determines if the project has a set of contributors from multiple organizations (e.g., companies).","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#contributors"}},{"name":"CI-Tests","score":10,"reason":"28 out of 28 merged PRs checked by a CI test -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project runs tests before pull requests are merged.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#ci-tests"}}]},"last_synced_at":"2025-09-13T12:08:14.619Z","repository_id":43217113,"created_at":"2025-09-13T12:08:14.619Z","updated_at":"2025-09-13T12:08:14.619Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32481556,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"ssl_error","status_checked_at":"2026-04-30T13:12:06.837Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dart","education","midi","music","music-notation","music-theory"],"created_at":"2025-10-23T02:45:57.857Z","updated_at":"2026-05-01T01:04:12.680Z","avatar_url":"https://github.com/albertms10.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Analysis CI](https://github.com/albertms10/music_notes/workflows/Analysis%20CI/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/albertms10/music_notes/badge.svg?branch=main)](https://coveralls.io/github/albertms10/music_notes?branch=main)\n[![pub package](https://img.shields.io/pub/v/music_notes.svg)](https://pub.dev/packages/music_notes)\n[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/albertms10/music_notes/badge)](https://api.securityscorecards.dev/projects/github.com/albertms10/music_notes)\n[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/8718/badge)](https://www.bestpractices.dev/projects/8718)\n[![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://opensource.org/license/bsd-3-clause/)\n[![style: very good analysis](https://img.shields.io/badge/style-very_good_analysis-B22C89.svg)](https://pub.dev/packages/very_good_analysis)\n\nA comprehensive Dart library for effortlessly working with music theory concepts,\noffering an elegant and beautifully crafted API.\n\n## Features\n\n- Notes, accidentals, and enharmonic operations\n- Intervals, qualities, and circle of fifths\n- Chords, scales, harmonic functions, inversions and retrogrades\n- Keys, key signatures, and modes\n- Frequencies and tuning systems (_work in progress_)\n\n## Usage\n\nImport the package into your Dart code:\n\n```dart\nimport 'package:music_notes/music_notes.dart';\n```\n\nNow, you can use the provided APIs to perform various music theory operations.\nFor more detailed usage instructions and examples, please refer to the\n[API documentation](https://pub.dev/documentation/music_notes/latest/).\n\n### Notes\n\nDefine a `Note` from a `NoteName` (`.a` to `.g`) and an `Accidental`, or using their\nshorthand static constants:\n\n```dart\nconst Note(.e, .flat); // E♭\nNote.c; // C\nNote.d; // D\nNote.f; // F\n```\n\n`NoteName`s can be obtained from semitones or ordinal:\n\n```dart\nNoteName.fromSemitones(2); // NoteName.d\nNoteName.fromSemitones(9); // NoteName.a\n\nNoteName.fromOrdinal(3); // NoteName.e\nNoteName.fromOrdinal(7); // NoteName.b\n```\n\nAlter a `Note` with `sharp` or `flat`:\n\n```dart\nNote.c.sharp; // C♯\nNote.d.flat; // D♭\nNote.g.flat.flat; // G𝄫\nNote.f.sharp.sharp.sharp; // F𝄪♯\n```\n\nAnd position them in the octave, resulting in `Pitch`es:\n\n```dart\nNote.f.inOctave(4); // F4\nNote.b.flat.inOctave(5); // B♭5\n```\n\nOr parse them in both scientific and Helmholtz notations:\n\n```dart\nNoteName.parse('b'); // NoteName.b\nNote.parse('a#'); // A♯\nPitch.parse(\"g''\"); // G5\nPitch.parse('Eb3'); // E♭3\n```\n\nGet their difference in semitones:\n\n```dart\nNoteName.c.difference(.e); // 4\nNoteName.a.difference(.e); // -5\nNoteName.a.positiveDifference(.e); // 7\n\nNote.c.difference(.e.flat); // 3\nPitch.parse('C').difference(.parse(\"c''''\")); // 60\n```\n\nTranspose them:\n\n```dart\nNote.g.flat.transposeBy(-Interval.m3); // E♭\nNote.b.inOctave(3).transposeBy(.P5); // F♯4\n```\n\nRespell them by any criteria:\n\n```dart\nNote.c.sharp.respellByNoteName(.d); // D♭\nNote.e.flat.respellByAccidental(.sharp); // D♯\nNote.g.flat.inOctave(3).respellByOrdinalDistance(-1); // F♯3\n\nNote.g.sharp.respelledUpwards; // A♭\nNote.a.flat.respelledDownwards; // G♯\nNote.b.sharp.inOctave(4).respelledSimple; // C5\n```\n\nCompare two `Pitch`es based on their semitones:\n\n```dart\nNote.c.inOctave(4) \u003c Note.c.inOctave(5); // true\nNote.d.inOctave(3) \u003e Note.f.inOctave(4); // false\nNote.a.flat.inOctave(5) \u003e= Note.g.sharp.inOctave(5); // true\n```\n\nKnow whether two `Note`s or `Pitch`es are enharmonically equivalent:\n\n```dart\nNote.f.sharp.isEnharmonicWith(Note.g.flat); // true\nNote.c.inOctave(4).isEnharmonicWith(Note.b.sharp.inOctave(3)); // true\nNote.a.isEnharmonicWith(Note.b.flat); // false\n```\n\nRepresent them as [`PitchClass`es](https://en.wikipedia.org/wiki/Pitch_class):\n\n```dart\nNote.d.flat.toClass(); // {C♯|D♭}\nNote.a.inOctave(4).toClass(); // {A}\n```\n\nPerform [`PitchClass` multiplications (modulo 12)](\u003chttps://en.wikipedia.org/wiki/Multiplication_(music)#Pitch-class_multiplication_modulo_12\u003e):\n\n```dart\nPitchClass.cSharp * 7; // {G}\nPitchClass.d * 7; // {D}\n// observe one semitone upwards results in ascending fifths G -\u003e D.\n\nPitchClass.cSharp * 5; // {F}\nPitchClass.d * 5; // {A♯|B♭}\n// observe one semitone upwards results in ascending fourths F -\u003e B-flat.\n```\n\nRepresent them using any notation formatter:\n\n```dart\nNote.d.flat\n  ..format() // D♭\n  ..format(const GermanNoteNotation()) // Des\n  ..format(const RomanceNoteNotation.symbol()); // Re♭\n\nNote.b.flat.inOctave(-1).format(); // B♭-1\nNote.c.inOctave(6).format(HelmholtzPitchNotation.english); // c‴\n\nPitchClass.c.format(); // {C}\nPitchClass.dSharp.format(); // {D♯|E♭}\n\nPitchClass.f.format(const IntegerPitchClassNotation()); // 5\nPitchClass.aSharp.format(const IntegerPitchClassNotation()); // t\n```\n\n### Intervals\n\nCreate an `Interval`:\n\n```dart\nconst Interval.imperfect(.tenth, .major); // M10\nInterval.d5; // d5\nSize.sixth.augmented; // A6\nSize.eleventh.simple.perfect; // P4\n```\n\nOr parse it from a string:\n\n```dart\nInterval.parse('m3'); // m3\nInterval.parse('P-5'); // P-5\nInterval.parse('AA6'); // AA6\n```\n\nTurn it descending:\n\n```dart\n-Interval.m7; // m-7\n(-Interval.P5).direction; // -1\nInterval.M3.descending; // M-3\n(-Interval.P4).ascending; // P4\n(-Interval.P4).withDescending(false); // P4\n```\n\nPerform common interval operations:\n\n```dart\nInterval.m3.inversion; // M6\nInterval.A4.inversion; // d5\nInterval.m9.inversion; // M7\n\nInterval.m9.simple; // m2\nInterval.P11.simple; // P4\n(-Interval.M3).simple; // M-3\n\nInterval.P5.isCompound; // false\nInterval.M9.isCompound; // true\n(-Interval.P11).isCompound; // true\n\nInterval.P5.isDissonant; // false\nInterval.d5.isDissonant; // true\nInterval.M7.isDissonant; // true\n```\n\nRespell an `Interval` by size:\n\n```dart\nInterval.A4.respellBySize(.fifth); // d5\nInterval.d3.respellBySize(.second); // M2\n```\n\nCalculate the `Interval` between two notes:\n\n```dart\nNote.c.interval(.g); // P5\nNote.d.interval(.f.sharp).inversion; // m6\n\nNoteName.d.intervalSize(.f); // 3\nNoteName.a.intervalSize(.e); // 5\n```\n\nKnow the intervallic distance between two notes:\n\n```dart\nInterval.P5.circleDistance\u003cNote\u003e(from: .c, to: .d);\n// (2, notes: [C, G, D])\nInterval.P4.circleDistance\u003cNote\u003e(from: .b.flat, to: .d);\n// (-4, notes: [B♭, F, D, G, D])\n```\n\nAnd even explore the circle of fifths or any circle of intervals\nup to a distance:\n\n```dart\nInterval.P5.circleFrom(Note.c).take(13).toList();\n// [C, G, D, A, E, B, F♯, C♯, G♯, D♯, A♯, E♯, B♯]\nNote.c.circleOfFifths(distance: 3); // [E♭, B♭, F, C, G, D, A]\nNote.c.splitCircleOfFifths.down.take(6).toList();\n// [F, B♭, E♭, A♭, D♭, G♭]\nNote.c.splitCircleOfFifths.up.take(8).toList();\n// [G, D, A, E, B, F♯, C♯, G♯]\n\nNote.d.circleOfFifthsDistance; // 2\nNote.a.flat.circleOfFifthsDistance; // -4\n\nNote.c.fifthsDistanceWith(.e.flat); // -3\nNote.b.fifthsDistanceWith(.f.sharp); // 1\n```\n\nKnow whether two `Interval`s are enharmonically equivalent:\n\n```dart\nInterval.M3.isEnharmonicWith(Interval.d4); // true\nInterval.A4.isEnharmonicWith(Interval.d5); // true\nInterval.P1.isEnharmonicWith(Interval.m2); // false\n```\n\nRepresent them as [`IntervalClass`es](https://en.wikipedia.org/wiki/Interval_class):\n\n```dart\nInterval.M2.toClass(); // {M2|d3}\nInterval.m6.toClass(); // {M3|d4}\nInterval.P8.toClass(); // {P1}\n```\n\nCompare two `Interval`s based on their semitones:\n\n```dart\nInterval.m3 \u003c .P5; // true\nInterval.m7 \u003c= .P5; // false\n-Interval.P4 \u003e .M3; // true\n```\n\nAdd, subtract and multiply `Interval`s and `IntervalClass`es:\n\n```dart\nInterval.m2 + .M2; // m3\nInterval.M2 + .P4; // P5\n\nIntervalClass.tritone + .M2; // {M3|d4}\nIntervalClass.M3 + .P4; // {m3}\nIntervalClass.P4 - .m3; // {M2|d3}\n\nIntervalClass.P4 * -1; // {P4}\nIntervalClass.M2 * 0; // {P1}\nIntervalClass.m3 * 2; // {A4|d5}\n```\n\nRepresent them as a string:\n\n```dart\nInterval.m2.format(); // m2\nInterval.A6.format(); // A6\n\nIntervalClass.M2.format(); // {M2|d3}\nIntervalClass.P4.format(); // {P4}\nIntervalClass.tritone.format(); // {A4|d5}\n```\n\n### Keys\n\nCreate a `Key` or get it from a given `Note`:\n\n```dart\nconst Key(.e, .minor); // E minor\nNote.a.flat.major; // A♭ major\n```\n\nKnow its `KeySignature`:\n\n```dart\nNote.d.major.signature; // {D major, B minor} +2 fifths (F♯ C♯)\nNote.e.flat.minor.signature;\n// {G♭ major, E♭ minor} −6 fifths (B♭ E♭ A♭ D♭ G♭ C♭)\n```\n\nWhether it is theoretical:\n\n```dart\nNote.e.major.isTheoretical; // false\nNote.a.flat.minor.isTheoretical; // true\n```\n\nAnd its relative and parallel `Key`s:\n\n```dart\nNote.d.major.relative; // B minor\nNote.c.minor.relative; // E♭ major\n\nNote.f.minor.parallel; // F major\nNote.c.sharp.major.parallel; // C♯ minor\n```\n\nRepresent it using any notation formatter:\n\n```dart\nNote.d.flat.major.format(); // D♭ major\nNote.c.major.format(const RomanceKeyNotation()); // Do maggiore\nNote.e.flat.minor.format(const GermanKeyNotation()); // es-Moll\n```\n\n### Key signatures\n\nCreate a `KeySignature`:\n\n```dart\nKeySignature.fromDistance(4); // {E major, C♯ minor} +4 fifths (F♯ C♯ G♯ D♯)\nKeySignature([.b.flat, .e.flat]); // {B♭ major, G minor} −2 fifths (B♭ E♭)\nKeySignature([.g.sharp, .a.sharp]); // Non-canonical (G♯ A♯)\n```\n\nIncrement them by sharps or flats:\n\n```dart\nKeySignature.fromDistance(-4).incrementBy(-1);\n// {E♭ major, C minor} −3 fifths (B♭ E♭ A♭)\nKeySignature([.f.sharp, .c.sharp]).incrementBy(3);\n// {B major, G♯ minor} +5 fifths (F♯ C♯ G♯ D♯ A♯)\n```\n\nAnd know its `Key`s:\n\n```dart\nKeySignature([.f.sharp]).keys[TonalMode.major]; // G major\nKeySignature.empty.keys[TonalMode.minor]; // A minor\n```\n\nNon-canonical key signatures are also supported, although they\nreturn `null` when asked about their fifths distance or keys:\n\n```dart\nKeySignature([.a.flat])\n  ..isCanonical // false\n  ..distance // null\n  ..keys; // \u003cTonalMode, Key\u003e{}\n```\n\n### Modes\n\nGet each `Mode`’s `ScalePattern`:\n\n```dart\nTonalMode.minor.scale; // ScalePattern.minor\nModalMode.locrian.scale; // ScalePattern.locrian\n```\n\nTheir [Dorian Brightness Quotient]:\n\n```dart\nModalMode.lydian.brightness; // 3\nModalMode.dorian.brightness; // 0\nModalMode.aeolian.brightness; // -1\n```\n\nOr its mirrored version:\n\n```dart\nModalMode.ionian.mirrored; // ModalMode.phrygian\nModalMode.aeolian.mirrored; // ModalMode.mixolydian\n```\n\n### Scales\n\nCreate a `Scale` from a `ScalePattern`:\n\n```dart\nScalePattern.lydian.on(Note.d); // D Lydian (D E F♯ G♯ A B C♯ D)\nScalePattern.wholeTone.on(Note.f); // F Whole-tone (F G A B C♯ D♯ F)\nScalePattern.majorPentatonic.on(Note.g.flat);\n// G♭ Major pentatonic (G♭ A♭ B♭ D♭ E♭ G♭)\n```\n\nOr get it from a `Key`:\n\n```dart\nNote.a.flat.major.scale; // A♭ Major (ionian) (A♭ B♭ C D♭ E♭ F G A♭)\nNote.d.minor.scale; // D Natural minor (aeolian) (D E F G A B♭ C D)\n```\n\nEven experiment with any `ScaleDegree` or `HarmonicFunction`:\n\n```dart\nScalePattern.lydian.on(Note.e).degree(.iv); // A♯\nNote.c.major.scale.functionChord(\n  HarmonicFunction.dominantV / .dominantV,\n); // D\n```\n\nRearrange any collection of `Note`s, `Pitch`es or `PitchClass`es\nas `inversion` or `retrograde`:\n\n```dart\n\u003cNote\u003e{.b, .a.sharp, .d}.inversion.toSet(); // {B, C, G♯}\n\u003cPitchClass\u003e{.dSharp, .g, .fSharp}.retrograde.toSet();\n// {{F♯|G♭}, {G}, {D♯|E♭}}\n```\n\nOr know its numeric representation:\n\n```dart\n\u003cPitchClass\u003e{.b, .aSharp, .d, .e}\n  ..numericRepresentation()\n      .toSet() // {0, 11, 3, 5}\n  ..numericRepresentation(reference: .d)\n      .toSet() // {9, 8, 0, 2}\n  ..deltaNumericRepresentation.toList(); // [0, -1, 4, 2]\n```\n\n### Chords\n\nCreate a `Chord` from a series of `Note`s or a `ChordPattern`:\n\n```dart\nChord\u003cNote\u003e([.a, .c.sharp, .e]); // A\nChordPattern.augmentedTriad.add11().add13().on(Note.d.sharp); // D♯+11 13\n```\n\nOr build it on top of a `Note`:\n\n```dart\nNote.f.minorTriad.add7().add9(.minor);\n// F-7 ♭9\nNote.e.flat.diminishedTriad.add7().transposeBy(.m2);\n// F♭ø\n```\n\nOr modify its root triad:\n\n```dart\nNote.g.minorTriad.major; // G\nNote.f.sharp.majorTriad.add9().diminished; // F♯dim\n```\n\n### Frequencies\n\nGet the `Frequency` of a `Pitch`:\n\n```dart\nNote.a.inOctave(4).frequency(); // 440\nNote.a.inOctave(4).frequency(temperature: const Celsius(18));\n// 438.4619866006409\n```\n\nCreate a `TuningFork` from a `Pitch` and a reference `Frequency`,\nor using its shorthand static constants:\n\n```dart\nNote.a.inOctave(4).at(const Frequency(438)); // A438\nTuningFork.a440; // A440\nTuningFork.c256; // C256\n```\n\nAnd use it in a `TuningSystem`:\n\n```dart\nNote.b.flat\n    .inOctave(4)\n    .frequency(\n      tuningSystem: const EqualTemperament.edo12(fork: .c256),\n    ); // 456.1401436878537\n```\n\nGet the `Frequency` at a given temperature:\n\n```dart\nconst Frequency(440).at(const Celsius(18)); // 438.4619866006409\nconst Frequency(440).at(const Celsius(24)); // 443.07602679871826\n```\n\nGet the closest `Pitch` from a given `Frequency`:\n\n```dart\nconst Frequency(432).closestPitch(); // A4−32\nconst Frequency(314).closestPitch(); // E♭4+16\nconst Frequency(440).closestPitch(temperature: const Celsius(24)); // A4−12\n```\n\nAnd combining both `frequency` and `closestPitch` methods,\nthe harmonic series of a given `Pitch`:\n\n```dart\nNote.c.inOctave(1).harmonics().take(16).toSet();\n// {C1±0, C2±0, G2+2, C3±0, E3−14, G3+2, A♯3−31, C4±0,\n// D4+4, E4−14, F♯4−49, G4+2, A♭4+41, A♯4−31, B4−12, C5±0}\n```\n\nCreate a `ClosestPitch` by adding or subtracting `Cent`s to a `Pitch`:\n\n```dart\nNote.f.sharp.inOctave(4) + const Cent(16); // F♯4+16\nNote.g.flat.inOctave(5) - const Cent(8.236); // G♭5−8\n```\n\nOr parse a `ClosestPitch` from a string:\n\n```dart\nClosestPitch.parse('A4'); // A4±0\nClosestPitch.parse('E♭3-28'); // E♭3−28\nClosestPitch.parse('A4+12.6').format(\n  const StandardClosestPitchNotation(fractionDigits: 1),\n); // A4+12.6\n```\n\n### In a nutshell\n\n```dart\nScalePattern\n    .lydian // Lydian (M2 M2 M2 m2 M2 M2 m2)\n    .on(Note.parse('a')) // A Lydian (A B C♯ D♯ E F♯ G♯ A)\n    .transposeBy(.M2) // B Lydian (B C♯ D♯ E♯ F♯ G♯ A♯ B)\n    .degree(.iii) // D♯\n    .respelledUpwards // E♭\n    .major // E♭ major\n    .relative // C minor\n    .scale // C Natural minor (aeolian) (C D E♭ F G A♭ B♭ C)\n    .degreeChord(.v) // G-\n    .add9(); // G-9\n```\n\n## Similar projects in other languages\n\n- `mingus` [Python](https://github.com/bspaans/python-mingus)\n- `modest` [Lua](https://github.com/esbudylin/modest)\n- `music21` [Python](https://github.com/cuthbertLab/music21)\n- `sharp11` [JavaScript](https://github.com/jsrmath/sharp11)\n- `teoria` [JavaScript](https://github.com/saebekassebil/teoria)\n- `tonal` [JavaScript](https://github.com/tonaljs/tonal)\n- `tonic` [JavaScript](https://github.com/osteele/tonic.ts) | [Dart](https://github.com/osteele/dart-tonic)\n\n## Contributing\n\nContributions are welcome! If you encounter any issues or have suggestions for improvements, please feel free to open an issue or submit a pull request on the [GitHub repository](https://github.com/albertms10/music_notes/pulls).\n\n## Star History\n\n\u003ca href=\"https://star-history.com/#albertms10/music_notes\u0026Date\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/svg?repos=albertms10/music_notes\u0026type=Date\u0026theme=dark\" /\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/svg?repos=albertms10/music_notes\u0026type=Date\" /\u003e\n    \u003cimg alt=\"Star History Chart\" src=\"https://api.star-history.com/svg?repos=albertms10/music_notes\u0026type=Date\" /\u003e\n  \u003c/picture\u003e\n\u003c/a\u003e\n\n## License\n\nThis package is released under the [BSD-3-Clause License](LICENSE).\n\n[Dorian Brightness Quotient]: https://mynewmicrophone.com/dorian-brightness-quotient\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falbertms10%2Fmusic_notes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falbertms10%2Fmusic_notes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falbertms10%2Fmusic_notes/lists"}