从Blob热加载带有WASM模块的Web Audio Worklet处理器时,是否出现DOMException?

时间:2019-04-09 17:41:41

标签: javascript blob web-audio webassembly wasm-bindgen

我正在尝试使用从EMSCRIPTEN从C ++代码转译的WASM模块导入来加载动态Web Audio工作集。

我想操纵内存中的工作区代码,使用Blob创建对象,将它们作为模块注入音频工作区,然后热交换它们。

我遵循了web-audio-samples解决方案中建议的设计模式,以实现作为WASM模块导入到工作件中的工作件。当处理器代码在文件中时,这似乎工作良好。

在没有外部WASM模块导入的情况下从内存进行热加载和交换工作集似乎也可以很好地工作。

这就是我为Blob创建代码的方式。为了说明这一点,我使用了simple-kernel.wasmmodule.js,它的编译方式与Web-audio-samples中的WASM设计模式示例使用的EMSCRIPTEN配置相同。

    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导入的处理器一起使用,或者从文件中加载它们时起作用。如果在工作let构造函数和处理方法中注释模块导入和模块代码,则它将起作用。

但是,用WASM导入热加载工作集似乎无法正常工作...当我尝试这样做时,我收到“加载工作集时出错:DOMException” ,没有其他问题线索。

我怀疑这可能有点天真,并且可能需要更复杂的功能,例如动态导入...

我创建了一个网络音频样本解决方案的分支,在其中添加了一个小的样本项目( wasm-hot-loading ),该项目创建了说明问题的条件。

可在此处使用:https://github.com/mimic-sussex/web-audio-samples/tree/master/audio-worklet/design-pattern/wasm-hot-loading

任何人都可以帮助我们弄清楚问题可能是什么以及这是否可行?

谢谢

2 个答案:

答案 0 :(得分:0)

问题是您的Worklet Processor的原点是不透明的。 这意味着您不能从此脚本内部解析相对导入。

要避免这种情况,您需要使用绝对URI。

因此,您必须重写代码才能将正确的baseURI添加到import语句中。由于此代码是从您的主要js页面调用的,因此您可以使用正确的格式来构建此blob内容,例如,使用URL constructor及其第二个参数 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());

答案 1 :(得分:0)

我有一个类似的错误。仅当导入在工作集中时才引发Dom Exception。 该问题是由于Chrome扩展程序称为Web音频检查器 此扩展肯定会在工作区周围添加一些包装功能,因为未授权将导入调用到函数中,因此工作区导入会中断。 无论如何,卸载了扩展程序并解决了问题。