我一直在尝试AudioContext api,试图进行一些基本的可视化。就像其中一个五颜六色的条形上升和下降。
我用来自mdn的音频文章介绍了可视化效果,我还查看了一些chrome插件和codepens。而且我自己也做了一些实现。 而且不管我做什么,我不禁会注意到,由于frequencyData,我所有的竖线都倾向于从左向右倾斜。
我有点不明白为什么数据数组开头的值总是接近最大值(255)。我需要一些帮助来解决这个问题。 下面是我的一些代码:
function frequencyToIndex(freq, fftSize, sampleRate = 44100) {
let nyquist = sampleRate / 2;
let fftBin = fftSize /2;
let index = Math.round(freq / nyquist * fftSize)
if(index <= 0) return 0
if(index > fftBin) return fftBin
return index
}
function byteFrequencyAverage(analyser, frequencies, minHz, maxHz, norm = 255) {
let sampleRate = analyser.context.sampleRate
let fftSize = analyser.fftSize
let start = frequencyToIndex(minHz, fftSize, sampleRate)
let end = frequencyToIndex(maxHz, fftSize, sampleRate)
let count = end - start
let sum = 0
while(start < end) {
sum += frequencies[start]
start +=1
}
return count ? sum/count : 0
}
// https://www.teachmeaudio.com/mixing/techniques/audio-spectrum/
let bands = {
subbas:{
from: 20,
to: 60
},
bass: {
from: 61,
to: 250
},
lowmid: {
from: 251,
to: 500
},
mid: {
from: 501,
to: 2000
},
uppermid: {
from: 2001,
to: 4000
},
presence: {
from: 40001,
to: 6000
},
akward: {
from: 6001,
to: 8000
}
}
var Bars = (function(canvas) {
const WIDTH =canvas.width;
const HEIGHT =canvas.height;
let context = canvas.getContext('2d')
let audioCtx = new (window.AudioContext || window.webkitAudioContext)();
let analyser = audioCtx.createAnalyser();
let audio = document.querySelector("#soundcloud");
function initSource() {
let dataArray = new Uint8Array();
let bufferLength = 0;
let source = audioCtx.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(audioCtx.destination);
analyser.fftSize = 1024;
bufferLength = analyser.frequencyBinCount;
dataArray = new Uint8Array(bufferLength);
context.clearRect(0, 0, WIDTH, HEIGHT);
return { dataArray: dataArray, bufferLength: bufferLength }
}
function withAudioDetails(dataArray, bufferLength) {
return function draw() {
requestAnimationFrame(draw);
analyser.getByteFrequencyData(dataArray);
context.fillStyle = 'rgb(0, 0, 0)';
context.clearRect(0, 0, WIDTH, HEIGHT);
let freqs = Object.keys(bands)
.map(k => byteFrequencyAverage(analyser, dataArray, bands[k].from, bands[k].to))
.map(Math.floor)
let barWidth = 20;
let x = 0;
for(let i = 0; i < freqs.length; i++) {
context.fillStyle = `rgb(${freqs[i] + 100}, 50, 50)`
context.fillRect(x, HEIGHT - freqs[i], barWidth, freqs[i])
x += barWidth + 1;
}
// mdn example
// let barWidth = (WIDTH / bufferLength) * 2.5;
// let barHeight;
// let x = 0;
// for(let i = 0; i < bufferLength; i++) {
// barHeight = dataArray[i]/2;
// console.log(dataArray[i], i)
// context.fillStyle = 'rgb(' + (barHeight+100) + ',50,50)';
// context.fillRect(x,HEIGHT-barHeight/2,barWidth,barHeight);
// x += barWidth + 1;
// }
}
}
return {
initSource: initSource,
withAudioDetails: withAudioDetails
}
})
因此,当我运行此命令时,我只会得到4-5小节。和左边的火箭,右边的高度总是很低。这与我在手机上使用某些媒体播放器或说Linux上使用cava时所看到的完全不同。 我已附上图片Image from cava和Image from webpage进行比较。
我可以做的一件事是缩小高值并缩小低值。但是我不确定那是个好主意。
谢谢。