音频可视化
音频可视化使用了WebAudio的功能,仅在支持WebAudio的平台有效。
import { _decorator, AudioClip, Component, instantiate, Label, lerp, Node, UITransform, v3 } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('MusicView')
export class MusicView extends Component {
@property(Label)
tip: Label = null;
@property([AudioClip])
bgms: AudioClip[] = [];
@property(Node) root: Node = null;
audioBufferSourceNode:AudioBufferSourceNode;
analyser:AnalyserNode;
dataArray:Uint8Array;
audioClip: AudioClip = null;
isPlaying:boolean = false;
bgm_index:number = 0;
copyNode:Node = null;
start() {
this.audioClip = this.bgms[0];
this.bgm_index = 0;
this.tip.string = 'BGM - ' + this.bgm_index;
this.initAudio();
}
initAudio(){
//取自节点作为克隆对象
if(!this.copyNode){
this.copyNode = instantiate(this.root.children[0]);
}
//清空root
this.root.removeAllChildren();
//示例化 item
for(let i = 0;i < 23;i++){
let item = instantiate(this.copyNode);
this.root.addChild(item);
item.setPosition(v3(-220 + i * 20, 0, 0))
}
}
changeBgm(){
this.bgm_index += 1;
if(this.bgm_index >= this.bgms.length){
this.bgm_index = 0;
};
this.audioClip = this.bgms[this.bgm_index];
this.tip.string = 'BGM - ' + this.bgm_index;
this.initAudio();
if(this.isPlaying){
this.audioBufferSourceNode.stop();
this.makeAnalyser();
}
}
makeAnalyser(){
let AudioContext = window.AudioContext;
// audioContext 只相当于一个容器。
let audioContext = new AudioContext();
// 要让 audioContext 真正丰富起来需要将实际的音乐信息传递给它的。
// 也就是将 AudioBuffer 数据传递进去。
// 以下就是创建音频资源节点管理者。
this.audioBufferSourceNode = audioContext.createBufferSource();
this.audioBufferSourceNode.loop = true;
// 将 AudioBuffer 传递进去。这里 cocos 封装的比较深
const audioBuffer = (this.audioClip as any)._player._player._audioBuffer;
this.audioBufferSourceNode.buffer = audioBuffer;
// 创建分析器。
this.analyser = audioContext.createAnalyser();
// 精度设置
this.analyser.fftSize = 256;
// 在传到扬声器之前,连接到分析器。
this.audioBufferSourceNode.connect(this.analyser);
// 连接到扬声器。
this.analyser.connect(audioContext.destination);
// 开始播放
this.audioBufferSourceNode.start(0);
}
onClickPlayBtn() {
if (this.isPlaying) {
// 停止播放
this.audioBufferSourceNode.stop();
this.isPlaying = false;
} else {
this.makeAnalyser();
this.isPlaying = true;
}
}
update(deltaTime: number) {
// 等待准备好
if (!this.analyser) return;
// 建立数据准备接受数据
this.dataArray = new Uint8Array(this.analyser.frequencyBinCount);
// 分析结果存入数组。
this.analyser.getByteFrequencyData(this.dataArray);
this.draw(this.dataArray);
}
draw(dataArray: Uint8Array) {
// 精度 256 解析数组长度为一半 128 长,这里我根据音乐挑选展示 60 个数据
for (let i = 0; i < 30; i++) {
// 在 10 - 70 每隔 2 个取音频数据展示,数据大小乘以 2 作为节点高度
let h = dataArray[10 + i * 2] * 2;
if (h < 10) h = 10;
let node = this.root.children[i];
// 插值手段,数据以 0.4 为阶段逼近目标值,高度变的不那么生硬
const height = node.getComponent(UITransform).height;
node.getComponent(UITransform).height = lerp(height, h, 0.4);
}
}
checkEnd(){
//if(this.audioBufferSourceNode.loop = true;)
}
}
浙公网安备 33010602011771号