2

我一直在尝试使用 postMessage 从一个 AudioWorkletProcessor 中提取输入,然后将该输入插入另一个 AudioWorkletProcessor。

我设法将 Float32Array 放入第二个 AudioWorkletProcessor 处理方法,但 RingBuffer 似乎不起作用。

我不知道如何检测 process 方法内部的错误或与 RingBuffer 相关的任何错误。

我得到静音输出,控制台中没有错误。

我需要知道如何将提取的 Float32Array 传递给 ring-buffer-worklet-processor 输出。

先感谢您。

编辑:在我添加( outputChannelCount: [2] )到 ringBufferWorkletNode 选项后,我开始在输出中获取音频,但根本不清楚。

const ringBufferWorkletNode = new AudioWorkletNode(
          audioCtx,
          "ring-buffer-worklet-processor",
          {
            outputChannelCount: [2],
            processorOptions: {
              kernelBufferSize: audioCtx.sampleRate,
              channelCount: 2,
            },
          }
        );

主线程:

navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(async (stream) => {

   const source = audioCtx.createMediaStreamSource(stream);

   await audioCtx.audioWorklet.addModule("http://localhost:3003/lib/audio-processor.js");

   await audioCtx.audioWorklet.addModule("http://localhost:3003/lib/ring-buffer-worklet- 
   processor.js");

   const voiceNode = new AudioWorkletNode(audioCtx, "audio-processor");


   const ringBufferWorkletNode = new AudioWorkletNode(audioCtx, "ring-buffer-worklet-processor",{
            // EDIT: added outputChannelCount
            outputChannelCount: [2],
       
            processorOptions: {
              kernelBufferSize: audioCtx.sampleRate / 2,        // 48000/2
              channelCount: 2,
            },
          }
        );

   voiceNode.port.onmessage = (e) => {
             ringBufferWorkletNode.port.postMessage(e.data);
           };
   ringBufferWorkletNode.port.onmessage = (e) => {
             console.log(e.data);
           };

   source.connect(voiceNode);

   ringBufferWorkletNode.connect(audioCtx.destination);

}

音频处理器.js

class AudioProcessor extends AudioWorkletProcessor {
  constructor(...args) {
    super(...args);
  }

  process(inputList, outputList, parameters) {
    this.port.postMessage(inputList[0]);

    return true;
  }
}

registerProcessor("audio-processor", AudioProcessor);

ring-buffer-worklet-processor.js

import Module from "./variable-buffer-kernel.wasmmodule.js";
import { HeapAudioBuffer, RingBuffer } from "./wasm-audio-helper.js";

class RingBufferWorkletProcessor extends AudioWorkletProcessor {

  static get parameterDescriptors() {
    return [
      {
        name: "input",
        defaultValue: null,
      },
    ];
  }

  constructor(options) {
    super();

    this._kernelBufferSize = options.processorOptions.kernelBufferSize;
    this._channelCount = options.processorOptions.channelCount;

    // RingBuffers for input and output.
    this._inputRingBuffer = new RingBuffer(
      this._kernelBufferSize,
      this._channelCount
    );
    this._outputRingBuffer = new RingBuffer(
      this._kernelBufferSize,
      this._channelCount
    );

    // For WASM memory, also for input and output.
    this._heapInputBuffer = new HeapAudioBuffer(
      Module,
      this._kernelBufferSize,
      this._channelCount
    );
    this._heapOutputBuffer = new HeapAudioBuffer(
      Module,
      this._kernelBufferSize,
      this._channelCount
    );

    // WASM audio processing kernel.
    this._kernel = new Module.VariableBufferKernel(this._kernelBufferSize);

    this.inputData = null;

    this.port.onmessage = this.onmessage.bind(this);

  }
  onmessage = (e) => {
    const { data } = e;
    if (data) {
      this.inputData = data;
    } else {
      this.inputData = null;
    }
  };

  process(inputs, outputs, parameters) {

    let output = outputs[0];
    let input = this.inputData;

    // AudioWorkletProcessor always gets 128 frames in and 128 frames out. Here
    // we push 128 frames into the ring buffer.
    if (input) {
      this.port.postMessage(input);
    // I get : (2) [Float32Array(128), Float32Array(128)] in console full with numbers not 0s
      this._inputRingBuffer.push(input);

      // Process only if we have enough frames for the kernel.
      if (this._inputRingBuffer.framesAvailable >= this._kernelBufferSize) {
        // Get the queued data from the input ring buffer.
        this._inputRingBuffer.pull(this._heapInputBuffer.getChannelData());

        // This WASM process function can be replaced with ScriptProcessor's
        // |onaudioprocess| callback funciton. However, if the event handler
        // touches DOM in the main scope, it needs to be translated with the
        // async messaging via MessagePort.
        this._kernel.process(
          this._heapInputBuffer.getHeapAddress(),
          this._heapOutputBuffer.getHeapAddress(),
          this._channelCount
        );

        // Fill the output ring buffer with the processed data.
        this._outputRingBuffer.push(this._heapOutputBuffer.getChannelData());
      }

      // Always pull 128 frames out. If the ring buffer does not have enough
      // frames, the output will be silent.
      this._outputRingBuffer.pull(output);
    }
    return true;
  }
}

registerProcessor("ring-buffer-worklet-processor", RingBufferWorkletProcessor);

来自主线程的 console.log 示例:

   ringBufferWorkletNode.port.onmessage = (e) => {
             console.log(e.data);
           };
(2) [Float32Array(128), Float32Array(128)]
0: Float32Array(128)
[0 … 99]
0: -0.00013565909466706216
1: -0.00004953467214363627
2: -0.00008576592517783865
3: -0.00005288537431624718
4: -0.000025271740014431998
5: -0.000051156635890947655
6: -0.00003429186836001463
7: -0.000021470399587997235
8: -0.000034319222322665155
9: -0.0000439783361798618
10: -0.000009586839041730855
11: -0.00003202698644599877
12: 0.000033984630135819316
13: -0.00002201009374402929
14: -0.00007097060733940452
15: 0.000004624932444130536
16: -0.00009633887384552509
17: 0.00000770429596741451
18: -0.00004159680975135416
19: -0.00012190178676974028
20: -0.00001845001861511264
21: -0.00008007502037798986
22: -0.00004237010216456838
23: -0.00001076792977983132
24: -0.00006972716801101342
25: -0.0000477194698760286
26: -0.000021934287360636517
27: -0.00009244760440196842
28: -0.000007403687050100416
29: 0.000007816993274900597
30: -0.00008117098332149908
31: -0.00003129038304905407
32: 0.00009489256626693532
33: 0.000023729033273411915
34: -0.000009693003448774107
35: -0.00003678350549307652
36: -0.00011439441732363775
37: -0.00003462867607595399
38: 0.000029057020583422855
39: -0.00003098553133895621
40: -0.00004036649261252023
41: -0.00001566937135066837
42: -0.00003948688390664756
43: -0.000021292273231665604
44: -0.000031062725611263886
45: -0.00006067131835152395
46: -0.00008801861258689314
47: -0.0000940829049795866
48: -0.000027806054276879877
49: 0.000005677926765201846
50: -0.00004410342808114365
51: -0.00005494384822668508
52: -0.00012077790597686544
53: -0.00005381474693422206
54: -0.00004889833144261502
55: -0.00006171152199385688
56: -0.00007169923628680408
57: -0.000027956590201938525
58: -0.0000925964122870937
59: -0.00008822995005175471
60: -0.00011014055053237826
61: -0.00009332459740107879
62: -0.00007393134728772566
63: -0.00009183597285300493
64: -0.000051114031521137804
65: -0.00009899734141072258
66: -0.00001619849535927642
67: -0.00006849400961073115
68: -0.00007494576129829511
69: -0.00004512929081101902
70: -0.00007846889639040455
71: -0.0000887925925781019
72: -0.00011394681496312842
73: -0.0000661616213619709
74: -0.00006388152542058378
75: -0.000028652870241785422
76: -0.000049569716793484986
77: -0.000008633718607597984
78: -0.00003698172440635972
79: -0.00007338733121287078
80: -0.00004050061761518009
81: -0.00011863364488817751
82: -0.00005003352271160111
83: 0.00009503970795776695
84: -0.000020715609934995882
85: -0.000040291022742167115
86: -0.00006244835822144523
87: -0.00013285929162520915
88: -0.00009266978304367512
89: -0.00015499485016334802
90: 0.000009959074304788373
91: -0.00002722918361541815
92: -0.000045168246288085356
93: 0.00005641198004013859
94: -6.97990401477e-7
95: -0.00008256734145106748
96: -0.00011380571231711656
97: -0.00010966734407702461
98: -0.00010636053775670007
99: -0.00009042541933013126
[100 … 127]
buffer: 
ArrayBuffer(512)
byteLength: 512
byteOffset: 0
length: 128
Symbol(Symbol.toStringTag): (...)
[[Prototype]]: TypedArray
1: Float32Array(128)
[0 … 99]
[100 … 127]
buffer: 
ArrayBuffer(512)
byteLength: 512
byteOffset: 0
length: 128
Symbol(Symbol.toStringTag): (...)
[[Prototype]]: TypedArray
length: 2
[[Prototype]]: Array(0)

这是我关注的 GitHub:https ://github.com/GoogleChromeLabs/web-audio-samples/tree/main/audio-worklet/design-pattern/wasm-ring-buffer

4

0 回答 0