热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

HTML5canvas绘制音频,音乐可视化

效果技术nodeJs+express+http+fs实现环境搭建,读取歌曲并生成列表ajax获取

效果

效果示例

技术

  • nodeJs + express + http + fs 实现环境搭建,读取歌曲并生成列表
  • ajax 获取音频
  • AudioContext API 解析音频
  • canvas 绘制图形图像
  • requestAnimationFrame 调起动画

重点

canvas绘制、AudioContext API 应用
代码在 ‘public/Javascripts/index.js’ 中
本博文重点讲解实现过程中使用的 AudioContext 相关的 API
如果对 web audio API 很有兴趣,请参见 web audio API

AudioContext

音频处理的环境和上下文,可以控制它所包含的节点的创建,以及音频处理、音频解码操作,读取播放状态等。
做任何音频相关的事情之前都要先创建 AudioContext 对象,因为一切都发生在这个环境之中。

那么如何创建 AudioContext 这个环境呢?

const AC = new(window.AudioContext || window.webkitAudioContext)();

这个环境下包含许多非常重要的方法和属性,挑几个说说:

AudioBufferSourceNode:代表一个音频源,可以挂载一段写在内存中的音频数据,没有输入,有一个输出方法,可以利用 start 方法来调用,利用 stop 方法来关闭

const AudioBufferSourceNode = AC.createBufferSource(); //这里创建了个音频源
AudioBufferSourceNode.start([when [, offset [, duration]]); //安排声音在指定时间播放。没有指定时间,则声音立即开始播放。
AudioBufferSourceNode.buffer = buffer; //挂载一段内存中的音频片段,
AudioBufferSourceNode.stop([when]); //停止播放
AudioBufferSourceNode.onended = ()=>{} //当前音频播放完毕后的回调函数

这里需要注意一个事情:
AudioBufferSourceNode 只能被播放一次
GainNode :代表一个音量控制器,通过它可以控制输出音频的音量大小,一般取值0-1

const GainNode = AC.createGain()
GainNode.gain.value = 0.6

AnalyserNode :代表一个音频分析器,赋予了节点可以提供实时频率及时间域分析的信息

const AnalyserNode = AC.createAnalyser();
AnalyserNode.fftSize = number * 2 // FFT是离散傅里叶变换的快速算法,用于将一个信号变换到频域,
									//得到的值是32-2048之间的2的整数次倍,默认是2048。
console.log(AnalyserNode.frequencyBinCount) // number,通常代表要用于可视化的数据值的数量,值为 analyserNode.fftSize/2

AudioDestinationNode:表示音频的最终输出地址 - 通常为扬声器

const AudioDestinationNode = AC.destination

currentTime:当前音频环境播放时长

AC.currentTime

(关于 currentTime 我的理解和翻译过来的 API 解读文档有所不同),下图是翻译来的意思:
在这里插入图片描述
这张图是英文原文
在这里插入图片描述
英文的意思大概是用来调节音频播放、可视化时间戳等(scheduling audio playback, visualizing timelines),
所以我的理解是当前环境的播放时长,事实上在案例中我也实际使用了这个值,在音频开始播放前, AC.currentTime 始终为 0,并且音频环境被 suspend() 掉的时候,currentTime的值也不再变化,即被暂停掉了

decodeAudioData:这是一个方法,通常用于异步解码音频文件,被解码的文件是通过使用 responseType 为 arraybuffer 类型的 ajax 获取的,该方法只能作用于完整的音频文件

xhr.responseType = "arraybuffer"; //返回一段二进制数据
xhr.onload = function() { //类似onreadystatechange
    AC.decodeAudioData(this.response,(buffer)=>{
    	console.log(buffer) //解码后得到的文件,可以挂在到 AudioBufferSourceNode.buffer 上
    	console.log(buffer.duration) // 音频时间长度
	},(err) => {
        console.log(`errMessage:${err}`);
    });
}

resume:重新启动一个已被暂停的音频环境

AC.resume()

suspend:暂停音频内容的进度.暂时停止音频硬件访问和减少在过程中的CPU/电池使用.

AC.suspend()

这里还少了一个重要步骤,即将音频和音量控制器,音频分析器,播放器相互关联,这样他们才能够正常使用

AudioBufferSourceNode.connect(AnalyserNode );
AnalyserNode .connect(GainNode);
GainNode.connect(AudioDestinationNode ); 

梳理一下音乐播放的实现流程

  1. node 使用 fs 模块读取所有的歌曲并生成列表渲染到前端页面
  2. 当点击播放的时候,我们先查找本地缓存中是否有当前歌曲,有的话,我们创建一个音频环境进行播放,没有的话,我们则通过 ajax 获取到音频数据,然后通过 AC.decodeAudioData 解析成 buffer 存到缓存中,然后创建音频环境进行播放
  3. 在每次播放不同的歌曲之前,先调用 AC.suspend 停止当前播放的音乐,这样保证同一时间只有一首歌处于播放状态
  4. 如果是点击暂停/播放按钮,那么我们单纯的通过 resume/suspend 来控制当前音频的播放与暂停
  5. 播放的时长是通过 AC.currentTime 拿到的,总时长是 buffer.duration, 进度条是二者的比值
  6. 音量的控制通过 gainNode.gain.value 来控制
  7. 本地文件播放则是通过 fileReader.readAsArrayBuffer 将文件读取,然后依然通过 AC.decodeAudioData 解码来进行播放

canvas图形绘制

首先我们得到 AnalyserNode.frequencyBinCount,即可视化数据值,然后将其存为 Uint8Array 数组类型,

let arr = new Uint8Array(AnalyserNode.frequencyBinCount);

之后通过 getByteFrequencyData 方法将当前频率数据复制到传递给它的 uint8array 中,

AnalyserNode.getByteFrequencyData(arr);

得到的值大概是这样
在这里插入图片描述
这就是我们可视化音频需要的数据了,他是随着音频播放而不断变化的值,初始全部为 0 ,然后遍历这个数组,拿到数组中每一项的值,就是一组音谱条应该绘制的高度,看图就明白了
在这里插入图片描述
每一组音谱条其实就是一条有宽度的,带有渐变背景色的线,线的高度就是 arr[i], 这条线被平均分成了 n 个小方格,每个小方格的高度为 4,彼此间隔为 0.5,然后我们不断计算更新小方块和小红块的位置,通过 requestAnimationFrame 重新渲染就可以了。

最后附上代码地址,欢迎 star 和 issue。


推荐阅读
  • Webpack5内置处理图片资源的配置方法
    本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 关于CMS收集器的知识介绍和优缺点分析
    本文介绍了CMS收集器的概念、运行过程和优缺点,并解释了垃圾回收器的作用和实践。CMS收集器是一种基于标记-清除算法的垃圾回收器,适用于互联网站和B/S系统等对响应速度和停顿时间有较高要求的应用。同时,还提供了其他垃圾回收器的参考资料。 ... [详细]
  • 网络请求模块选择——axios框架的基本使用和封装
    本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 本文总结了在编写JS代码时,不同浏览器间的兼容性差异,并提供了相应的解决方法。其中包括阻止默认事件的代码示例和猎取兄弟节点的函数。这些方法可以帮助开发者在不同浏览器上实现一致的功能。 ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
  • JavaScript和HTML之间的交互是经由过程事宜完成的。事宜:文档或浏览器窗口中发作的一些特定的交互霎时。能够运用侦听器(或处置惩罚递次来预订事宜),以便事宜发作时实行相应的 ... [详细]
  • 用Vue实现的Demo商品管理效果图及实现代码
    本文介绍了一个使用Vue实现的Demo商品管理的效果图及实现代码。 ... [详细]
  • 通过Anaconda安装tensorflow,并安装运行spyder编译器的完整教程
    本文提供了一个完整的教程,介绍了如何通过Anaconda安装tensorflow,并安装运行spyder编译器。文章详细介绍了安装Anaconda、创建tensorflow环境、安装GPU版本tensorflow、安装和运行Spyder编译器以及安装OpenCV等步骤。该教程适用于Windows 8操作系统,并提供了相关的网址供参考。通过本教程,读者可以轻松地安装和配置tensorflow环境,以及运行spyder编译器进行开发。 ... [详细]
  • 本文介绍了利用ARMA模型对平稳非白噪声序列进行建模的步骤及代码实现。首先对观察值序列进行样本自相关系数和样本偏自相关系数的计算,然后根据这些系数的性质选择适当的ARMA模型进行拟合,并估计模型中的位置参数。接着进行模型的有效性检验,如果不通过则重新选择模型再拟合,如果通过则进行模型优化。最后利用拟合模型预测序列的未来走势。文章还介绍了绘制时序图、平稳性检验、白噪声检验、确定ARMA阶数和预测未来走势的代码实现。 ... [详细]
author-avatar
xinyaolin_857
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有