music_dsl
1from dataclasses import dataclass 2 3from music_dsl.domain.static.notes import Notes 4from music_dsl.encode import Scales 5 6 7@dataclass 8class Key: 9 root: Notes 10 scale: Scales 11 12 13__version__ = "0.1.0" 14 15# The thin top-level surface (Key/Notes/Scales) is intentional: deeper theory is 16# submodule-scoped (see API-SURFACE.md). __all__ keeps `import *` to exactly this. 17__all__ = ["Key", "Notes", "Scales", "__version__"]
@dataclass
class
Key:
root: Notes
scale: Scales
class
Notes(music_dsl.utils.JsonSerializableEnum):
11class Notes(JsonSerializableEnum): 12 C = "C" 13 Cs = "C#" 14 Db = "Db" 15 D = "D" 16 Ds = "D#" 17 Eb = "Eb" 18 E = "E" 19 F = "F" 20 Fs = "F#" 21 Gb = "Gb" 22 G = "G" 23 Gs = "G#" 24 Ab = "Ab" 25 A = "A" 26 As = "A#" 27 Bb = "Bb" 28 B = "B" 29 30 def to_flat(self): 31 if self.value not in _SHARPS_TO_FLATS: 32 return self 33 return Notes(_SHARPS_TO_FLATS[self.value]) 34 35 def normalized(self): 36 return self.to_flat() 37 38 def __eq__(self, other): 39 if not isinstance(other, Notes): 40 return NotImplemented # note == None / str / ScaleDegree → False, not a crash 41 enharmonic = _SHARPS_TO_FLATS.get(other.value) or _FLATS_TO_SHARPS.get( 42 other.value 43 ) 44 return self.value == other.value or self.value == enharmonic 45 46 def __hash__(self): 47 # Consistent with the enharmonic __eq__: sharps/flats of the same pitch 48 # (Cs/Db, ...) normalize to one flat spelling, so equal notes hash equal. 49 return hash(self.to_flat().value) 50 51 @classmethod 52 def names_by_value(cls): 53 """Map each note's string value to its member name (e.g. ``'C#' -> 'Cs'``).""" 54 return {note.value: note.name for note in cls}
C =
<Notes.C: 'C'>
Cs =
<Notes.Cs: 'C#'>
Db =
<Notes.Db: 'Db'>
D =
<Notes.D: 'D'>
Ds =
<Notes.Ds: 'D#'>
Eb =
<Notes.Eb: 'Eb'>
E =
<Notes.E: 'E'>
F =
<Notes.F: 'F'>
Fs =
<Notes.Fs: 'F#'>
Gb =
<Notes.Gb: 'Gb'>
G =
<Notes.G: 'G'>
Gs =
<Notes.Gs: 'G#'>
Ab =
<Notes.Ab: 'Ab'>
A =
<Notes.A: 'A'>
As =
<Notes.As: 'A#'>
Bb =
<Notes.Bb: 'Bb'>
B =
<Notes.B: 'B'>
class
Scales(enum.Enum):
146class Scales(Enum): 147 # --- Modes of the major scale (functional) -------------------------------- 148 Major = _fn(_scale_mask(0, 2, 4, 5, 7, 9, 11), "Major (Ionian)", "major-mode") 149 Dorian = _fn(_scale_mask(0, 2, 3, 5, 7, 9, 10), "Dorian", "major-mode") 150 Phrygian = _fn(_scale_mask(0, 1, 3, 5, 7, 8, 10), "Phrygian", "major-mode") 151 Lydian = _fn(_scale_mask(0, 2, 4, 6, 7, 9, 11), "Lydian", "major-mode") 152 Mixolydian = _fn(_scale_mask(0, 2, 4, 5, 7, 9, 10), "Mixolydian", "major-mode") 153 Minor = _fn(_scale_mask(0, 2, 3, 5, 7, 8, 10), "Natural minor (Aeolian)", "major-mode") 154 Locrian = _fn(_scale_mask(0, 1, 3, 5, 6, 8, 10), "Locrian", "major-mode") 155 156 # --- Melodic minor and its modes (functional) ----------------------------- 157 MelodicMinor = _fn(_scale_mask(0, 2, 3, 5, 7, 9, 11), "Melodic minor", "melodic-minor") 158 DorianFlat2 = _fn(_scale_mask(0, 1, 3, 5, 7, 9, 10), "Dorian b2", "melodic-minor") 159 LydianAugmented = _fn(_scale_mask(0, 2, 4, 6, 8, 9, 11), "Lydian augmented", "melodic-minor") 160 LydianDominant = _fn(_scale_mask(0, 2, 4, 6, 7, 9, 10), "Lydian dominant", "melodic-minor") 161 MixolydianFlat6 = _fn(_scale_mask(0, 2, 4, 5, 7, 8, 10), "Mixolydian b6", "melodic-minor") 162 LocrianNatural2 = _fn(_scale_mask(0, 2, 3, 5, 6, 8, 10), "Locrian natural 2", "melodic-minor") 163 Altered = _fn(_scale_mask(0, 1, 3, 4, 6, 8, 10), "Altered (Super Locrian)", "melodic-minor") 164 165 # --- Harmonic minor and its modes (functional) ---------------------------- 166 HarmonicMinor = _fn(_scale_mask(0, 2, 3, 5, 7, 8, 11), "Harmonic minor", "harmonic-minor") 167 LocrianNatural6 = _fn(_scale_mask(0, 1, 3, 5, 6, 9, 10), "Locrian natural 6", "harmonic-minor") 168 IonianSharp5 = _fn(_scale_mask(0, 2, 4, 5, 8, 9, 11), "Ionian #5", "harmonic-minor") 169 DorianSharp4 = _fn(_scale_mask(0, 2, 3, 6, 7, 9, 10), "Dorian #4 (Ukrainian)", "harmonic-minor") 170 PhrygianDominant = _fn(_scale_mask(0, 1, 4, 5, 7, 8, 10), "Phrygian dominant", "harmonic-minor") 171 LydianSharp2 = _fn(_scale_mask(0, 3, 4, 6, 7, 9, 11), "Lydian #2", "harmonic-minor") 172 Ultralocrian = _fn(_scale_mask(0, 1, 3, 4, 6, 8, 9), "Ultralocrian", "harmonic-minor") 173 174 # --- Harmonic major and other named heptatonics (functional) -------------- 175 HarmonicMajor = _fn(_scale_mask(0, 2, 4, 5, 7, 8, 11), "Harmonic major", "harmonic-major") 176 DoubleHarmonic = _fn(_scale_mask(0, 1, 4, 5, 7, 8, 11), "Double harmonic (Byzantine)", "exotic") 177 HungarianMinor = _fn(_scale_mask(0, 2, 3, 6, 7, 8, 11), "Hungarian minor", "exotic") 178 HungarianMajor = _fn(_scale_mask(0, 3, 4, 6, 7, 9, 10), "Hungarian major", "exotic") 179 NeapolitanMajor = _fn(_scale_mask(0, 1, 3, 5, 7, 9, 11), "Neapolitan major", "exotic") 180 NeapolitanMinor = _fn(_scale_mask(0, 1, 3, 5, 7, 8, 11), "Neapolitan minor", "exotic") 181 182 # --- Pentatonic and blues (functional) ------------------------------------ 183 MajorPentatonic = _fn(_scale_mask(0, 2, 4, 7, 9), "Major pentatonic", "pentatonic") 184 MinorPentatonic = _fn(_scale_mask(0, 3, 5, 7, 10), "Minor pentatonic", "pentatonic") 185 Blues = _fn(_scale_mask(0, 3, 5, 6, 7, 10), "Blues (minor)", "blues") 186 187 # --- Bebop (functional, 8-note; passing tone documented in SPEC) ----------- 188 BebopDominant = _fn(_scale_mask(0, 2, 4, 5, 7, 9, 10, 11), "Bebop dominant", "bebop") 189 BebopMajor = _fn(_scale_mask(0, 2, 4, 5, 7, 8, 9, 11), "Bebop major", "bebop") 190 BebopDorian = _fn(_scale_mask(0, 2, 3, 4, 5, 7, 9, 10), "Bebop Dorian", "bebop") 191 BebopMinor = _fn(_scale_mask(0, 2, 3, 5, 7, 9, 10, 11), "Bebop minor", "bebop") 192 193 # --- Symmetric / atonal (NON-functional: membership only) ----------------- 194 WholeTone = _sym(_scale_mask(0, 2, 4, 6, 8, 10), "Whole tone", "symmetric") 195 DiminishedHalfWhole = _sym( 196 _scale_mask(0, 1, 3, 4, 6, 7, 9, 10), "Diminished (half-whole)", "symmetric" 197 ) 198 DiminishedWholeHalf = _sym( 199 _scale_mask(0, 2, 3, 5, 6, 8, 9, 11), "Diminished (whole-half)", "symmetric" 200 ) 201 Augmented = _sym(_scale_mask(0, 3, 4, 7, 8, 11), "Augmented", "symmetric") 202 Chromatic = _sym(_scale_mask(*range(12)), "Chromatic", "atonal")
Major =
<Scales.Major: ScaleDescriptor(mask=46534580949, name='Major (Ionian)', category='major-mode', supports_diatonic_function=True)>
Dorian =
<Scales.Dorian: ScaleDescriptor(mask=48699370326, name='Dorian', category='major-mode', supports_diatonic_function=True)>
Phrygian =
<Scales.Phrygian: ScaleDescriptor(mask=57358527834, name='Phrygian', category='major-mode', supports_diatonic_function=True)>
Lydian =
<Scales.Lydian: ScaleDescriptor(mask=45997578933, name='Lydian', category='major-mode', supports_diatonic_function=True)>
Mixolydian =
<Scales.Mixolydian: ScaleDescriptor(mask=46551362262, name='Mixolydian', category='major-mode', supports_diatonic_function=True)>
Minor =
<Scales.Minor: ScaleDescriptor(mask=48766495578, name='Natural minor (Aeolian)', category='major-mode', supports_diatonic_function=True)>
Locrian =
<Scales.Locrian: ScaleDescriptor(mask=57627028842, name='Locrian', category='major-mode', supports_diatonic_function=True)>
MelodicMinor =
<Scales.MelodicMinor: ScaleDescriptor(mask=48682589013, name='Melodic minor', category='melodic-minor', supports_diatonic_function=True)>
DorianFlat2 =
<Scales.DorianFlat2: ScaleDescriptor(mask=57291402582, name='Dorian b2', category='melodic-minor', supports_diatonic_function=True)>
LydianAugmented =
<Scales.LydianAugmented: ScaleDescriptor(mask=45863328429, name='Lydian augmented', category='melodic-minor', supports_diatonic_function=True)>
LydianDominant =
<Scales.LydianDominant: ScaleDescriptor(mask=46014360246, name='Lydian dominant', category='melodic-minor', supports_diatonic_function=True)>
MixolydianFlat6 =
<Scales.MixolydianFlat6: ScaleDescriptor(mask=46618487514, name='Mixolydian b6', category='melodic-minor', supports_diatonic_function=True)>
LocrianNatural2 =
<Scales.LocrianNatural2: ScaleDescriptor(mask=49034996586, name='Locrian natural 2', category='melodic-minor', supports_diatonic_function=True)>
Altered =
<Scales.Altered: ScaleDescriptor(mask=58701032874, name='Altered (Super Locrian)', category='melodic-minor', supports_diatonic_function=True)>
HarmonicMinor =
<Scales.HarmonicMinor: ScaleDescriptor(mask=48749714265, name='Harmonic minor', category='harmonic-minor', supports_diatonic_function=True)>
LocrianNatural6 =
<Scales.LocrianNatural6: ScaleDescriptor(mask=57559903590, name='Locrian natural 6', category='harmonic-minor', supports_diatonic_function=True)>
IonianSharp5 =
<Scales.IonianSharp5: ScaleDescriptor(mask=46400330445, name='Ionian #5', category='harmonic-minor', supports_diatonic_function=True)>
DorianSharp4 =
<Scales.DorianSharp4: ScaleDescriptor(mask=48162368310, name='Dorian #4 (Ukrainian)', category='harmonic-minor', supports_diatonic_function=True)>
PhrygianDominant =
<Scales.PhrygianDominant: ScaleDescriptor(mask=55210519770, name='Phrygian dominant', category='harmonic-minor', supports_diatonic_function=True)>
LydianSharp2 =
<Scales.LydianSharp2: ScaleDescriptor(mask=41701562805, name='Lydian #2', category='harmonic-minor', supports_diatonic_function=True)>
Ultralocrian =
<Scales.Ultralocrian: ScaleDescriptor(mask=58734595500, name='Ultralocrian', category='harmonic-minor', supports_diatonic_function=True)>
HarmonicMajor =
<Scales.HarmonicMajor: ScaleDescriptor(mask=46601706201, name='Harmonic major', category='harmonic-major', supports_diatonic_function=True)>
DoubleHarmonic =
<Scales.DoubleHarmonic: ScaleDescriptor(mask=55193738457, name='Double harmonic (Byzantine)', category='exotic', supports_diatonic_function=True)>
HungarianMinor =
<Scales.HungarianMinor: ScaleDescriptor(mask=48212712249, name='Hungarian minor', category='exotic', supports_diatonic_function=True)>
HungarianMajor =
<Scales.HungarianMajor: ScaleDescriptor(mask=41718344118, name='Hungarian major', category='exotic', supports_diatonic_function=True)>
NeapolitanMajor =
<Scales.NeapolitanMajor: ScaleDescriptor(mask=57274621269, name='Neapolitan major', category='exotic', supports_diatonic_function=True)>
NeapolitanMinor =
<Scales.NeapolitanMinor: ScaleDescriptor(mask=57341746521, name='Neapolitan minor', category='exotic', supports_diatonic_function=True)>
MajorPentatonic =
<Scales.MajorPentatonic: ScaleDescriptor(mask=45443795604, name='Major pentatonic', category='pentatonic', supports_diatonic_function=True)>
MinorPentatonic =
<Scales.MinorPentatonic: ScaleDescriptor(mask=40040212818, name='Minor pentatonic', category='pentatonic', supports_diatonic_function=True)>
Blues =
<Scales.Blues: ScaleDescriptor(mask=40577214834, name='Blues (minor)', category='blues', supports_diatonic_function=True)>
BebopDominant =
<Scales.BebopDominant: ScaleDescriptor(mask=46568143575, name='Bebop dominant', category='bebop', supports_diatonic_function=True)>
BebopMajor =
<Scales.BebopMajor: ScaleDescriptor(mask=46668831453, name='Bebop major', category='bebop', supports_diatonic_function=True)>
BebopDorian =
<Scales.BebopDorian: ScaleDescriptor(mask=50847378390, name='Bebop Dorian', category='bebop', supports_diatonic_function=True)>
BebopMinor =
<Scales.BebopMinor: ScaleDescriptor(mask=48716151639, name='Bebop minor', category='bebop', supports_diatonic_function=True)>
WholeTone =
<Scales.WholeTone: ScaleDescriptor(mask=45812984490, name='Whole tone', category='symmetric', supports_diatonic_function=False)>
DiminishedHalfWhole =
<Scales.DiminishedHalfWhole: ScaleDescriptor(mask=58902408630, name='Diminished (half-whole)', category='symmetric', supports_diatonic_function=False)>
DiminishedWholeHalf =
<Scales.DiminishedWholeHalf: ScaleDescriptor(mask=49085340525, name='Diminished (whole-half)', category='symmetric', supports_diatonic_function=False)>
Augmented =
<Scales.Augmented: ScaleDescriptor(mask=41231686041, name='Augmented', category='symmetric', supports_diatonic_function=False)>
Chromatic =
<Scales.Chromatic: ScaleDescriptor(mask=68719476735, name='Chromatic', category='atonal', supports_diatonic_function=False)>
__version__ =
'0.1.0'