使用 Tone.js,我可以获得代表通过我的扬声器播放的音频的原始 PCM 数据吗?

问题描述 投票:0回答:0

我需要获取一个表示音频文件(wav 文件数据)的字节数组,并制作一个新的字节数组来表示相同的 wav 文件,但音高会增加。这听起来很简单,但显然绝非如此。我尝试自己做这件事,但我缺乏数学技能,甚至无法遵循任何做这件事的指导方针。

使用库 Tone.js,我可以通过几行代码来提高音频的音调。问题是音频只是从我的扬声器播放,我需要那个音频的实际数据。

我知道 Tone.js 使用的是 Web Audio API,当我使用 Web Audio API 时,播放音频看起来有点像这样。

let source = this.audioCtx.createBufferSource();

// this.audioBuffer is an AudioBuffer.
source.buffer = this.audioBuffer;

// Logs the first PCM float32 value of the sources buffer, which for my data is 0.012939848005771637.
// This data is retrieved from an actual .wav file using audioContext.decodeAudioData()
console.log(this.audioBuffer.getChannelData(0)[0]);

// Honestly, not 100% sure exactly what this is doing. I know it's needed though.
source.connect(this.audioCtx.destination);

// Calling the start() method will play the audio.
source.start();

该代码的主要收获是三件事。

  1. 有一个源是使用 audioContexts createBufferSource() 方法创建的 AudioBufferSourceNode。
  2. 如果您对该源缓冲区属性调用 getChannelData(),您将检索实际的 PCM 数据。同样,这就是我想要做的,获取实际的 PCM 数据。
  3. source.start() 将是扬声器播放音频之前调用的最后一件事。

我的想法是,如果我深入研究 Tone.js 源代码,并找到调用播放音频的 start() 方法的代码,我就可以使用 getChannelData() 和查看从我的扬声器播放的音频,当使用来自 Tone.js 的 PitchShift 效果时,它是我音频的调高版本。

花了一些时间,但我最终在 ToneBufferSource.ts 文件中找到了我要找的东西。在 ToneBufferSource 类的顶部定义了一个 start() 函数,在该函数中有一个看起来像这样的代码,以及许多其他代码。

// These logs are mine
console.log(this._source);
console.log(this._source.buffer.getChannelData(0)[0]);

// This plays the audio.
this._source.start(computedTime, computedOffset);

我的第一个日志告诉我 this._source 确实是一个 AudioBufferSourceNode,问题是当我从 getChannelData 记录第一个 float32 数据时,它与我的非音调数据相同,0.012939848005771637。如果我在数组中记录第 10 个或第 100 个值,它与 unpitched 数据数组的第 10 个或第 100 个值相同。基本上,即使我通过扬声器听到的是音调增加的音频,但缓冲区源中的数据是普通数据吗?那么,真的,是什么给了? Tone.js 如何提高音调但来源相同?

然后我发现 Tone.js 正在使用标准化音频上下文库,它是实际处理 AudioContext、AudioBufferSourceNode 等的库。即使我在上面的段落中指出:this._source 是一个 AudioBufferSourceNode,它实际上不是。

你可以在图中看到有一个_context 属性,但是普通的AudioBufferSourceNode 没有_context 属性,只有一个context 属性。还有另一个属性叫做 _nativeAudioBufferSourceNode,这是实际的 AudioBufferSourceNode。

无论如何,所有这一切都说明了我随后挖掘了标准化音频上下文代码,寻找它的 source.start() 方法来分析来自扬声器的数据,就像我在上面所做的那样。这是我发现的……在工厂 udio-buffer-source-node-constructor.js

// Again, I put this log here. It's not in the source code...
console.log(this._nativeAudioBufferSourceNode.buffer.getChannelData(0)[0]);
this._nativeAudioBufferSourceNode.start(when, offset, duration);

记录源缓冲区中的第一个 float32 的日志再次为 0.012939848005771637,与未倾斜的数据完全相同。无论音高变化如何,它都是一样的,无论我做

const pitch = new PitchShift(8).toDestination();
还是
const pitch = new PitchShift(-1).toDestination();
都是一样的。数据不会改变以表示来自我的扬声器的实际不同声音。

有没有办法获取代表我通过扬声器听到的音频的数据?

javascript web-audio-api pcm pitch-shifting tonejs
© www.soinside.com 2019 - 2024. All rights reserved.