"use strict";
var import_agents = require("@livekit/agents");
var import_rtc_node = require("@livekit/rtc-node");
var import_node_fs = require("node:fs");
var import_node_path = require("node:path");
var import_vitest = require("vitest");
var import_vad = require("./vad.cjs");
const import_meta = {};
const TARGET_SAMPLE_RATE = 16e3;
const CHUNK_DURATION_MS = 10;
function makeSpeechThenSilenceFrames() {
  const sample = (0, import_node_fs.readFileSync)((0, import_node_path.join)(import_meta.dirname, "../../test/src/long.wav"));
  const channels = sample.readUInt16LE(22);
  const fileSampleRate = sample.readUInt32LE(24);
  const dataSamples = sample.readUInt32LE(40) / 2;
  const pcm = new Int16Array(sample.buffer, sample.byteOffset, Math.trunc(sample.byteLength / 2));
  const dataStart = 22;
  const speechSampleCount = Math.min(Math.trunc(fileSampleRate * 1.5), dataSamples);
  const speech = pcm.slice(dataStart, dataStart + speechSampleCount);
  let speechFrame = new import_rtc_node.AudioFrame(
    speech,
    fileSampleRate,
    channels,
    Math.trunc(speechSampleCount / channels)
  );
  if (fileSampleRate !== TARGET_SAMPLE_RATE) {
    const resampler = new import_rtc_node.AudioResampler(fileSampleRate, TARGET_SAMPLE_RATE, channels);
    const out = [...resampler.push(speechFrame), ...resampler.flush()];
    resampler.close();
    speechFrame = (0, import_agents.mergeFrames)(out);
  }
  const silenceSamples = Math.trunc(TARGET_SAMPLE_RATE * 1.2);
  const silenceFrame = new import_rtc_node.AudioFrame(
    new Int16Array(silenceSamples),
    TARGET_SAMPLE_RATE,
    channels,
    silenceSamples
  );
  const merged = (0, import_agents.mergeFrames)([speechFrame, silenceFrame]);
  const chunkSize = TARGET_SAMPLE_RATE * CHUNK_DURATION_MS / 1e3;
  const bstream = new import_agents.AudioByteStream(TARGET_SAMPLE_RATE, channels, chunkSize);
  const arrayBuffer = merged.data.buffer.slice(
    merged.data.byteOffset,
    merged.data.byteOffset + merged.data.byteLength
  );
  const frames = bstream.write(arrayBuffer);
  frames.push(...bstream.flush());
  return frames;
}
async function drainSpeechSegment(stream, frames) {
  for (const frame of frames) {
    stream.pushFrame(frame);
  }
  let sos;
  while (true) {
    const { done, value } = await stream.next();
    if (done) {
      throw new Error("stream ended before END_OF_SPEECH");
    }
    if (value.type === import_agents.VADEventType.START_OF_SPEECH && sos === void 0) {
      sos = value;
    } else if (value.type === import_agents.VADEventType.END_OF_SPEECH && sos !== void 0) {
      return [sos, value];
    }
  }
}
(0, import_vitest.describe)("Silero VADStream flush reset", () => {
  (0, import_vitest.it)(
    "recovers a full speech segment after flush() resets the stream",
    { timeout: 3e4 },
    async () => {
      const frames = makeSpeechThenSilenceFrames();
      (0, import_vitest.expect)(frames.length).toBeGreaterThan(1);
      const vad = await import_vad.VAD.load();
      const stream = vad.stream();
      try {
        const [firstSos, firstEos] = await drainSpeechSegment(stream, frames);
        (0, import_vitest.expect)(firstSos.type).toBe(import_agents.VADEventType.START_OF_SPEECH);
        (0, import_vitest.expect)(firstEos.type).toBe(import_agents.VADEventType.END_OF_SPEECH);
        stream.flush();
        const [secondSos, secondEos] = await drainSpeechSegment(stream, frames);
        (0, import_vitest.expect)(secondSos.type).toBe(import_agents.VADEventType.START_OF_SPEECH);
        (0, import_vitest.expect)(secondEos.type).toBe(import_agents.VADEventType.END_OF_SPEECH);
      } finally {
        stream.close();
      }
    }
  );
});
//# sourceMappingURL=vad.test.cjs.map