我正在尝试使用EMSCRIPTEN从C ++代码转换的WASM模块导入加载动态Web Audio工作片。
我想在内存中操作worklet代码,使用Blob创建对象,将它们作为模块注入音频工作组,然后热插拔它们。
我遵循了web-audio-samples解决方案中建议的设计模式,以实现将WASM模块导入到worklet中的worklet。当处理器代码在文件中时,这似乎很有效。
在没有外部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代码创建一个对象并将其加载到worklet中。
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导入的处理器,或者当我从文件加载它们时。如果在worklet构造函数和process方法中注释模块导入和模块代码,它就可以工作。
但是,使用WASM导入来加载一个worklet似乎没有工作......当我尝试这样做时,我得到“加载worklet时出错:DOMException”并且没有其他线索。
我怀疑这可能有点天真,它可能需要更复杂,如动态导入......
我创建了一个web-audio-samples解决方案的分支,我在其中添加了一个小样本项目(wasm-hot-loading),它创建了说明问题的条件。
任何人都可以帮助解释问题可能是什么以及这是否可行?
谢谢
FEED
问题是您的Worklet Processor的起源是不透明的。这意味着无法从此脚本中解析相对导入。
为了避免这种情况,您需要使用绝对URI。
因此,您必须重写代码才能将正确的baseURI添加到imports语句中。由于此代码是从主js页面调用的,因此您可以使用正确的格式构建此blob内容,例如使用URL constructor及其第二个参数库。
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());