def __calcPitchClasses(self): self.__pitchClasses.clear() halfToneNum = self.Key self.__pitchClasses.append(PitchClass.Get(halfToneNum)) for i in self.__intervals: halfToneNum += i self.__pitchClasses.append(PitchClass.Get(halfToneNum))
def __calcPitchClasses(self, scaleKey=None): key = scaleKey if None is not scaleKey and isinstance(scaleKey, ScaleKey): key = scaleKey else: key = self.Key self.__pitchClasses.clear() halfToneNum = key.PitchClass self.__pitchClasses.append(PitchClass.Get(halfToneNum)) for i in self.__intervals: halfToneNum += i self.__pitchClasses.append(PitchClass.Get(halfToneNum))
def test_Get_ZERO(self): lowerLimit = 0 self.assertEqual(0, NoteName.Get('C0', lowerLimit)) self.assertEqual(69, NoteName.Get('A5', lowerLimit)) self.assertEqual(127, NoteName.Get('G10', lowerLimit)) for k in Key.Keys.keys(): for o in range(lowerLimit, lowerLimit+10, 1): with self.subTest(key=k, octave=o): octave = o + abs(lowerLimit) if lowerLimit < 0 else o - abs(lowerLimit) expected = PitchClass.Get(Key.Get(k))[0] + (octave * (PitchClass.Max+1)) self.assertEqual(expected, NoteName.Get(k + str(o), lowerLimit)) expected = PitchClass.Get(Key.Get(k)+1)[0] + (octave * (PitchClass.Max+1)) self.assertEqual(expected, NoteName.Get(k + '#' + str(o), lowerLimit)) expected = PitchClass.Get(Key.Get(k)-1)[0] + (octave * (PitchClass.Max+1)) self.assertEqual(expected, NoteName.Get(k + 'b' + str(o), lowerLimit))
def Get(cls, name: str, lowerLimit=-1): if not (name and isinstance(name, str)): raise TypeError(f'引数nameはstr型にしてください。: type(name)={type(name)}') k, o = cls.__Split(name) pitch_class = PitchClass.Get(Key.Get(k))[0] # B#の場合、Cになる。相対オクターブは無視される octave_class = cls.__GetOctave(o, lowerLimit) return NoteNumber.Get(pitch_class, octave_class)
def Get(cls, pitchClass:int, relativeOctave:int): if not(isinstance(pitchClass, int) and isinstance(relativeOctave, int)): raise TypeError(f'引数pitchClass, relativeOctaveはint型にしてください。: type(pitchClass)={type(pitchClass)}, type(relativeOctave)={type(relativeOctave)}') PitchClass.Validate(pitchClass) noteNumber = pitchClass + (relativeOctave * (PitchClass.Max+1)) # print('noteNumber:', noteNumber, 'pitchClass:', pitchClass, 'relativeOctave:', relativeOctave) if noteNumber < cls.Min or cls.Max < noteNumber: raise ValueError(f'ノート番号が{cls.Min}〜{cls.Max}の範囲外になりました。pitchClass, relativeOctave, 共に0以上の整数値にして範囲内になるようにしてください。: noteNumber={noteNumber}, pitchClass={pitchClass}, relativeOctave={relativeOctave}') return noteNumber
def test_PitchClasses_2(self): keys = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11} for k, kp in keys.items(): for acc_count in range(0, 2): for a, ap in Accidental.Accidentals.items(): name = k + a * acc_count pitch = PitchClass.Get(kp + (ap * acc_count))[0] intervals = ScaleIntervals.Major s = Scale(name, intervals=intervals) halfToneNum = pitch # print(s.Key.PitchClass, end=',') for i, interval in enumerate(intervals): with self.subTest(name=name, degree=i + 1 + 1): # print(s.PitchClasses[i+1][0], end=',') halfToneNum += interval self.assertEqual(PitchClass.Get(halfToneNum), s.PitchClasses[i + 1]) self.assertEqual(PitchClass.Get(halfToneNum), s.GetPitchClass(i + 1 + 1))
def test_init_set(self): keys = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11} for k, kp in keys.items(): for acc_count in range(1, 4): for a, ap in Accidental.Accidentals.items(): name = k + a * acc_count pitch = PitchClass.Get(kp + (ap * acc_count))[0] with self.subTest(name=name): s = ScaleKey(name) self.assertEqual(name, s.Name) self.assertEqual(pitch, s.PitchClass)
def test_Get_SPN(self): self.assertEqual(0, NoteName.Get('C-1')) self.assertEqual(69, NoteName.Get('A4')) self.assertEqual(127, NoteName.Get('G9')) lowerLimit = -1 for k in Key.Keys: for o in range(lowerLimit, lowerLimit + 10, 1): with self.subTest(key=k, octave=o): octave = o + abs( lowerLimit) if lowerLimit < 0 else o - abs(lowerLimit) expected = PitchClass.Get( Key.Get(k))[0] + (octave * (PitchClass.Max + 1)) self.assertEqual(expected, NoteName.Get(k + str(o))) expected = PitchClass.Get(Key.Get(k) + 1)[0] + (octave * (PitchClass.Max + 1)) self.assertEqual(expected, NoteName.Get(k + '#' + str(o))) expected = PitchClass.Get(Key.Get(k) - 1)[0] + (octave * (PitchClass.Max + 1)) self.assertEqual(expected, NoteName.Get(k + 'b' + str(o)))
def test_PitchClasses(self): keys = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11} for k, kp in keys.items(): for acc_count in range(0, 2): for a, ap in Accidental.Accidentals.items(): name = k + a * acc_count pitch = PitchClass.Get(kp + (ap * acc_count))[0] with self.subTest(name=name): s = Scale(name, intervals=ScaleIntervals.Major) self.assertEqual(name, s.Key.Name) self.assertEqual(pitch, s.Key.PitchClass) self.assertEqual(pitch, s.PitchClasses[0][0]) self.assertEqual(pitch, s.GetPitchClass(1)[0])
def test_Get_Plus(self): self.assertEqual((11, 0), PitchClass.Get(11)) self.assertEqual((0, 1), PitchClass.Get(12)) self.assertEqual((1, 1), PitchClass.Get(13)) self.assertEqual((11, 1), PitchClass.Get(23)) self.assertEqual((0, 2), PitchClass.Get(24)) for halfToneNum in range(12, 12*3): with self.subTest(halfToneNum=halfToneNum): self.assertEqual((halfToneNum % 12, halfToneNum // 12), PitchClass.Get(halfToneNum))
def test_Get_Minus(self): self.assertEqual((11, -1), PitchClass.Get(-1)) self.assertEqual((10, -1), PitchClass.Get(-2)) self.assertEqual((0, -1), PitchClass.Get(-12)) self.assertEqual((11, -2), PitchClass.Get(-13)) self.assertEqual((0, -3), PitchClass.Get(-12*3)) for halfToneNum in range(-12*3, 0): with self.subTest(halfToneNum=halfToneNum): expect = halfToneNum % 12 if expect < 0: expect += 12 self.assertEqual((expect, halfToneNum // 12), PitchClass.Get(halfToneNum))
def test_PitchClass(self): pitch_class = PitchClass.Get(0) self.assertTrue(hasattr(pitch_class, 'PitchClass')) self.assertTrue(hasattr(pitch_class, 'RelativeOctave'))
def test_Validate(self): for pitchClass in range(PitchClass.Min, PitchClass.Max+1): PitchClass.Validate(pitchClass)
def PitchClass(self, v): p = PitchClass.Get(v)[0] self.__pitchClass = p self.__noteNumber = NoteNumber.Get(p, self.OctaveClass)
def test_Validate_Invalid_Type(self): with self.assertRaises(TypeError) as e: PitchClass.Validate('無効な型') self.assertIn('引数pitchClassはint型にしてください。', str(e.exception))
def test_Get(self): for halfToneNumber in range(NoteNumber.Min, NoteNumber.Max + 1): with self.subTest(halfToneNumber=halfToneNumber): self.assertEqual( halfToneNumber, NoteNumber.Get(*PitchClass.Get(halfToneNumber)))
def Name(self, v): self.__pitchClass = PitchClass.Get(Key.Get(v))[0] self.__name = v
def Key(self, v): self.__key = PitchClass.Get(v)[0] self.__calcPitchClasses()
def GetFrequency(self, pitchClass, octaveClass): PitchClass.Validate(pitchClass) OctaveClass.Validate(octaveClass, _min=0) return self.FundamentalTone.Hz * math.pow(2, (NoteNumber.Get( pitchClass, octaveClass) - self.FundamentalTone.NoteNumber) / (PitchClass.Max + 1))
def Name(self, v): self.__pitchClass = PitchClass.Get(Key.Get(v))[0] self.__name = v self.__scale._Scale__calcPitchClasses(self)
def NoteNumber(self, v): self.__pitchClass, self.__octaveClass = PitchClass.Get(v) self.__noteNumber = v
def test_Validate_OutOfRange_128(self): with self.assertRaises(ValueError) as e: PitchClass.Validate(12) self.assertIn(f'引数pitchClassは{PitchClass.Min}〜{PitchClass.Max}までの整数値にしてください。', str(e.exception))
def test_Get_Invalid_Type(self): with self.assertRaises(TypeError) as e: #TypeError: not all arguments converted during string formatting PitchClass.Get('無効な型') self.assertIn('引数halfToneNumはint型にしてください。', str(e.exception))
def test_Get(self): for halfToneNum in range(12): self.assertEqual((halfToneNum, 0), PitchClass.Get(halfToneNum))
def Key(self, v): self.__key = PitchClass.Get(v)[0]
def test_Get_str(self): with self.assertRaises( TypeError ) as e: #TypeError: not all arguments converted during string formatting PitchClass.Get('無効値') self.assertEqual(e.message, '')
def GetFrequency(self, pitchClass, octaveClass): PitchClass.Validate(pitchClass) OctaveClass.Validate(octaveClass, _min=0) return self.__ScaleFrequencies[pitchClass] * math.pow(2, octaveClass - self.FundamentalTone.OctaveClass)