如何用 vanilla javascript 绘制音频频谱?
How to draw audio spectrum with vanilla javascript?
我需要使用 vanilla javascript 从用户的媒体文件中绘制 canvas 上的音频频谱。但是,我无法解决那个问题。因为,每个人都使用 savesurfer.js.
我确实在网络音频上使用了 createAnalyser API。但是,'CreateAnalyser' 无法获取用户媒体文件的频率。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<input type="file" id="file">
<canvas id="canvas" width="500" height="250"></canvas>
<script>
// draw an oscilloscope of the current audio source
var canvas = document.getElementById('canvas');
var canvasCtx = canvas.getContext('2d');
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
var audio = null;
document.getElementById('file').addEventListener('change', function(e) {
var audioCtx = new AudioContext();
var file = e.target.files[0];
var fileName = file.name;
var fileReader = new FileReader();
var audio = new Audio(fileName);
var analyser = audioCtx.createAnalyser();
fileReader.onload = function(e) {
var buffer = e.target.result;
var source = audioCtx.createBufferSource();
audioCtx.decodeAudioData(buffer, (buffer) => {
source.loop = true;
var offlineAudioCtx = new OfflineAudioContext(buffer);
offlineAudioCtx.startRendering().then(function(buffer) {
source.buffer = buffer;
source.connect(analyser);
source.connect(audioCtx.destination);
var dataArray = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteTimeDomainData(dataArray);
console.log(dataArray);
});
});
}
fileReader.readAsArrayBuffer(file);
});
</script>
</body>
</html>
您在这里遗漏了一些东西。首先,你没有连接到分析器节点的输入,所以你需要做一些类似
的事情
source.connect(analyser);
您现在应该得到非常量输出。
您可能不想在每个事件上都创建一个新的 AudioContext(和 AnalyserNode)。每一种你只需要一个。
您可能还想在每个事件中多次调用 analyser.getByteTimeDomainData()
,但这没关系。还有,时空数据的实际长度是fftSize
,而不是frequencyBinCount
。您在这里所做的只是复制可用时域数据的一半。也许这也可以满足您的需求。
我需要使用 vanilla javascript 从用户的媒体文件中绘制 canvas 上的音频频谱。但是,我无法解决那个问题。因为,每个人都使用 savesurfer.js.
我确实在网络音频上使用了 createAnalyser API。但是,'CreateAnalyser' 无法获取用户媒体文件的频率。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<input type="file" id="file">
<canvas id="canvas" width="500" height="250"></canvas>
<script>
// draw an oscilloscope of the current audio source
var canvas = document.getElementById('canvas');
var canvasCtx = canvas.getContext('2d');
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
var audio = null;
document.getElementById('file').addEventListener('change', function(e) {
var audioCtx = new AudioContext();
var file = e.target.files[0];
var fileName = file.name;
var fileReader = new FileReader();
var audio = new Audio(fileName);
var analyser = audioCtx.createAnalyser();
fileReader.onload = function(e) {
var buffer = e.target.result;
var source = audioCtx.createBufferSource();
audioCtx.decodeAudioData(buffer, (buffer) => {
source.loop = true;
var offlineAudioCtx = new OfflineAudioContext(buffer);
offlineAudioCtx.startRendering().then(function(buffer) {
source.buffer = buffer;
source.connect(analyser);
source.connect(audioCtx.destination);
var dataArray = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteTimeDomainData(dataArray);
console.log(dataArray);
});
});
}
fileReader.readAsArrayBuffer(file);
});
</script>
</body>
</html>
您在这里遗漏了一些东西。首先,你没有连接到分析器节点的输入,所以你需要做一些类似
的事情source.connect(analyser);
您现在应该得到非常量输出。
您可能不想在每个事件上都创建一个新的 AudioContext(和 AnalyserNode)。每一种你只需要一个。
您可能还想在每个事件中多次调用 analyser.getByteTimeDomainData()
,但这没关系。还有,时空数据的实际长度是fftSize
,而不是frequencyBinCount
。您在这里所做的只是复制可用时域数据的一半。也许这也可以满足您的需求。