Beispiel #1
0
class Sweep:
    def __init__(self):
        self.is_enabled = False
        self.reload = False
        self.divider = Divider()
        self.negative_flag = False
        self.shift = 0

    def reset(self):
        self.is_enabled = False
        self.reload = False
        self.divider = Divider()

    def step(self):
        """Returns true if pulse period needs to be adjusted"""
        return_value = False
        if self.reload:
            if self.divider.counter == 0 and self.is_enabled:
                return_value = True
            self.divider.reload()
            self.reload = False  # Done reloading
        elif self.divider.step() and self.is_enabled:
            self.divider.reload()
            return_value = True

        return return_value
Beispiel #2
0
class Envelope:
    def __init__(self):
        self.start = False
        self.loop = False
        self.divider = Divider()
        self.counter = 0x00  # 1 byte

    def reset(self):
        self.start = False
        self.loop = False
        self.divider.reset()
        self.counter = 0x00

    def step(self):
        if self.start:
            self.start = False
            self.counter = 0x0F
            self.divider.reload()
        elif self.divider.step():
            if self.counter > 0:
                self.counter = (self.counter - 1) & 0xFF
            elif self.loop:
                self.counter = 0x0F
Beispiel #3
0
class Noise:

    LENGTH_COUNTER_DATA = [
        10, 254, 20, 2, 40, 4, 80, 6, 160, 8, 60, 10, 14, 12, 26, 14, 12, 16,
        24, 18, 48, 20, 96, 22, 192, 24, 72, 26, 16, 28, 32, 30
    ]

    PERIOD_DATA = [
        4,
        8,
        16,
        32,
        64,
        96,
        128,
        160,
        202,
        254,
        380,
        508,
        762,
        1016,
        2034,
        4068,
    ]

    def __init__(self):
        self.envelope = Envelope()
        self.divider = Divider()
        self.shift = 0x0000
        self.length_counter = 0x00
        self.is_enabled = False
        self.registers = [0x00, 0x00, 0x00]

    def reset(self):
        self.is_enabled = False
        self.registers = [0x00, 0x00, 0x00]
        self.divider.reset()
        self.length_counter = 0x00
        self.envelope.reset()
        self.shift = 0x0000

    def enable(self):
        self.is_enabled = True

    def disable(self):
        self.is_enabled = False
        self.length_counter = 0x00

    def read_register(self, address):
        if address == 0x400c:
            return self.registers[0]
        elif address == 0x400e:
            return self.registers[1]
        elif address == 0x400f:
            return self.registers[2]
        else:
            raise NoiseError("Invalid read access to register {}".format(
                hex(address)))

    def write_register(self, address, value):
        if address == 0x400c:
            # --lc.vvvv, length counter halt, constant volume/envelope flag, volume/envelope divider period
            self.registers[0] = value
            self.envelope.loop = ((value >> 5) & 1) == 1
            self.envelope.divider.period = value & 0x0F
        elif address == 0x400e:
            # M---.PPPP Mode, period
            self.registers[1] = value
            self.divider.period = self.PERIOD_DATA[value & 0x0F]
            self.divider.reload()
        elif address == 0x400F:
            # llll.l--- Length counter load and envelope restart
            self.registers[2] = value
            self.envelope.start = True
            if self.is_enabled:
                self.length_counter = self.LENGTH_COUNTER_DATA[value >> 3]
        else:
            raise NoiseError("Invalid write access to register {}".format(
                hex(address)))

    def output(self):
        if not self.is_enabled:
            return 0
        if self.shift & 0x0001 != 0:
            return 0
        if self.length_counter == 0:
            return 0
        if (self.registers[0] >> 4) & 0x01:  # Constant volume flag
            return self.envelope.counter
        else:
            return self.registers[0] & 0x0F