DOMException при горячей загрузке процессора веб-аудио с помощью модулей WASM из BLOB-объекта? - PullRequest
0 голосов
/ 09 апреля 2019

Я пытаюсь загрузить динамические рабочие листы Web Audio с импортом модуля WASM, перенесенным из кода C ++, используя EMSCRIPTEN.

Я хочу манипулировать кодом рабочих листов в памяти, использовать Blob для создания объектов, вставлять их в виде модулей в рабочий аудиоканал и выполнять горячую замену.

Я следовал шаблону проектирования, предложенному в решении web-audio-samples, чтобы реализовать рабочие листы, которые импортируются как модуль WASM в рабочий лист.Кажется, это хорошо работает, когда код процессора находится в файле.

Горячая загрузка и замена рабочих листов из памяти без импорта внешних модулей WASM также, кажется, работают хорошо.

Так я создаю код для BLOB-объекта.Чтобы проиллюстрировать это, я использую файл simple-kernel.wasmmodule.js, скомпилированный с той же конфигурацией EMSCRIPTEN, что и пример шаблона проектирования WASM в web-audio-samples.

    const blobCode = () => {

      return `
      import Module from './simple-kernel.wasmmodule.js';
      import { RENDER_QUANTUM_FRAMES, MAX_CHANNEL_COUNT, HeapAudioBuffer } from '../lib/wasm-audio-helper.js';

      class WASMWorkletProcessor extends AudioWorkletProcessor {

        constructor() {
          super();

          // Allocate the buffer for the heap access. Start with stereo, but it can
          // be expanded up to 32 channels.
          this._heapInputBuffer = new HeapAudioBuffer(Module, RENDER_QUANTUM_FRAMES,
                                                      2, MAX_CHANNEL_COUNT);
          this._heapOutputBuffer = new HeapAudioBuffer(Module, RENDER_QUANTUM_FRAMES,
                                                      2, MAX_CHANNEL_COUNT);
          this._kernel = new Module.SimpleKernel();
        }

        process(inputs, outputs, parameters) {
        .
        .
        .
           return true;
        }
      }
      registerProcessor('wasm-worklet-processor', WASMWorkletProcessor);`;
}

И вот как яиспользуйте код с Blob для создания объекта и загрузки его в рабочий лист.

const workletHotLoading = async (context) => {

  const blob = new Blob([ blobCode() ], { type: "application/javascript; charset=utf-8" });

  const workletUrl = window.URL.createObjectURL(blob);

  await context.audioWorklet.addModule(workletUrl);

  const oscillator = new OscillatorNode(context);

  const wasmBlobWorkletNode = new AudioWorkletNode(context, 'wasm-worklet-processor');

  wasmBlobWorkletNode.onprocessorerror = (event) => {
    console.log(`An error from WASMWorkletProcessor.constructor() was detected.`);
  };

  oscillator.connect(wasmBlobWorkletNode).connect(context.destination);

  oscillator.start();
};

Я ожидал, что это будет работать, как это делают процессоры без импорта WASM или когда я загружаю их из файла.Если комментарий импортирует модуль и код модуля в конструкторе рабочего процесса и методе обработки, это работает.

Однако, горячая загрузка рабочего листа с импортом WASM не работает ... Когда я пытаюсь это сделать, я получаю "Ошибка при загрузке рабочего стола: DOMException" иникакой другой подсказки.

Я подозреваю, что это может быть немного наивно и что для этого может потребоваться более сложный, такой как динамический импорт ...

Я создал форк решения для веб-аудио-сэмпловгде я добавил небольшой пример проекта ( wasm-hot-loading ), который создает условия для иллюстрации проблемы.

Доступно здесь: https://github.com/mimic-sussex/web-audio-samples/tree/master/audio-worklet/design-pattern/wasm-hot-loading

Может кто-нибудь помочь пролить свет на то, в чем может быть проблема и возможно ли это?

Спасибо

1 Ответ

0 голосов
/ 23 апреля 2019

Проблема в том, что источник вашего Worklet Processor непрозрачен. Это означает, что ваш относительный импорт не может быть разрешен изнутри этого скрипта.

Чтобы обойти это, вам нужно использовать абсолютные URI.

Таким образом, вы должны переписать свой код, чтобы добавить правильный baseURI в ваши операторы импорта. Поскольку этот код вызывается с вашей главной js-страницы, вы можете затем создать содержимое этого BLOB-объекта в правильном формате, например, используя URL-конструктор и его второй параметр base .

const blobCode = () => {
    return `
import Module from "${
  // convert relative to absolute URL
  new URL('./simple-kernel.wasmmodule.js', location.href)
}";
import { RENDER_QUANTUM_FRAMES, MAX_CHANNEL_COUNT, HeapAudioBuffer } from "${
  new URL('../lib/wasm-audio-helper.js', location.href)
}";

class WASMWorkletProcessor extends AudioWorkletProcessor {

  constructor() {
    super();
[...]
 `
 };

console.log(blobCode());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...