Web Audio API getByteTimeDomainData returns flat 128(全为零)

Web Audio API getByteTimeDomainData returns flat 128 (all zero)

我正在使用 Web Audio API 只是显示麦克风 activity 指示灯以向用户显示他们的麦克风已连接并且正在接收输入。

这是一个 Angular 网络项目,我使用计时器通过 getByteTimeDomainData() 拍摄输入快照。

当我 运行 时,我拍摄的每张快照都是 128(零),无论我发出多少噪音。

代码:

private setupMicInputListener(stream: MediaStream): void {
    const threshold = 10;
    const timerSource = timer(0, 100);
    timerSource.subscribe((val) => {
      const audioLevel = this.getCurrentAverageMicInputLevel(stream);
      console.log(audioLevel);
      this.audioInputDetected = audioLevel > threshold;
    });
  }

  private getCurrentAverageMicInputLevel(stream: MediaStream): number {
    const audioContext = new window.AudioContext();
    const analyser = audioContext.createAnalyser();
    const microphone = audioContext.createMediaStreamSource(stream);
    microphone.connect(analyser);

    analyser.smoothingTimeConstant = 0.8;
    analyser.fftSize = 2048;
    const buffer = new Uint8Array(analyser.fftSize);
    analyser.getByteTimeDomainData(buffer);
    let values = 0;

    const length = buffer.length;
    for (let i = 0; i < length; i++) {
      values += (buffer[i]);
    }

    const averageLevel = values / length;

    return averageLevel;
  }

我读到如果它没有连接到输出,信号无处可去,但是当我尝试

microphone.connect(audioContext.destination)

我通过扬声器获得了疯狂的反馈。我知道我传入的流是正确的。在这段代码之外,我得到了用户设备,我可以观察到该设备是我的麦克风。我创建了一个 MediaStream 并在将流传递到此组件之前将我的麦克风音轨添加到其中。另外,当我使用上面的代码行时,我可以听到我在所有反馈中发出的声音。

我不熟悉 angular,但从代码来看,您似乎定期调用 getCurrentAverageMicInputLevel。这每次都会使用相应的 AnalyserNode 创建一个新的音频上下文。然后你立即要求时域数据的 2048 个样本。在这一点上,分析仪实际上从麦克风接收到任何数据的可能性很小,因此您只能得到 2048 个零的缓冲区。

要解决此问题,只需创建上下文、分析器(包括设置分析器的参数)和麦克风一次,也许在 setupMicInputListener 中。然后让 getCurrentAverageMicInputLevel 调用 getByteTimeDomainData。我想如果麦克风没有静音,您会看到非零值。

对于Chrome,一般来说,你确实需要有一个节点最终连接到目的地,但也有例外,分析器节点就是例外之一。但要确保输出完全没有连接到任何东西才能正常工作。