零、涉及到的技术,Api,名词等
大家可以自行在
MDN
上搜索查阅
AudioContext
AudioBufferSourceNode
AnalyserNode
ArrayBuffer
TypeArray – Uint8Array等XMLHttpRequest
Canvas
requestAnimationFrame
一、技术分析 – 基本思路
- 1.播放音频
- 2.在音频播放的时候拿到实时数据
- 3.在Canvas上按一定规则画出
二、下载一个音频
首先手写一段xml请求方法
我习惯使用promise来封装请求,方便进行异步编程,更好的利用async和await来进行异步同步等操作
// 加载音频文件
function loadSound(url) {
	return new Promise((resolve) => {
		const request = new XMLHttpRequest(); //建立一个请求
		request.open('GET', url, true); //配置好请求类型,文件路径等
		request.responseType = 'arraybuffer'; //配置数据返回类型
		// 一旦获取完成,对音频进行进一步操作,比如解码
		request.onload = () => {
			resolve(request.response);
		}
		request.send();
	});
}
复制代码写一个init的异步函数。并在里面加载音频
// 弄个函数,方便异步编程
async function init() {
	const arrayBuffer = await loadSound("https://yun.duiba.com.cn/aurora/assets/3457521d415e67cd2311a0df0ac4152439e75de7.mp3");
	audioBufferSourceNode.buffer = audioBuffer;
}
init();
复制代码三、播放一个音频
在全局变量中创建AudioContext对象和音频播放节点,可以用于播放音频
// 兼容
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
// 创建音频播放节点
const audioBufferSourceNode = audioContext.createBufferSource();
audioBufferSourceNode.connect(audioContext.destination);    // 连接到AudioContext对象
复制代码在init函数中使用AudioContext将ArrayBuffer转为AudioBuffer用于音频播放
并绑定给AudioBufferSourceNode
/**
 * ArrayBuffer 转 AudioBuffer
 * @param arrayBuffer
 * @returns {Promise}
 */
function bufferToAudio(arrayBuffer) {
	return new Promise((resolve, reject) => {
		audioContext.decodeAudioData(
			arrayBuffer,
			(res) => {
				resolve(res);
			},
			(err) => {
				reject(err);
			}
		);
	});
}
// 弄个函数,方便异步编程
async function init() {
	const arrayBuffer = await loadSound("https://yun.duiba.com.cn/aurora/assets/3457521d415e67cd2311a0df0ac4152439e75de7.mp3");
	// 把arrayBuffer转换成audioBuffer
	const audioBuffer = await bufferToAudio(arrayBuffer);
	// 绑定音频对象
	audioBufferSourceNode.buffer = audioBuffer;
}
复制代码写一个播放按钮
<button onclick="play()">播放</button>
<script>
    function play() {
        if (audioBufferSourceNode.isStart) {
            audioBufferSourceNode.isStart = false;
            audioBufferSourceNode.stop();   // 暂停音频
        } else {
            audioBufferSourceNode.isStart = true;
            audioBufferSourceNode.start(0); // 从0开始播放音频
        }
    }
</script>
复制代码打开网页,点击按钮发现又美妙的歌声传出
要学神仙~ 驾鹤飞天~
点石成金~ 妙不可言~
四、音频分析器
在全局变量中创建音频音频分析器,并和音频对象连接
// 创建音频分析器,连接音频分析器
const analyser = audioContext.createAnalyser();
audioBufferSourceNode.connect(analyser);
analyser.fftSize = 2048;    // 表示单次数据的长度,只能是2的n次方
// 设置好fftSize之后可以拿到frequencyBinCount
const bufferLength = analyser.frequencyBinCount;
// 使用frequencyBinCount来创建一个Uint8Array,用于装数据
const dataArray = new Uint8Array(bufferLength);
复制代码通过analyser.getByteTimeDomainData可以将当前数据填充在dataArray中
analyser.getByteTimeDomainData(dataArray);
复制代码五、拿到实时数据在Canvas上按规则画出
创建一个Canvas
<canvas id="myCanvas" width="450" height="450"></canvas>
复制代码写一个draw函数在里面写绘画逻辑
这个网上抄来的,随便找一段好看的就行
绑定在requestAnimationFrame上每帧调用
在init之后直接调用draw
// canvas
const canvas = document.getElementById("myCanvas");
const canvasCtx = canvas.getContext("2d");
function draw() {
	requestAnimationFrame(draw);    // 循环调用
	analyser.getByteTimeDomainData(dataArray);  // 将当前数据填充在dataArray中
	canvasCtx.fillStyle = 'rgb(200, 200, 200)';
	canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
	canvasCtx.lineWidth = 2;
	canvasCtx.strokeStyle = 'rgb(0, 0, 0)';
	canvasCtx.beginPath();
	const sliceWidth = canvas.width * 1.0 / bufferLength;
	let x = 0;
	for (let i = 0; i < bufferLength; i++) {
		const v = dataArray[i] / 128.0;
		const y = v * canvas.height / 2;
		if (i === 0) {
			canvasCtx.moveTo(x, y);
		} else {
			canvasCtx.lineTo(x, y);
		}
		x += sliceWidth;
	}
	canvasCtx.lineTo(canvas.width, canvas.height / 2);
	canvasCtx.stroke();
}
init();
draw();
复制代码© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
    






















![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)
