#angular #web-audio-api #webassembly #audio-worklet
#угловатый #web-audio-api #веб-сборка #аудио-рабочий лист
Вопрос:
Я использую Angular для разработки веб-приложения для видеоконференцсвязи. Я пытаюсь вызвать некоторые функции wasm в моем AudioWorkletProcessor
классе. Тем не менее, я совершенно зациклен на том, как передать модуль wasm в AudioWorkletProcessor
, а затем вызвать эти функции. Я смог создать экземпляр модуля wasm из js-файла, сгенерированного из emcc (используя command: emcc test.cpp -s WASM=1 -s MODULARIZE=1
), а затем попытался передать этот модуль через options.processorOptions
параметр при создании AudioWorkletNode
; однако, похоже, что объекты функций не могут быть переданы, поскольку это дает DataCloneError
. Есть ли лучший способ создания экземпляра модуля wasm и передачи его в процессор worklet, чтобы я мог использовать его функции?
Код audio.service.ts:
import { Injectable } from '@angular/core';
import { AudioContext, AudioWorkletNode } from 'standardized-audio-context';
import * as Module from '../../../assets/worklet/a.out.js'; // a.out.js is file generated by emcc
declare const WebAssembly: any;
@Injectable()
export class AudioService {
audioCtx = new AudioContext();
constructor() {}
async createNewSetting(track) {
const srcNode = this.audioCtx.createMediaStreamTrackSource(track);
const destNode = this.audioCtx.createMediaStreamDestination();
await this.audioCtx.resume();
await this.audioCtx.audioWorklet.addModule(
'./assets/worklet/spatial-processor.js'
);
// Instantiate the wasm module and put in path to file
const wasm = await Module({ locateFile: function(s) { return 'assets/worklet/' s; }});
// Will throw DataCloneError
const spatialNode = new AudioWorkletNode(
this.audioCtx,
'spatial-processor',
{ processorOptions: {
compiledModule: wasm
}}
);
// Connect the nodes
srcNode.connect(spatialNode);
spatialNode.connect(destNode);
// Return the updated audio stream
return destNode.stream.getTracks()[0];
}
}
Ответ №1:
Передача экземпляра модуля WASM рабочему (или AudioWorklet) невозможна. Это работает только тогда, когда модуль WASM скомпилирован, но еще не создан. В MDN есть пример, который показывает, как это сделать с обычным рабочим, но он работает так же, как и при использовании processorOptions
of an AudioWorkletProcessor
.
Идея состоит в том, чтобы использовать compileStreaming()
в основном потоке и instantiate()
в рабочем.
С другой стороны, также можно импортировать все непосредственно в AudioWorklet, как показано в этом примере. Однако я бы не рекомендовал этого делать, поскольку компиляция кода в аудиопотоке может привести к звуковому сбою.
https://googlechromelabs.github.io/web-audio-samples/audio-worklet/design-pattern/wasm/
Комментарии:
1. Ах, хорошо, это имеет смысл. Когда я выполняю метод compileStreaming () и создаю экземпляр () в worker, я получаю ошибку «Import # 0 module =»wasi_snapshot_preview1″: модуль не является объектом или функцией» ошибка. Я знаю, что js-файл, который создает emcc, заполняет функции в этом отсутствующем модуле, но поскольку я не могу использовать js-файл в процессоре, должен ли я сам заполнять отсутствующие методы модуля (через объект импорта, который передается в instantiate()), или есть болеевозможный способ приблизиться к этому?
2. Я не уверен, понял ли я ваш вопрос. Насколько я знаю, с emscripten это не так просто, потому что он создает некоторый код склеивания ( a.out.js file), который вызывает эти функции для вас. Это помогает?
3. Да, это помогает.