import numpy as np
import sounddevice as sd

class BytebeatPlayer:
    def __init__(self, func, sample_rate=44100, blocksize=1024, mode="byte"):
        self.func = func
        self.sr = sample_rate
        self.blocksize = blocksize
        self.mode = mode
        self.t = 0
        self.stream = None

    def _callback(self, outdata, frames, info, status):
        ts = np.arange(self.t, self.t + frames, dtype=np.int64)
        s = self.func(ts)

        if self.mode == "byte":
            s = (np.asarray(s & 255, dtype=np.float32) / 128.0) - 1.0
        else:
            s = np.clip(np.asarray(s, dtype=np.float32), -1, 1)

        outdata[:] = np.column_stack((s, s))
        self.t += frames

    def start(self):
        self.stream = sd.OutputStream(
            channels=2,
            samplerate=self.sr,
            blocksize=self.blocksize,
            callback=self._callback,
            dtype="float32"
        )
        self.stream.start()

    def stop(self):
        if self.stream:
            self.stream.stop()
            self.stream.close()
            self.stream = None
