从wav文件中读取样本

12

我正在尝试使用HTML5创建一个网页,该网页将从WAV文件中的样本数据存储到一个数组中。是否有办法使用JavaScript获取样本数据?我正在使用文件输入来选择WAV文件。

在JavaScript中,我已经添加了:

document.getElementById('fileinput').addEventListener('change', readFile, false);

但是我不知道在readFile中该怎么做。

编辑: 我尝试以ArrayBuffer的形式获取文件,将其传递给decodeAudioData方法,并从中获取typedArraybuffer。 这是我的代码:

var openFile = function(event) {
var input = event.target;
var audioContext = new AudioContext();

var reader = new FileReader();
reader.onload = function(){
var arrayBuffer = reader.result;
  console.log("arrayBuffer:");
  console.log(arrayBuffer);
  audioContext.decodeAudioData(arrayBuffer, decodedDone);

};
reader.readAsArrayBuffer(input.files[0]);
};
function decodedDone(decoded) {
var typedArray = new Uint32Array(decoded, 1, decoded.length);
  console.log("decoded");
  console.log(decoded);
  console.log("typedArray");
  console.log(typedArray);

for (i=0; i<10; i++)
{
    console.log(typedArray[i]);
}

}

typedArray的元素全部为0。是我创建typedArray的方式错误了还是我做了其他错误?

编辑: 我最终解决了这个问题。这是我的代码:

var openFile = function(event) {
var input = event.target;
var audioContext = new AudioContext();

var reader = new FileReader();
reader.onload = function(){
var arrayBuffer = reader.result;
  console.log("arrayBuffer:");
  console.log(arrayBuffer);
  audioContext.decodeAudioData(arrayBuffer, decodedDone);

};
reader.readAsArrayBuffer(input.files[0]);
};
function decodedDone(decoded) {

 var typedArray = new Float32Array(decoded.length);

typedArray=decoded.getChannelData(0);
console.log("typedArray:");
console.log(typedArray);

}

感谢您的回答!


我对此并不确定。可能是我错了,因为我甚至从未听说过dataURI这个术语,但它似乎是一种从网页元素中获取数据的方法。当我使用事件监听器时,我可以使用事件从wav文件中获取一些数据(标题等),但我似乎无法获取wav文件的时间域数据。我正在寻找一种获取样本值以创建类似均衡器的方法。当然,还有其他制作均衡器的方法,但我正在与其他人合作,他们需要将样本数据存储在数组中(最好切成固定大小的数组)。 - myName
所以如果我理解正确,您想获取音频的持续时间,您可以将其加载到音频标签中,并使用JS从那里获取持续时间,就像这样:http://codetheory.in/get-the-duration-of-an-audio-or-video-file-in-javascript/。 - Slugge
我不仅想要持续时间,还想获取wav文件中的时域数据,并将其放入一个数组中,其中每个元素是某一时刻的振幅。 - myName
1
我非常怀疑你能用 JavaScript 做到这一点,很可能需要更高级的编程语言。比如 Java、Python、C 或类似的语言。 - Slugge
dataURIs效率低下,不要使用它们。现在有blob URL可用。此外,Web音频API内置均衡器 :) - Touffy
显示剩余3条评论
3个回答

6
您需要学习很多关于Web API的内容才能实现它,但最终其实非常简单。
  1. 使用文件API获取ArrayBuffer格式的文件内容。
  2. 将其传递给Web Audio APIdecodeAudioData方法。
  3. 获得一个包含所需原始样本的类型化ArrayBuffer。

编辑:如果您想要实现均衡器,那么只需使用Audio API中的本地均衡器节点即可,否则您会浪费时间。根据您的波形文件长度,最好不要全部加载到内存中,而是创建一个从中读取的源,并将该源连接到均衡器节点。


谢谢,我会试一下。当我输入均衡器时,实际上是在谈论某种可视化工具。 - myName
好的,API 中还有一个本地分析器节点。你需要阅读大量的内容,但我相信你会发现它是一篇令人兴奋的文章。 - Touffy
我尝试过这个,但不确定是否正确。发送到decodeAudioData回调成功函数的变量是已解码的arraybuffer吗?另外,我该如何创建TypedArray? - myName
没事了,我搞定了。 callbackSuccess中的参数是AudioBuffer。 感谢你的回答。 - myName

1

这里有一个简单的代码示例,可以在JavaScript中从wav音频文件中获取Float32Array

let audioData = await fetch("https://example.com/test.wav").then(r => r.arrayBuffer());

let audioCtx = new AudioContext({sampleRate:44100});

let decodedData = await audioCtx.decodeAudioData(audioData); // audio is resampled to the AudioContext's sampling rate

console.log(decodedData.length, decodedData.duration, decodedData.sampleRate, decodedData.numberOfChannels);

let float32Data = decodedData.getChannelData(0); // Float32Array for channel 0

0

使用async函数封装Joe的代码可以解决问题,像这样:

async function readAudio(url) {
  let audioData = await fetch(url).then(r => r.arrayBuffer());
  let audioCtx = new AudioContext({sampleRate:8000});
  // audio is resampled to the AudioContext's sampling rate
  let decodedData = await audioCtx.decodeAudioData(audioData);
  console.log(decodedData.length, decodedData.duration,
             decodedData.sampleRate, decodedData.numberOfChannels);
  let float32Data = decodedData.getChannelData(0); // Float32Array for channel 0
  processAudio(float32Data);  // PCM Float32 is between -1 to +1
}

readAudio("Something.wav");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接