/**
 * PCM 流式播放 AudioWorklet Processor
 * 动态扩容缓冲区 + 线性插值重采样（24kHz PCM → 系统采样率）
 * 豆包 TTS PCM 格式：24000Hz / 16bit / mono / little-endian (pcm_s16le)
 */
class PcmPlaybackProcessor extends AudioWorkletProcessor {
	constructor() {
		super();
		// 缓冲区：初始 60 秒 @ 24kHz = 1440000 采样，足够容纳 TTS 突发数据
		this._bufferSize = 1440000;
		this._buffer = new Float32Array(this._bufferSize);
		this._writePos = 0;
		this._readPos = 0;
		this._stopped = false;

		// 重采样：从 24kHz 到系统采样率（sampleRate 是 AudioWorklet 全局变量）
		this._srcRate = 24000;
		this._ratio = this._srcRate / sampleRate;
		this._fractionalPos = 0;

		this.port.onmessage = (e) => {
			const { type } = e.data;
			if (type === 'pcm') {
				this._enqueuePcm(e.data.buffer);
			} else if (type === 'clear') {
				this._writePos = 0;
				this._readPos = 0;
				this._fractionalPos = 0;
			} else if (type === 'stop') {
				this._stopped = true;
			}
		};
	}

	/** 缓冲区中可读采样数 */
	_available() {
		const diff = this._writePos - this._readPos;
		return diff >= 0 ? diff : diff + this._bufferSize;
	}

	/** 将 Int16 PCM 数据转为 Float32 写入缓冲区，空间不足时自动扩容 */
	_enqueuePcm(arrayBuffer) {
		const int16 = new Int16Array(arrayBuffer);
		const len = int16.length;
		const avail = this._available();

		// 如果剩余空间不够，扩容到当前 2 倍
		if (avail + len >= this._bufferSize - 1) {
			this._grow(Math.max(this._bufferSize * 2, avail + len + this._bufferSize));
		}

		for (let i = 0; i < len; i++) {
			this._buffer[this._writePos] = int16[i] / 32768;
			this._writePos = (this._writePos + 1) % this._bufferSize;
		}
	}

	/** 扩容缓冲区，保留已有数据 */
	_grow(newSize) {
		const newBuf = new Float32Array(newSize);
		const avail = this._available();
		// 按顺序拷贝可读数据到新缓冲区头部
		for (let i = 0; i < avail; i++) {
			newBuf[i] = this._buffer[(this._readPos + i) % this._bufferSize];
		}
		this._buffer = newBuf;
		this._bufferSize = newSize;
		this._readPos = 0;
		this._writePos = avail;
	}

	process(inputs, outputs) {
		if (this._stopped) return false;

		const output = outputs[0][0];
		if (!output) return true;

		for (let i = 0; i < output.length; i++) {
			// 需要至少 2 个采样做线性插值
			if (this._available() < 2) {
				output[i] = 0;
				continue;
			}

			// 线性插值重采样
			const intPart = Math.floor(this._fractionalPos);
			const frac = this._fractionalPos - intPart;

			const idx0 = (this._readPos + intPart) % this._bufferSize;
			const idx1 = (this._readPos + intPart + 1) % this._bufferSize;

			output[i] = this._buffer[idx0] + (this._buffer[idx1] - this._buffer[idx0]) * frac;

			// 步进
			this._fractionalPos += this._ratio;

			// 消费已经越过的整数采样
			const consumed = Math.floor(this._fractionalPos);
			if (consumed > 0) {
				this._readPos = (this._readPos + consumed) % this._bufferSize;
				this._fractionalPos -= consumed;
			}
		}

		return true;
	}
}

registerProcessor('pcm-playback-processor', PcmPlaybackProcessor);
