function mixAudioByFormat(audioStreams) {
  const dst = audioStreams.reduce((dst2, audioStream) => {
    const { audioBuffer: srcBuffer, volume } = audioStream;
    const max_audioval = (1 << 16 - 1) - 1;
    const min_audioval = -(1 << 16 - 1);
    let srcIndex = 0;
    let dstIndex = 0;
    const src = new Int16Array(srcBuffer, 0, srcBuffer.byteLength / 2);
    let length = src.length;
    while (length--) {
      const src1 = src[srcIndex] * volume;
      const src2 = dst2[srcIndex];
      srcIndex += 1;
      let dst_sample = src1 + src2;
      if (dst_sample > max_audioval) {
        dst_sample = max_audioval;
      } else if (dst_sample < min_audioval) {
        dst_sample = min_audioval;
      }
      dst2[dstIndex] = dst_sample;
      dstIndex += 1;
    }
    return dst2;
  }, new Int16Array(2048));
  return dst.buffer;
}
const proxies = /* @__PURE__ */ new WeakMap();
const transferables = ["ArrayBuffer", "MessagePort", "ImageBitmap", "OffscreenCanvas"];
function checkAndAppendtoTransferable(target, transferList) {
  const targetTypeStr = Object.prototype.toString.call(target).slice(8, -1);
  if (transferables.indexOf(targetTypeStr) !== -1) {
    transferList.push(target);
    return;
  }
  if (targetTypeStr === "Object") {
    const ownkeys = Reflect.ownKeys(target);
    for (let key of ownkeys) {
      checkAndAppendtoTransferable(target[key], transferList);
    }
  }
}
function proxy(obj, target = self) {
  if (proxies.has(target)) {
    throw new Error("The specified target already has a proxy");
  }
  proxies.set(target, true);
  const persisted = [];
  const listener = (event) => {
    switch (event.data.type) {
      case "ACTION_OPERATION":
        {
          const { id, data } = event.data;
          try {
            let result = obj;
            for (const action of data) {
              if (action.type === "get") {
                result = result[action.key];
              } else if (action.type === "set") {
                result = Reflect.set(result, action.key, action.value);
              } else if (action.type === "apply") {
                const prop = result[action.key];
                if (typeof prop !== "function") {
                  throw new TypeError(`${action.key} is not a function`);
                } else {
                  result = prop.call(obj, ...action.args.map((arg) => {
                    if (arg && arg.type === "TYPE_FUNCTION") {
                      return (() => {
                        let called = false;
                        if (arg.persisted) {
                          persisted.push(arg.ref);
                        }
                        return (...params) => {
                          if (called && !persisted.includes(arg.ref)) {
                            throw new Error("A non-persistent callback has been called before");
                          }
                          called = true;
                          target.postMessage({
                            type: "RESULT_CALLBACK",
                            id,
                            func: {
                              args: params,
                              ref: arg.ref
                            }
                          });
                        };
                      })();
                    }
                    return arg;
                  }));
                }
              }
            }
            Promise.resolve(result).then((r) => {
              const transferList = [];
              checkAndAppendtoTransferable(r, transferList);
              target.postMessage({
                type: "RESULT_SUCCESS",
                id,
                result: r
              }, transferList);
            }, (error) => {
              target.postMessage({
                type: "RESULT_ERROR",
                id,
                error
              });
            });
          } catch (error) {
            target.postMessage({
              type: "RESULT_ERROR",
              id,
              error
            });
          } finally {
          }
        }
        break;
      case "ACTION_DISPOSE":
        {
          const index = persisted.indexOf(event.data.ref);
          if (index > -1) {
            persisted.splice(index, 1);
          }
        }
        break;
    }
  };
  target.addEventListener("message", listener);
  return {
    dispose: () => {
      target.removeEventListener("message", listener);
      proxies.delete(target);
    }
  };
}
const mixer = {
  mixAudio(streams) {
    return mixAudioByFormat(streams);
  }
};
proxy(mixer);
