📄 src/lib/birdnet.svelte.ts
import BirdNetWorker from "./birdnet.worker.ts?worker";
import type { Prediction, WorkerInMessage, WorkerOutMessage } from "./types";
import { addDetection } from "./history";

class BirdNetService {
  workerReady = $state(false);
  predictions = $state<Prediction[]>([]);

  readonly #worker: Worker;

  constructor() {
    this.#worker = new BirdNetWorker();
    this.#worker.addEventListener(
      "message",
      (e: MessageEvent<WorkerOutMessage>) => {
        const msg = e.data;
        if (msg.type === "ready") {
          this.workerReady = true;
        } else if (msg.type === "results") {
          this.predictions = msg.predictions;
          for (const p of msg.predictions) addDetection(p);
        }
      },
    );
    this.#worker.postMessage({ type: "init" } satisfies WorkerInMessage);
  }

  analyze(samples: Float32Array): void {
    this.#worker.postMessage(
      { type: "analyze", samples } satisfies WorkerInMessage,
      [samples.buffer],
    );
  }

  clearPredictions(): void {
    this.predictions = [];
  }
}

export const birdnet = new BirdNetService();