패키지, 저장소 및 앱 카테고리 검색

패키지 상세v0.28.0

music_notes

음악 이론 개념을 쉽게 다룰 수 있도록 도와주는 포괄적인 Dart 라이브러리입니다.

AndroidiOSWebmacOSWindowsLinux
30일 다운로드
895
좋아요
36
Pub 점수
160

패키지 설치

flutter pub add music_notes

패키지 개요

공개 정보를 바탕으로 생성한 선택 가이드입니다.

음악 이론 개념을 다루는 것을 간소화하기 위해 설계된 포괄적인 Dart 라이브러리입니다. 음표, 스케일, 코드, 음정 및 키 서명을 다루는 도구를 직관적인 API로 제공합니다. 음악 애플리케이션, 교육 도구 또는 오디오 처리 기능을 개발하는 개발자에게 이상적입니다. Android, iOS, Web, macOS, Windows, Linux에서 크로스플랫폼 개발을 지원합니다. 복잡한 음악적 관계를 사용하기 쉬운 함수로 추상화하여 정확하고 효율적인 음악 관련 계산을 가능하게 합니다.

사용 사례

  • 음악 앱 개발
  • 인터랙티브 음악 교육
  • 코드 및 스케일 생성
  • 오디오 애플리케이션 로직
  • 실시간 음악 분석
  • 구성 지원

주요 기능

  • 노트 및 간격 조작
  • 스케일과 코드 구성
  • 키 서명 지원
  • 크로스 플랫폼 호환성
  • 직관적인 API 설계
  • 정확한 음악 이론 계산

적합한 대상

  • 음악 앱에서의 Dart 개발자
  • 교육 소프트웨어 제작자
  • 오디오 처리 프로젝트
  • 코드 기반 도구를 사용하는 음악가
  • 음악 이론 논리를 필요로 하는 앱 빌더

고려 사항

  • 기본 음악 이론에 대한 이해가 필요합니다
  • 이론적 측면에만 국한됨(오디오 재생 제외)
  • 내장된 사운드 합성 없음
  • 추가 오디오 라이브러리와 함께 사용할 때 가장 좋습니다
  • 고급 사용 사례를 위한 맞춤 설정이 필요할 수 있습니다
  • 핵심 기능에 중점을 둔 문서

원본 README

연결된 소스 저장소의 README 원문 스냅샷입니다. 최신 내용은 저장소에서 확인하세요.

Analysis CI Coverage Status pub package OpenSSF Scorecard OpenSSF Best Practices License style: very good analysis

A comprehensive Dart library for effortlessly working with music theory concepts, offering an elegant and beautifully crafted API.

Features

  • Notes, accidentals, and enharmonic operations
  • Intervals, qualities, and circle of fifths
  • Chords, scales, harmonic functions, inversions and retrogrades
  • Keys, key signatures, and modes
  • Frequencies and tuning systems (work in progress)

Usage

Import the package into your Dart code:

import 'package:music_notes/music_notes.dart';

Now, you can use the provided APIs to perform various music theory operations. For more detailed usage instructions and examples, please refer to the API documentation.

Notes

Define a Note from a NoteName (.a to .g) and an Accidental, or using their shorthand static constants:

const Note(.e, .flat); // E♭
Note.c; // C
Note.d; // D
Note.f; // F

NoteNames can be obtained from semitones or ordinal:

NoteName.fromSemitones(2); // NoteName.d
NoteName.fromSemitones(9); // NoteName.a

NoteName.fromOrdinal(3); // NoteName.e
NoteName.fromOrdinal(7); // NoteName.b

Alter a Note with sharp or flat:

Note.c.sharp; // C♯
Note.d.flat; // D♭
Note.g.flat.flat; // G𝄫
Note.f.sharp.sharp.sharp; // F𝄪♯

And position them in the octave, resulting in Pitches:

Note.f.inOctave(4); // F4
Note.b.flat.inOctave(5); // B♭5

Or parse them in both scientific and Helmholtz notations:

NoteName.parse('b'); // NoteName.b
Note.parse('a#'); // A♯
Pitch.parse("g''"); // G5
Pitch.parse('Eb3'); // E♭3

Get their difference in semitones:

NoteName.c.difference(.e); // 4
NoteName.a.difference(.e); // -5
NoteName.a.positiveDifference(.e); // 7

Note.c.difference(.e.flat); // 3
Pitch.parse('C').difference(.parse("c''''")); // 60

Transpose them:

Note.g.flat.transposeBy(-Interval.m3); // E♭
Note.b.inOctave(3).transposeBy(.P5); // F♯4

Respell them by any criteria:

Note.c.sharp.respellByNoteName(.d); // D♭
Note.e.flat.respellByAccidental(.sharp); // D♯
Note.g.flat.inOctave(3).respellByOrdinalDistance(-1); // F♯3

Note.g.sharp.respelledUpwards; // A♭
Note.a.flat.respelledDownwards; // G♯
Note.b.sharp.inOctave(4).respelledSimple; // C5

Compare two Pitches based on their semitones:

Note.c.inOctave(4) < Note.c.inOctave(5); // true
Note.d.inOctave(3) > Note.f.inOctave(4); // false
Note.a.flat.inOctave(5) >= Note.g.sharp.inOctave(5); // true

Know whether two Notes or Pitches are enharmonically equivalent:

Note.f.sharp.isEnharmonicWith(Note.g.flat); // true
Note.c.inOctave(4).isEnharmonicWith(Note.b.sharp.inOctave(3)); // true
Note.a.isEnharmonicWith(Note.b.flat); // false

Represent them as PitchClasses:

Note.d.flat.toClass(); // {C♯|D♭}
Note.a.inOctave(4).toClass(); // {A}

Perform PitchClass multiplications (modulo 12):

PitchClass.cSharp * 7; // {G}
PitchClass.d * 7; // {D}
// observe one semitone upwards results in ascending fifths G -> D.

PitchClass.cSharp * 5; // {F}
PitchClass.d * 5; // {A♯|B♭}
// observe one semitone upwards results in ascending fourths F -> B-flat.

Represent them using any notation formatter:

Note.d.flat
  ..format() // D♭
  ..format(const GermanNoteNotation()) // Des
  ..format(const RomanceNoteNotation.symbol()); // Re♭

Note.b.flat.inOctave(-1).format(); // B♭-1
Note.c.inOctave(6).format(HelmholtzPitchNotation.english); // c‴

PitchClass.c.format(); // {C}
PitchClass.dSharp.format(); // {D♯|E♭}

PitchClass.f.format(const IntegerPitchClassNotation()); // 5
PitchClass.aSharp.format(const IntegerPitchClassNotation()); // t
Intervals

Create an Interval:

const Interval.imperfect(.tenth, .major); // M10
Interval.d5; // d5
Size.sixth.augmented; // A6
Size.eleventh.simple.perfect; // P4

Or parse it from a string:

Interval.parse('m3'); // m3
Interval.parse('P-5'); // P-5
Interval.parse('AA6'); // AA6

Turn it descending:

-Interval.m7; // m-7
(-Interval.P5).direction; // -1
Interval.M3.descending; // M-3
(-Interval.P4).ascending; // P4
(-Interval.P4).withDescending(false); // P4

Perform common interval operations:

Interval.m3.inversion; // M6
Interval.A4.inversion; // d5
Interval.m9.inversion; // M7

Interval.m9.simple; // m2
Interval.P11.simple; // P4
(-Interval.M3).simple; // M-3

Interval.P5.isCompound; // false
Interval.M9.isCompound; // true
(-Interval.P11).isCompound; // true

Interval.P5.isDissonant; // false
Interval.d5.isDissonant; // true
Interval.M7.isDissonant; // true

Respell an Interval by size:

Interval.A4.respellBySize(.fifth); // d5
Interval.d3.respellBySize(.second); // M2

Calculate the Interval between two notes:

Note.c.interval(.g); // P5
Note.d.interval(.f.sharp).inversion; // m6

NoteName.d.intervalSize(.f); // 3
NoteName.a.intervalSize(.e); // 5

Know the intervallic distance between two notes:

Interval.P5.circleDistance<Note>(from: .c, to: .d);
// (2, notes: [C, G, D])
Interval.P4.circleDistance<Note>(from: .b.flat, to: .d);
// (-4, notes: [B♭, F, C, G, D])

And even explore the circle of fifths or any circle of intervals up to a distance:

Interval.P5.circleFrom(Note.c).take(13).toList();
// [C, G, D, A, E, B, F♯, C♯, G♯, D♯, A♯, E♯, B♯]
Note.c.circleOfFifths(distance: 3); // [E♭, B♭, F, C, G, D, A]
Note.c.splitCircleOfFifths.down.take(6).toList();
// [F, B♭, E♭, A♭, D♭, G♭]
Note.c.splitCircleOfFifths.up.take(8).toList();
// [G, D, A, E, B, F♯, C♯, G♯]

Note.d.circleOfFifthsDistance; // 2
Note.a.flat.circleOfFifthsDistance; // -4

Note.c.fifthsDistanceWith(.e.flat); // -3
Note.b.fifthsDistanceWith(.f.sharp); // 1

Know whether two Intervals are enharmonically equivalent:

Interval.M3.isEnharmonicWith(Interval.d4); // true
Interval.A4.isEnharmonicWith(Interval.d5); // true
Interval.P1.isEnharmonicWith(Interval.m2); // false

Represent them as IntervalClasses:

Interval.M2.toClass(); // {M2|d3}
Interval.m6.toClass(); // {M3|d4}
Interval.P8.toClass(); // {P1}

Compare two Intervals based on their semitones:

Interval.m3 < .P5; // true
Interval.m7 <= .P5; // false
-Interval.P4 > .M3; // true

Add, subtract and multiply Intervals and IntervalClasses:

Interval.m2 + .M2; // m3
Interval.M2 + .P4; // P5

IntervalClass.tritone + .M2; // {M3|d4}
IntervalClass.M3 + .P4; // {m3}
IntervalClass.P4 - .m3; // {M2|d3}

IntervalClass.P4 * -1; // {P4}
IntervalClass.M2 * 0; // {P1}
IntervalClass.m3 * 2; // {A4|d5}

Represent them as a string:

Interval.m2.format(); // m2
Interval.A6.format(); // A6

IntervalClass.M2.format(); // {M2|d3}
IntervalClass.P4.format(); // {P4}
IntervalClass.tritone.format(); // {A4|d5}
Keys

Create a Key or get it from a given Note:

const Key(.e, .minor); // E minor
Note.a.flat.major; // A♭ major

Know its KeySignature:

Note.d.major.signature; // {D major, B minor} +2 fifths (F♯ C♯)
Note.e.flat.minor.signature;
// {G♭ major, E♭ minor} −6 fifths (B♭ E♭ A♭ D♭ G♭ C♭)

Whether it is theoretical:

Note.e.major.isTheoretical; // false
Note.a.flat.minor.isTheoretical; // true

And its relative and parallel Keys:

Note.d.major.relative; // B minor
Note.c.minor.relative; // E♭ major

Note.f.minor.parallel; // F major
Note.c.sharp.major.parallel; // C♯ minor

Represent it using any notation formatter:

Note.d.flat.major.format(); // D♭ major
Note.c.major.format(const RomanceKeyNotation()); // Do maggiore
Note.e.flat.minor.format(const GermanKeyNotation()); // es-Moll
Key signatures

Create a KeySignature:

KeySignature.fromDistance(4); // {E major, C♯ minor} +4 fifths (F♯ C♯ G♯ D♯)
KeySignature([.b.flat, .e.flat]); // {B♭ major, G minor} −2 fifths (B♭ E♭)
KeySignature([.g.sharp, .a.sharp]); // Non-canonical (G♯ A♯)

Increment them by sharps or flats:

KeySignature.fromDistance(-4).incrementBy(-1);
// {E♭ major, C minor} −3 fifths (B♭ E♭ A♭)
KeySignature([.f.sharp, .c.sharp]).incrementBy(3);
// {B major, G♯ minor} +5 fifths (F♯ C♯ G♯ D♯ A♯)

And know its Keys:

KeySignature([.f.sharp]).keys[TonalMode.major]; // G major
KeySignature.empty.keys[TonalMode.minor]; // A minor

Non-canonical key signatures are also supported, although they return null when asked about their fifths distance or keys:

KeySignature([.a.flat])
  ..isCanonical // false
  ..distance // null
  ..keys; // <TonalMode, Key>{}
Modes

Get each Mode’s ScalePattern:

TonalMode.minor.scale; // ScalePattern.minor
ModalMode.locrian.scale; // ScalePattern.locrian

Their Dorian Brightness Quotient:

ModalMode.lydian.brightness; // 3
ModalMode.dorian.brightness; // 0
ModalMode.aeolian.brightness; // -1

Or its mirrored version:

ModalMode.ionian.mirrored; // ModalMode.phrygian
ModalMode.aeolian.mirrored; // ModalMode.mixolydian
Scales

Create a Scale from a ScalePattern:

ScalePattern.lydian.on(Note.d); // D Lydian (D E F♯ G♯ A B C♯ D)
ScalePattern.wholeTone.on(Note.f); // F Whole-tone (F G A B C♯ D♯ F)
ScalePattern.majorPentatonic.on(Note.g.flat);
// G♭ Major pentatonic (G♭ A♭ B♭ D♭ E♭ G♭)

Or get it from a Key:

Note.a.flat.major.scale; // A♭ Major (ionian) (A♭ B♭ C D♭ E♭ F G A♭)
Note.d.minor.scale; // D Natural minor (aeolian) (D E F G A B♭ C D)

Even experiment with any ScaleDegree or HarmonicFunction:

ScalePattern.lydian.on(Note.e).degree(.iv); // A♯
Note.c.major.scale.functionChord(
  HarmonicFunction.dominantV / .dominantV,
); // D

Rearrange any collection of Notes, Pitches or PitchClasses as inversion or retrograde:

<Note>{.b, .a.sharp, .d}.inversion.toSet(); // {B, C, G♯}
<PitchClass>{.dSharp, .g, .fSharp}.retrograde.toSet();
// {{F♯|G♭}, {G}, {D♯|E♭}}

Or know its numeric representation:

<PitchClass>{.b, .aSharp, .d, .e}
  ..numericRepresentation()
      .toSet() // {0, 11, 3, 5}
  ..numericRepresentation(reference: .d)
      .toSet() // {9, 8, 0, 2}
  ..deltaNumericRepresentation.toList(); // [0, -1, 4, 2]
Chords

Create a Chord from a series of Notes or a ChordPattern:

Chord([.a, .c.sharp, .e]); // A
ChordPattern.augmentedTriad.add11().add13().on(.d.sharp); // D♯+11 13

Or build it on top of a Note:

Note.f.minorTriad.add7().add9(.minor);
// F-7 ♭9
Note.e.flat.diminishedTriad.add7().transposeBy(.m2);
// F♭ø

Or modify its root triad:

Note.g.minorTriad.major; // G
Note.f.sharp.majorTriad.add9().diminished; // F♯dim
Frequencies

Get the Frequency of a Pitch:

Note.a.inOctave(4).frequency(); // 440
Note.a.inOctave(4).frequency(temperature: const Celsius(18));
// 438.4619866006409

Create a TuningFork from a Pitch and a reference Frequency, or using its shorthand static constants:

Note.a.inOctave(4).at(const Frequency(438)); // A438
TuningFork.a440; // A440
TuningFork.c256; // C256

And use it in a TuningSystem:

Note.b.flat
    .inOctave(4)
    .frequency(
      tuningSystem: const EqualTemperament.edo12(fork: .c256),
    ); // 456.1401436878537

Get the Frequency at a given temperature:

const Frequency(440).at(const Celsius(18)); // 438.4619866006409
const Frequency(440).at(const Celsius(24)); // 443.07602679871826

Get the closest Pitch from a given Frequency:

const Frequency(432).closestPitch(); // A4−32
const Frequency(314).closestPitch(); // E♭4+16
const Frequency(440).closestPitch(temperature: const Celsius(24)); // A4−12

And combining both frequency and closestPitch methods, the harmonic series of a given Pitch:

Note.c.inOctave(1).harmonics().take(16).toSet();
// {C1±0, C2±0, G2+2, C3±0, E3−14, G3+2, A♯3−31, C4±0,
// D4+4, E4−14, F♯4−49, G4+2, A♭4+41, A♯4−31, B4−12, C5±0}

Create a ClosestPitch by adding or subtracting Cents to a Pitch:

Note.f.sharp.inOctave(4) + const Cent(16); // F♯4+16
Note.g.flat.inOctave(5) - const Cent(8.236); // G♭5−8

Or parse a ClosestPitch from a string:

ClosestPitch.parse('A4'); // A4±0
ClosestPitch.parse('E♭3-28'); // E♭3−28
ClosestPitch.parse('A4+12.6').format(
  const StandardClosestPitchNotation(fractionDigits: 1),
); // A4+12.6
In a nutshell
ScalePattern
    .lydian // Lydian (M2 M2 M2 m2 M2 M2 m2)
    .on(Note.parse('a')) // A Lydian (A B C♯ D♯ E F♯ G♯ A)
    .transposeBy(.M2) // B Lydian (B C♯ D♯ E♯ F♯ G♯ A♯ B)
    .degree(.iii) // D♯
    .respelledUpwards // E♭
    .major // E♭ major
    .relative // C minor
    .scale // C Natural minor (aeolian) (C D E♭ F G A♭ B♭ C)
    .degreeChord(.v) // G-
    .add9(); // G-9

Similar projects in other languages

Contributing

Contributions 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.

Star History

Star History Chart

License

This package is released under the BSD-3-Clause License.

카테고리

의존성

의존성 목록 2 개

소스 저장소

이 패키지를 사용하는 프로젝트

아직 데이터가 없습니다.