如何将高音频与 CSS 变化同步?
How to synchronize high audio frequencies with CSS changes?
我正在创建一个与音乐互动的程序,我试图将鼓点或低音与 CSS 同步,因此在每个高频声音中,背景都会及时改变.
我的第一个想法是创建一个音频频谱,以了解它如何与播放的声音相互作用。在这种情况下,我使用 Web Audio API analyserNode.fftSize
获取音频文件中的所有频率点并使用 <canvas>
创建频谱
const audioCtx = new AudioContext();
//Create audio source
//Here, we use an audio file, but this could also be e.g. microphone input
const audioEle = new Audio();
audioEle.src = "good-day.mp3"; //insert file name here
audioEle.autoplay = true;
audioEle.preload = "auto";
const audioSourceNode = audioCtx.createMediaElementSource(audioEle);
//Create analyser node
const analyserNode = audioCtx.createAnalyser();
analyserNode.fftSize = 256;
const bufferLength = analyserNode.frequencyBinCount;
const dataArray = new Float32Array(bufferLength); // this is where all the frequencies are stored
然后,使用这个 dataArray
和那个时刻的所有频率,我 运行 一个条件说: 如果频率高于 X,将背景更改为蓝色:
if (Math.max(...dataArray) + 100 > 70) { // +- 70 is a good number for that specific song
await changeBgColor();
}
最终结果似乎有效,但并不完美,因为 if
条件每秒 运行s 60 次,有时由于声音或音频文件中的另一个声音干扰了低音的频率。
我不知道是否有什么东西真的可以对此有用。我尝试使用 ToneJS and wadJS 但我无法使用这些库。
我想知道用声音进行这些 CSS 迭代的最佳方法是什么。
用于测试此代码的歌曲是:Ice Cube - It Was A Good Day (good-day.mp3)
完整代码:
index.html
<!DOCTYPE html>
<body id="bd">
<script>
const audioCtx = new AudioContext();
//Create audio source
//Here, we use an audio file, but this could also be e.g. microphone input
const audioEle = new Audio();
audioEle.src = "good-day.mp3"; //insert file name here
audioEle.autoplay = true;
audioEle.preload = "auto";
const audioSourceNode = audioCtx.createMediaElementSource(audioEle);
//Create analyser node
const analyserNode = audioCtx.createAnalyser();
analyserNode.fftSize = 256;
const bufferLength = analyserNode.frequencyBinCount;
const dataArray = new Float32Array(bufferLength);
//Set up audio node network
audioSourceNode.connect(analyserNode);
analyserNode.connect(audioCtx.destination);
//Create 2D canvas
const canvas = document.createElement("canvas");
canvas.style.position = "absolute";
canvas.style.top = 0;
canvas.style.left = 0;
canvas.width = window.innerWidth;
canvas.height = 300;
document.body.appendChild(canvas);
const canvasCtx = canvas.getContext("2d");
canvasCtx.clearRect(0, 0, canvas.width, canvas.height);
async function draw() {
const changeBgColor = () => {
document.getElementById("bd").style["background-color"] = "blue";
};
const sleep = () => {
// setTimeout(() => null, 1000)
console.log("bass sound");
};
//Schedule next redraw
requestAnimationFrame(draw);
//Get spectrum data
analyserNode.getFloatFrequencyData(dataArray);
//Draw black background
canvasCtx.fillStyle = "rgb(0, 0, 0)";
canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
//Draw spectrum
const barWidth = (canvas.width / bufferLength) * 2.5;
let posX = 0;
document.getElementById("bd").style["background-color"] = "red";
if (Math.max(...dataArray) + 100 > 70) { // +- 70 is a good number for that specific song
await changeBgColor();
}
for (let i = 0; i < bufferLength; i++) {
const barHeight = (dataArray[i] + 100) * 2;
// console.log(barHeight)
canvasCtx.fillStyle = `rgb(${Math.floor(
barHeight + 100
)}, 255, ${Math.floor(barHeight + 200)})`;
canvasCtx.fillRect(
posX,
canvas.height - barHeight / 2,
barWidth,
barHeight / 2
);
posX += barWidth + 1;
}
}
draw();
</script>
</body>
我对这段代码的引用是 MDN 中关于 AnalyserNode
的文档
这里是关于如何将音乐频率检索到数组并将其传递给 CSS 的快速演示。
这是非常基础的,有很多问题,但也许是进一步制作适当动画的良好开端。
const audio = document.getElementById('music');
audio.load();
audio.play();
const ctx = new AudioContext();
const audioSrc = ctx.createMediaElementSource(audio);
const analyser = ctx.createAnalyser();
audioSrc.connect(analyser);
analyser.connect(ctx.destination);
analyser.fftSize = 256;
const bufferLength = analyser.frequencyBinCount;
const frequencyData = new Uint8Array(bufferLength);
setInterval(async () => {
analyser.getByteFrequencyData(frequencyData);
let dataArray = Object.values(frequencyData);
//if (Math.max(...dataArray) + 100 > 70) { // +- 70 is a good number for that specific song
window.requestAnimationFrame(
await changeBgColor(dataArray)
)
//}
}, 100);
const changeBgColor = (dataArray) => {
console.log(dataArray)
let color1 = dataArray.slice(0,3).map((a) => a / 100) // Smaller numbers are darker
let color2 = dataArray.slice(3,6)
let color3 = dataArray.slice(6,9)
document.body.style.background = `linear-gradient(90deg, rgba(${color1}, 1) 0%, rgba(${color2},0.2) 35%, rgba(${color3},1) 100%)`
}
<audio id="music" src="https://cdn.glitch.com/02dcea11-9bd2-4462-ac38-eeb6a5ad9530%2F331_full_beautiful-minds_0171_preview.mp3?1522829295082" crossorigin="use-URL-credentials" controls="true"></audio>
<hr>
<span id="console"></span>
我正在创建一个与音乐互动的程序,我试图将鼓点或低音与 CSS 同步,因此在每个高频声音中,背景都会及时改变.
我的第一个想法是创建一个音频频谱,以了解它如何与播放的声音相互作用。在这种情况下,我使用 Web Audio API analyserNode.fftSize
获取音频文件中的所有频率点并使用 <canvas>
const audioCtx = new AudioContext();
//Create audio source
//Here, we use an audio file, but this could also be e.g. microphone input
const audioEle = new Audio();
audioEle.src = "good-day.mp3"; //insert file name here
audioEle.autoplay = true;
audioEle.preload = "auto";
const audioSourceNode = audioCtx.createMediaElementSource(audioEle);
//Create analyser node
const analyserNode = audioCtx.createAnalyser();
analyserNode.fftSize = 256;
const bufferLength = analyserNode.frequencyBinCount;
const dataArray = new Float32Array(bufferLength); // this is where all the frequencies are stored
然后,使用这个 dataArray
和那个时刻的所有频率,我 运行 一个条件说: 如果频率高于 X,将背景更改为蓝色:
if (Math.max(...dataArray) + 100 > 70) { // +- 70 is a good number for that specific song
await changeBgColor();
}
最终结果似乎有效,但并不完美,因为 if
条件每秒 运行s 60 次,有时由于声音或音频文件中的另一个声音干扰了低音的频率。
我不知道是否有什么东西真的可以对此有用。我尝试使用 ToneJS and wadJS 但我无法使用这些库。
我想知道用声音进行这些 CSS 迭代的最佳方法是什么。
用于测试此代码的歌曲是:Ice Cube - It Was A Good Day (good-day.mp3)
完整代码:
index.html
<!DOCTYPE html>
<body id="bd">
<script>
const audioCtx = new AudioContext();
//Create audio source
//Here, we use an audio file, but this could also be e.g. microphone input
const audioEle = new Audio();
audioEle.src = "good-day.mp3"; //insert file name here
audioEle.autoplay = true;
audioEle.preload = "auto";
const audioSourceNode = audioCtx.createMediaElementSource(audioEle);
//Create analyser node
const analyserNode = audioCtx.createAnalyser();
analyserNode.fftSize = 256;
const bufferLength = analyserNode.frequencyBinCount;
const dataArray = new Float32Array(bufferLength);
//Set up audio node network
audioSourceNode.connect(analyserNode);
analyserNode.connect(audioCtx.destination);
//Create 2D canvas
const canvas = document.createElement("canvas");
canvas.style.position = "absolute";
canvas.style.top = 0;
canvas.style.left = 0;
canvas.width = window.innerWidth;
canvas.height = 300;
document.body.appendChild(canvas);
const canvasCtx = canvas.getContext("2d");
canvasCtx.clearRect(0, 0, canvas.width, canvas.height);
async function draw() {
const changeBgColor = () => {
document.getElementById("bd").style["background-color"] = "blue";
};
const sleep = () => {
// setTimeout(() => null, 1000)
console.log("bass sound");
};
//Schedule next redraw
requestAnimationFrame(draw);
//Get spectrum data
analyserNode.getFloatFrequencyData(dataArray);
//Draw black background
canvasCtx.fillStyle = "rgb(0, 0, 0)";
canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
//Draw spectrum
const barWidth = (canvas.width / bufferLength) * 2.5;
let posX = 0;
document.getElementById("bd").style["background-color"] = "red";
if (Math.max(...dataArray) + 100 > 70) { // +- 70 is a good number for that specific song
await changeBgColor();
}
for (let i = 0; i < bufferLength; i++) {
const barHeight = (dataArray[i] + 100) * 2;
// console.log(barHeight)
canvasCtx.fillStyle = `rgb(${Math.floor(
barHeight + 100
)}, 255, ${Math.floor(barHeight + 200)})`;
canvasCtx.fillRect(
posX,
canvas.height - barHeight / 2,
barWidth,
barHeight / 2
);
posX += barWidth + 1;
}
}
draw();
</script>
</body>
我对这段代码的引用是 MDN 中关于 AnalyserNode
的文档这里是关于如何将音乐频率检索到数组并将其传递给 CSS 的快速演示。
这是非常基础的,有很多问题,但也许是进一步制作适当动画的良好开端。
const audio = document.getElementById('music');
audio.load();
audio.play();
const ctx = new AudioContext();
const audioSrc = ctx.createMediaElementSource(audio);
const analyser = ctx.createAnalyser();
audioSrc.connect(analyser);
analyser.connect(ctx.destination);
analyser.fftSize = 256;
const bufferLength = analyser.frequencyBinCount;
const frequencyData = new Uint8Array(bufferLength);
setInterval(async () => {
analyser.getByteFrequencyData(frequencyData);
let dataArray = Object.values(frequencyData);
//if (Math.max(...dataArray) + 100 > 70) { // +- 70 is a good number for that specific song
window.requestAnimationFrame(
await changeBgColor(dataArray)
)
//}
}, 100);
const changeBgColor = (dataArray) => {
console.log(dataArray)
let color1 = dataArray.slice(0,3).map((a) => a / 100) // Smaller numbers are darker
let color2 = dataArray.slice(3,6)
let color3 = dataArray.slice(6,9)
document.body.style.background = `linear-gradient(90deg, rgba(${color1}, 1) 0%, rgba(${color2},0.2) 35%, rgba(${color3},1) 100%)`
}
<audio id="music" src="https://cdn.glitch.com/02dcea11-9bd2-4462-ac38-eeb6a5ad9530%2F331_full_beautiful-minds_0171_preview.mp3?1522829295082" crossorigin="use-URL-credentials" controls="true"></audio>
<hr>
<span id="console"></span>