# Path: pym2149/buf.py
# class BufType:
# 
#     def __init__(self, _, dtype):
#         self.dtype = dtype
# 
#     def __call__(self):
#         return MasterBuf(self.dtype)
# 
# Path: pym2149/nod.py
# class BufNode(Node):
# 
#     def __init__(self, buftype, channels = 1):
#         super().__init__()
#         self.masterbuf = buftype()
#         self.channels = channels
#         self.realcallimpl = self.callimpl
#         self.callimpl = self.makeresult
# 
#     def makeresult(self):
#         self.blockbuf = self.masterbuf.ensureandcrop(self.block.framecount * self.channels)
#         resultornone = self.realcallimpl()
#         if resultornone is not None:
#             return resultornone
#         return self.blockbuf
# 
# class Node:
# 
#     def __init__(self):
#         self.block = None
# 
#     def call(self, block): # I think we don't default masked to False to ensure it is propagated.
#         return self(block, False)
# 
#     def __call__(self, block, masked):
#         if self.block != block:
#             self.block = block
#             self.masked = masked
#             self.result = self.callimpl()
#         elif not masked and self.masked:
#             log.warning("This node has already executed masked: %s", self)
#         return self.result
# 
#     def chain(self, node):
#         return node(self.block, self.masked)


from .buf import BufType
from .nod import BufNode, Node
import logging


log = logging.getLogger(__name__)

class BinMix(BufNode):

    def __init__(self, tone, noise, toneflagreg, noiseflagreg):
        super().__init__(BufType.signal)
        self.tone = tone
        self.noise = noise
        self.toneflagreg = toneflagreg
        self.noiseflagreg = noiseflagreg

    def callimpl(self):
        # The truth table options are {AND, OR, XOR}.
        # Other functions are negations of these, the 2 constants, or not symmetric.
        # XOR sounds just like noise so it can't be that.
        # AND and OR have the same frequency spectrum so either will sound good.
        # We use AND as zero is preferred over envelope, see qbmixenv:
        noiseflag = self.noiseflagreg.value
        if self.toneflagreg.value:
            self.blockbuf.copybuf(self.chain(self.tone))
            if noiseflag:
                self.blockbuf.andbuf(self.chain(self.noise))
        elif noiseflag:
            self.blockbuf.copybuf(self.chain(self.noise))
        else:
            # Fixed and variable levels should work, see qanlgmix and qenvpbuf:
            self.blockbuf.fill_i1(1)


# Path: pym2149/buf.py
# class BufType:
# 
#     def __init__(self, _, dtype):
#         self.dtype = dtype
# 
#     def __call__(self):
#         return MasterBuf(self.dtype)
# 
# Path: pym2149/nod.py
# class BufNode(Node):
# 
#     def __init__(self, buftype, channels = 1):
#         super().__init__()
#         self.masterbuf = buftype()
#         self.channels = channels
#         self.realcallimpl = self.callimpl
#         self.callimpl = self.makeresult
# 
#     def makeresult(self):
#         self.blockbuf = self.masterbuf.ensureandcrop(self.block.framecount * self.channels)
#         resultornone = self.realcallimpl()
#         if resultornone is not None:
#             return resultornone
#         return self.blockbuf
# 
# class Node:
# 
#     def __init__(self):
#         self.block = None
# 
#     def call(self, block): # I think we don't default masked to False to ensure it is propagated.
#         return self(block, False)
# 
#     def __call__(self, block, masked):
#         if self.block != block:
#             self.block = block
#             self.masked = masked
#             self.result = self.callimpl()
#         elif not masked and self.masked:
#             log.warning("This node has already executed masked: %s", self)
#         return self.result
# 
#     def chain(self, node):
#         return node(self.block, self.masked)


# Path: pym2149/mix.py
from .buf import BufType
from .nod import BufNode, Node
import logging



log = logging.getLogger(__name__)

class BinMix(BufNode):

    def __init__(self, tone, noise, toneflagreg, noiseflagreg):
        super().__init__(BufType.signal)
        self.tone = tone
        self.noise = noise
        self.toneflagreg = toneflagreg
        self.noiseflagreg = noiseflagreg

    def callimpl(self):
        # The truth table options are {AND, OR, XOR}.
        # Other functions are negations of these, the 2 constants, or not symmetric.
        # XOR sounds just like noise so it can't be that.
        # AND and OR have the same frequency spectrum so either will sound good.
        # We use AND as zero is preferred over envelope, see qbmixenv:
        noiseflag = self.noiseflagreg.value
        if self.toneflagreg.value:
            self.blockbuf.copybuf(self.chain(self.tone))
            if noiseflag:
                self.blockbuf.andbuf(self.chain(self.noise))
        elif noiseflag:
            self.blockbuf.copybuf(self.chain(self.noise))
        else:
            # Fixed and variable levels should work, see qanlgmix and qenvpbuf:
            self.blockbuf.fill_i1(1)


class Multiplexer(Node):