# Path: pym2149/pitch.py
# class FiveLimit(Unequal):
#     'Asymmetric variant.'
# 
#     @types(Config)
#     def __init__(self, config):
#         reffreq = float(config.referencefrequency)
#         refpitch = float(config.referencemidinote)
#         freqs = [None] * 12
#         for p5 in range(-1, 2):
#             for p3 in range(-1, 3): # Skip first column for asymmetric.
#                 ratio = 3 ** p3 * 5 ** p5
#                 ratio /= 2 ** math.floor(math.log(ratio, 2))
#                 index = round(math.log(ratio, 2) * 12)
#                 freqs[index] = reffreq * ratio
#         super().__init__(refpitch, freqs)
# 
# class Meantone(Unequal):
#     'Including Pythagorean as a special case when meantonecomma is zero.'
# 
#     syntonic = 81 / 80
# 
#     @types(Config)
#     def __init__(self, config):
#         reffreq = float(config.referencefrequency)
#         refpitch = float(config.referencemidinote)
#         flats = config.meantoneflats
#         fifthratio = 1.5 / self.syntonic ** float(config.meantonecomma)
#         freqs = [None] * 12
#         for fifth in range(-flats, 12 - flats):
#             pitch = fifth * 7
#             freqs[pitch % 12] = reffreq * fifthratio ** fifth / 2 ** (pitch // 12)
#         super().__init__(refpitch, freqs)
#         wolfpitch = Pitch(refpitch + 11 - flats)
#         log.debug("The fifth %s to %s is a wolf interval.", wolfpitch, wolfpitch + 7)
# 
# class Pitch(float):
# 
#     names = ('C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B')
# 
#     def __add__(self, that):
#         return type(self)(float.__add__(self, that))
# 
#     def __sub__(self, that):
#         return type(self)(float.__sub__(self, that))
# 
#     def __str__(self):
#         return self.str(10)
# 
#     def str(self, mincents):
#         nearest = int(math.ceil(self - .5))
#         octave = nearest // 12
#         note = nearest % 12
#         cents = int(round((self - nearest) * 100))
#         octave -= 1
#         notestr = self.names[note]
#         if len(notestr) < 2:
#             notestr += '.'
#         octavestr = str(octave)
#         if len(octavestr) < 2:
#             octavestr = '.' + octavestr
#         if abs(cents) < mincents:
#             centsstr = ' ' * 3
#         else:
#             centsstr = f"{cents:+3d}"
#         return notestr + octavestr + centsstr


from .pitch import FiveLimit, Meantone, Pitch
from types import SimpleNamespace
from unittest import TestCase
import math
        self.assertEqual(2 ** 18 / 3 ** 11, m.freq(63) / m.freq(56))

    def test_meantonemajor(self):
        m = Meantone(SimpleNamespace(referencefrequency = 440, referencemidinote = 69, meantoneflats = 2, meantonecomma = .25))
        self.assertEqual(8, sum(1 for p in range(60, 72) if math.isclose(5 / 4, m.freq(p + 4) / m.freq(p))))

    def test_meantoneminor(self):
        m = Meantone(SimpleNamespace(referencefrequency = 440, referencemidinote = 69, meantoneflats = 2, meantonecomma = 1 / 3))
        self.assertEqual(9, sum(1 for p in range(60, 72) if math.isclose(6 / 5, m.freq(p + 3) / m.freq(p))))

class TestFiveLimit(TestCase):

    def test_asymmetric(self):
        t = FiveLimit(SimpleNamespace(referencefrequency = 440, referencemidinote = 69))
        self.assertAlmostEqual(440, t.freq(69))
        self.assertAlmostEqual(440 * 16 / 15, t.freq(70))
        self.assertAlmostEqual(440 * 9 / 8, t.freq(71))
        self.assertAlmostEqual(440 * 6 / 5, t.freq(72))
        self.assertAlmostEqual(440 * 5 / 4, t.freq(73))
        self.assertAlmostEqual(440 * 4 / 3, t.freq(74))
        self.assertAlmostEqual(440 * 45 / 32, t.freq(75))
        self.assertAlmostEqual(440 * 3 / 2, t.freq(76))
        self.assertAlmostEqual(440 * 8 / 5, t.freq(77))
        self.assertAlmostEqual(440 * 5 / 3, t.freq(78))
        self.assertAlmostEqual(440 * 9 / 5, t.freq(79))
        self.assertAlmostEqual(440 * 15 / 8, t.freq(80))

class TestPitch(TestCase):

    def test_str(self):

# Path: pym2149/pitch.py
# class FiveLimit(Unequal):
#     'Asymmetric variant.'
# 
#     @types(Config)
#     def __init__(self, config):
#         reffreq = float(config.referencefrequency)
#         refpitch = float(config.referencemidinote)
#         freqs = [None] * 12
#         for p5 in range(-1, 2):
#             for p3 in range(-1, 3): # Skip first column for asymmetric.
#                 ratio = 3 ** p3 * 5 ** p5
#                 ratio /= 2 ** math.floor(math.log(ratio, 2))
#                 index = round(math.log(ratio, 2) * 12)
#                 freqs[index] = reffreq * ratio
#         super().__init__(refpitch, freqs)
# 
# class Meantone(Unequal):
#     'Including Pythagorean as a special case when meantonecomma is zero.'
# 
#     syntonic = 81 / 80
# 
#     @types(Config)
#     def __init__(self, config):
#         reffreq = float(config.referencefrequency)
#         refpitch = float(config.referencemidinote)
#         flats = config.meantoneflats
#         fifthratio = 1.5 / self.syntonic ** float(config.meantonecomma)
#         freqs = [None] * 12
#         for fifth in range(-flats, 12 - flats):
#             pitch = fifth * 7
#             freqs[pitch % 12] = reffreq * fifthratio ** fifth / 2 ** (pitch // 12)
#         super().__init__(refpitch, freqs)
#         wolfpitch = Pitch(refpitch + 11 - flats)
#         log.debug("The fifth %s to %s is a wolf interval.", wolfpitch, wolfpitch + 7)
# 
# class Pitch(float):
# 
#     names = ('C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B')
# 
#     def __add__(self, that):
#         return type(self)(float.__add__(self, that))
# 
#     def __sub__(self, that):
#         return type(self)(float.__sub__(self, that))
# 
#     def __str__(self):
#         return self.str(10)
# 
#     def str(self, mincents):
#         nearest = int(math.ceil(self - .5))
#         octave = nearest // 12
#         note = nearest % 12
#         cents = int(round((self - nearest) * 100))
#         octave -= 1
#         notestr = self.names[note]
#         if len(notestr) < 2:
#             notestr += '.'
#         octavestr = str(octave)
#         if len(octavestr) < 2:
#             octavestr = '.' + octavestr
#         if abs(cents) < mincents:
#             centsstr = ' ' * 3
#         else:
#             centsstr = f"{cents:+3d}"
#         return notestr + octavestr + centsstr


# Path: pym2149/test_pitch.py
from .pitch import FiveLimit, Meantone, Pitch
from types import SimpleNamespace
from unittest import TestCase
import math

        self.assertEqual(2 ** 18 / 3 ** 11, m.freq(63) / m.freq(56))

    def test_meantonemajor(self):
        m = Meantone(SimpleNamespace(referencefrequency = 440, referencemidinote = 69, meantoneflats = 2, meantonecomma = .25))
        self.assertEqual(8, sum(1 for p in range(60, 72) if math.isclose(5 / 4, m.freq(p + 4) / m.freq(p))))

    def test_meantoneminor(self):
        m = Meantone(SimpleNamespace(referencefrequency = 440, referencemidinote = 69, meantoneflats = 2, meantonecomma = 1 / 3))
        self.assertEqual(9, sum(1 for p in range(60, 72) if math.isclose(6 / 5, m.freq(p + 3) / m.freq(p))))

class TestFiveLimit(TestCase):

    def test_asymmetric(self):
        t = FiveLimit(SimpleNamespace(referencefrequency = 440, referencemidinote = 69))
        self.assertAlmostEqual(440, t.freq(69))
        self.assertAlmostEqual(440 * 16 / 15, t.freq(70))
        self.assertAlmostEqual(440 * 9 / 8, t.freq(71))
        self.assertAlmostEqual(440 * 6 / 5, t.freq(72))
        self.assertAlmostEqual(440 * 5 / 4, t.freq(73))
        self.assertAlmostEqual(440 * 4 / 3, t.freq(74))
        self.assertAlmostEqual(440 * 45 / 32, t.freq(75))
        self.assertAlmostEqual(440 * 3 / 2, t.freq(76))
        self.assertAlmostEqual(440 * 8 / 5, t.freq(77))
        self.assertAlmostEqual(440 * 5 / 3, t.freq(78))
        self.assertAlmostEqual(440 * 9 / 5, t.freq(79))
        self.assertAlmostEqual(440 * 15 / 8, t.freq(80))

class TestPitch(TestCase):

    def test_str(self):

        self.assertEqual('C..4   ', str(Pitch(60)))