Web Audio API之手把手教你用web api处理声音信号:可视化音乐demo
1.Web Audio API 介绍
Web Audio API 提供了在Web上控制音频的一个非常有效通用的系统 ,这些通用系统通俗的讲就是我们可以利用Web Audio API提供的各种方法操作各种源中的声音,处理声音,使声音可视化等。
要使用Web Audio API,我们还是先来简单的了解一下它的工作流程:
- 创建音频环境(eg. AudioContext..)
- 在音频环境里创建源 — 例如
, 振荡器, 流(eg. navigator.getUserMedia/createMediaElementSource..)
- 创建效果节点,例如混响、双二阶滤波器、平移、压缩(Web Audio API 提供一些简单的滤波器或者延时器等,可以制作一个简单的混音工具)
- 为音频选择一个目地,例如你的系统扬声器
- 连接源到效果器,以及效果器和目地(分析和可视化eg. AnalyserNode)
其兼容性如下:
桌面端:
浏览器 | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari (WebKit) |
支持版本 | 14 | 23 | 未实现 | 15 | 6 |
移动端:
浏览器 |
Android |
Chrome |
Firefox Mobile (Gecko) |
Firefox OS |
IE Phone |
Opera Mobile |
Safari Mobile |
---|---|---|---|---|---|---|---|
支持版本 | 未实现 | 28 | 25 | 1.2 | 未实现 | 未实现 | 6 |
2.示例代码
"talking is cheap , show me the codes."
我知道各位看官并不想听什么时域频域变换,什么傅立叶变换,什么web audio api原理,那我就废话不多说,直接放码过来了,先看看效果再来给大家解释。
尽情复制粘贴,然后拿个现代一点的浏览器跑一下(用IE的请点右上角红叉,谢谢)。
注意:audio标签的src属性内容请自己在本机找一个浏览器支持的声音源格式。
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8" />
- <meta name="Author" contect="GabrielChen">
- <meta name="keywords" contect="Web Audio API">
- <title>Web Audio API 学习</title>
- <script>
- var canvas;
- var ctx;
- var audioContext;
- var analyser;
- var mic;
- function init() {
- canvasOne = document.getElementById('canvasOne');
- ctx = canvasOne.getContext("2d");
- canvasTwo = document.getElementById('canvasTwo');
- ctx2 = canvasTwo.getContext("2d");
- }
- navigator.getMedia = ( navigator.getUserMedia ||
- navigator.webkitGetUserMedia ||
- navigator.mozGetUserMedia ||
- navigator.msGetUserMedia);
- navigator.getMedia ( { audio: true }, function (stream) {
- audioContext = new (window.AudioContext || window.webkitAudioContext);
- mic = audioContext.createMediaStreamSource(stream);
- analyser= audioContext.createAnalyser();
- analyser.fftSize = 256;
- mic.connect(analyser);
- drawSpectrum();
- },function(){});
- function drawSpectrum() {
- var WIDTH = canvasOne.width;
- var HEIGHT= canvasOne.height;
- var array = new Uint8Array(128);
- analyser.getByteFrequencyData(array);
- ctx.clearRect(0, 0, WIDTH, HEIGHT);
- ctx2.clearRect(0, 0, 800, 800);
- for ( var i = 0; i < (array.length); i++ ){
- var value = array[i];
- ctx.fillRect(i*5,HEIGHT-value,3,HEIGHT);
- }
- for ( var i = 0; i < (array.length); i++ ){
- var value = array[i];
- ctx2.beginPath();
- ctx2.arc(300,300,value,0,360,false);
- ctx2.lineWidth=5;
- ctx2.strokeStyle="rgba("+value+","+value+",0,0.2)";
- ctx2.stroke();//画空心圆
- ctx2.closePath();
- }
- requestAnimationFrame(drawSpectrum);
- };
- </script>
- <style>
- #canvasOne {
- border: 1px solid #ddd;
- }
- </style>
- </head>
- <body onload="init();">
- <h1>从audio源获取声音</h1>
- <audio src="./Fatbros.ogg" controls="controls" id="audio">你的浏览器不支持audio标签</audio>
- <h1>audio读取声音</h1>
- <canvas id="canvasFormAudio" width="640"></canvas>
- <h1>频域图模仿</h1>
- <canvas id="canvasOne" width="640"></canvas>
- <h1>圆形声波图</h1>
- <canvas id="canvasTwo" width="800" height="800"></canvas>
- <script type="text/javascript">
- var context1;
- var source;
- var analyserfa;
- var canvasFormAudio;
- var ctxfa;
- canvasFormAudio = document.getElementById('canvasFormAudio');
- ctxfa = canvasFormAudio.getContext("2d");
- try {
- context1 = new (window.AudioContext || window.webkitAudioContext);
- } catch(e) {
- throw new Error('The Web Audio API is unavailable');
- }
- analyserfa=context1.createAnalyser();
- window.addEventListener('load', function(e) {
- var audio =document.getElementById("audio");
- var source = context1.createMediaElementSource(audio);
- source.connect(analyserfa);
- analyserfa.connect(context1.destination);
- drawSpectrumfa();
- }, false);
- function drawSpectrumfa() {
- var WIDTH = canvasFormAudio.width;
- var HEIGHT= canvasFormAudio.height;
- var array = new Uint8Array(128);
- analyserfa.getByteFrequencyData(array);
- ctxfa.clearRect(0, 0, WIDTH, HEIGHT);
- for ( var i = 0; i < (array.length); i++ ){
- var value = array[i];
- ctxfa.fillRect(i*5,HEIGHT-value,3,HEIGHT);
- }
- requestAnimationFrame(drawSpectrumfa);
- }
- </script>
- </body>
- </html>
3.代码分析
我们从body部分入手分析
- <body onload="init();">
- <h1>从audio源获取声音</h1>
- <audio src="./Fatbros.ogg" controls="controls" id="audio">你的浏览器不支持audio标签</audio>
- <h1>audio读取声音</h1>
- <canvas id="canvasFormAudio" width="640"></canvas>
- <h1>频域图模仿</h1>
- <canvas id="canvasOne" width="640"></canvas>
- <h1>圆形声波图</h1>
- <canvas id="canvasTwo" width="800" height="800"></canvas>
用onload属性调用初始化函数init(),主要在页面生成之后初始化一些变量,避免读不到相关DOM。
- function init() {
- canvasOne = document.getElementById('canvasOne');
- ctx = canvasOne.getContext("2d");
- canvasTwo = document.getElementById('canvasTwo');
- ctx2 = canvasTwo.getContext("2d");
- }
第一块canvas:从audio源获取声音
首先一个audio标签,在本机选定一个src,设置controls属性代表浏览器显示播放器控制页面,设置id为audio。
再设置一个id为"canvasFormAudio"的画布canvas。
- <audio src="./Fatbros.ogg" controls="controls" id="audio">你的浏览器不支持audio标签</audio>
- <h1>audio读取声音</h1>
- <canvas id="canvasFormAudio" width="640"></canvas>
获取声音源以及绘图
- //直接从audio处理音频源,声明一些必要的变量
- var context1;
- var source;
- var analyserfa;
- var canvasFormAudio;
- var ctxfa;
- //初始化画布
- canvasFormAudio = document.getElementById('canvasFormAudio');
- ctxfa = canvasFormAudio.getContext("2d");
//建立一个音频环境,因为浏览器实现不同,做了一点兼容性处理- try {
- context1 = new (window.AudioContext || window.webkitAudioContext);
- } catch(e) {
- throw new Error('The Web Audio API is unavailable');
- }
- //建立一个分析器
- analyserfa=context1.createAnalyser();
- window.addEventListener('load', function(e) {
- // 从audio标签获取声音源 source
- var audio =document.getElementById("audio");
- var source = context1.createMediaElementSource(audio);
- source.connect(analyserfa);
- analyserfa.connect(context1.destination);
- //调用绘图函数
- drawSpectrumfa();
- }, false);
//绘图函数- function drawSpectrumfa() {
- var WIDTH = canvasFormAudio.width;
- var HEIGHT= canvasFormAudio.height;
- var array = new Uint8Array(128);
- //复制当前的频率值到一个无符号数组中
- analyserfa.getByteFrequencyData(array);
- //clearRect(矩形左上角x坐标,矩形左上角y坐标,清除矩形的宽,清除矩形的高)
- ctxfa.clearRect(0, 0, WIDTH, HEIGHT);
- //循环生成长条矩形
- for ( var i = 0; i < (array.length); i++ ){
- var value = array[i];
- //fillRect(矩形左上角x坐标,矩形左上角y坐标,矩形宽,矩形高)
//这里我们的array一共有128组数据,所以我们当时canvas设置的宽度为5*128=640- ctxfa.fillRect(i*5,HEIGHT-value,3,HEIGHT);
- }
- //根据浏览器频率绘图或者操作一些非css效果
- requestAnimationFrame(drawSpectrumfa);
- }
第二块:频域图模仿和圆形声波图
这两个图的音源都是利用浏览器调用电脑麦克风取得,所以一定要同意浏览器请求的麦克风权限。
绘图区域
- <h1>频域图模仿</h1>
- <canvas id="canvasOne" width="640"></canvas>
- <h1>圆形声波图</h1>
- <canvas id="canvasTwo" width="800" height="800"></canvas>
初始化init()函数、从麦克风获取音源和绘图函数
- var canvas;
- var ctx;
- var audioContext;
- var analyser;
- var mic;
- //初始化两个画布的函数,声明为2d绘图
- function init() {
- canvasOne = document.getElementById('canvasOne');
- ctx = canvasOne.getContext("2d");
- canvasTwo = document.getElementById('canvasTwo');
- ctx2 = canvasTwo.getContext("2d");
- }
- //getMedia调用参数如下,返回一个多媒体流
//constraints可选{ video: true, audio: true },代表获取多媒体的类型
//var stream = navigator.getUserMedia(constraints, successCallback, errorCallback);- navigator.getMedia = ( navigator.getUserMedia ||
- navigator.webkitGetUserMedia ||
- navigator.mozGetUserMedia ||
- navigator.msGetUserMedia);
- navigator.getMedia ( { audio: true }, function (stream) {
- audioContext = new (window.AudioContext || window.webkitAudioContext);
- //返回一个多媒体流
- mic = audioContext.createMediaStreamSource(stream);
- //creates an AnalyserNode 创建一个分析节点
- analyser= audioContext.createAnalyser();
- //fftsize默认值2048,是快速傅立叶变换用于频域分析的值,必须为2的幂,而我们得到的数据通常为其的一半,下面会说道
- analyser.fftSize = 256;
- mic.connect(analyser);
//调用绘图函数- drawSpectrum();
- },function(){});
- //圆形声波绘图和矩形绘图
- function drawSpectrum() {
- var WIDTH = canvasOne.width;
- var HEIGHT= canvasOne.height;
- //长度为128无符号数组用于保存getByteFrequencyData返回的频域数据
- var array = new Uint8Array(128);
- analyser.getByteFrequencyData(array);
//以下是根据频率数据画图,主要为canvas知识,不做详细解答- ctx.clearRect(0, 0, WIDTH, HEIGHT);
- ctx2.clearRect(0, 0, 800, 800);
- for ( var i = 0; i < (array.length); i++ ){
- var value = array[i];
- ctx.fillRect(i*5,HEIGHT-value,3,HEIGHT);
- }
- //ctx2.clearRect(700, 700, WIDTH, HEIGHT);
- for ( var i = 0; i < (array.length); i++ ){
- var value = array[i];
- ctx2.beginPath();
- ctx2.arc(300,300,value,0,360,false);
- ctx2.lineWidth=5;
- ctx2.strokeStyle="rgba("+value+","+value+",0,0.2)";
- ctx2.stroke();//画空心圆
- ctx2.closePath();
- }
- //
- requestAnimationFrame(drawSpectrum);
- };
4.最终效果
6.最新进展
文中的getMedia方法(getUserMedia)在chrome 47后已经不可以从非安全源访问(Insecure Origins),即http协议,.firefox还可以但不知道为什么有bug,几秒钟后就share设备失败。
现在chrome开发者可以使用以下方法继续在非安全源使用这个函数:
You can run chrome with the --unsafely-treat-insecure-origin-as-secure="example.com" flag (replacing "example.com"with the origin you actually want to test), which will treat that origin as secure for this session. Note that you also need to include the --user-data-dir=/test/only/profile/dir to create a fresh testing profile for the flag to work
7.参考
1.MDN
2.api接口查询
3.chrome
Web Audio API之手把手教你用web api处理声音信号:可视化音乐demo的更多相关文章
- 手把手教你把web应用丢到服务器上(单页应用+ 服务端渲染)
前两篇文章中,我分别介绍了框架的搭建利用vue-cli + vant搭建一个移动端开发模板,并且把项目中axios请求和vuex的用法做了简要的介绍如何在项目里管理好axios请求与vuex.在这两篇 ...
- 手把手教你入门web.xml:吃透监听器
监听器的原理: 被监听对象→对象拥有的事件→捕获到事件变化→监听器捕捉事件→监听器处理该事件 Web服务器上有4个范围,抛开page范围,还有request范围,session范围,applicati ...
- 手把手教你搭建WEB服务器和FTP服务器
注:本次教程的环境是在“Windows 10 PC中远程控制的Windows Server 2012 R2服务器”,你可以自己在自己电脑中安装虚拟机再安装Windows Server 2012 R2服 ...
- 手把手教你用Python网络爬虫获取网易云音乐歌曲
前天给大家分享了用Python网络爬虫爬取了网易云歌词,在文尾说要爬取网易云歌曲,今天小编带大家一起来利用Python爬取网易云音乐,分分钟将网站上的音乐down到本地. 跟着小编运行过代码的筒子们将 ...
- 【Web Audio API】 — 那些年的 web audio
转 TAT.Jdo:[Web Audio API] - 那些年的 web audio 这主题主要是早期对 web audio api的一些尝试,这里整理一下以便以后翻阅,如有错误,诚请指正. 在这之前 ...
- 手把手教你如何优雅的使用Aop记录带参数的复杂Web接口日志
前言 不久前,因为需求的原因,需要实现一个操作日志.几乎每一个接口被调用后,都要记录一条跟这个参数挂钩的特定的日志到数据库.举个例子,就比如禁言操作,日志中需要记录因为什么禁言,被禁言的人的id和各种 ...
- 【HTML5】Web Audio API打造超炫的音乐可视化效果
HTML5真是太多炫酷的东西了,其中Web Audio API算一个,琢磨着弄了个音乐可视化的demo,先上效果图: 项目演示:别说话,点我! 源码已经挂到github上了,有兴趣的同学也可以去st ...
- 关于HTML5音频——audio标签和Web Audio API各平台浏览器的支持情况
对比audio标签 和 Web Audio API 各平台浏览器的支持情况: audio element Web Audio API desktop browsers Chrome 14 Yes ...
- [Javascript] Intro to the Web Audio API
An introduction to the Web Audio API. In this lesson, we cover creating an audio context and an osci ...
随机推荐
- Attention注意力机制介绍
什么是Attention机制 Attention机制通俗的讲就是把注意力集中放在重要的点上,而忽略其他不重要的因素.其中重要程度的判断取决于应用场景,拿个现实生活中的例子,比如1000个人眼中有100 ...
- HADOOP docker(七):hive权限管理
1. hive权限简介1.1 hive中的用户与组1.2 使用场景1.3 权限模型1.3 hive的超级用户2. 授权管理2.1 开启权限管理2.2 实现超级用户2.3 实现hiveserver2用户 ...
- Python3 数据类型-集合
在Python中集合set是基本数据类型的一种,它有可变集合(set)和不可变集合(frozenset)两种.创建集合set.集合set添加.集合删除.交集.并集.差集的操作都是非常实用的方法. 集合 ...
- from module import 和 import 的区别
最近在用codecademy学python,遇到一些题目错误,小小记录一下 如from math import sqrt是把sqrt作为本文件的方法导入进来了,使用的时候只需要直接调用sqrt. 而如 ...
- 常用排序算法--java版
package com.whw.sortPractice; import java.util.Arrays; public class Sort { /** * 遍历一个数组 * @param sor ...
- JS DOM视频相关的知识
1.实现点击a标签改变图片时,如果a的href属性有一个目标网址,但是点击又必须跳转到另外一张图,往往会最后跳转到目标网址,可以在onclick事件函数中加入ruturn false,阻止跳转到页面. ...
- 【alpha】Scrum站立会议第2次....10.17
小组名称:nice! 小组成员:李权 于淼 杨柳 刘芳芳 项目内容:约跑app 1.任务进度 成员 已完成 今日完成 李权 数据库设计 消息发送代码实现 于淼 注册.登录界面,以及登录界面后台代码.发 ...
- 原生js移动端可拖动进度条插件
该插件最初的想法来自网上的一篇文章,直达链接:https://www.cnblogs.com/libin-1/p/6220056.html 笔者因为业务需要寻找到这个插件,然后拿来用之,发现各种不方便 ...
- 【Quartz.net】- Cron表达式
一.结构 corn从左到右(用空格隔开):秒 分 小时 月份中的日期 月份 星期中的日期 年份 二.各字段的含义 字段 允许值 允许的特殊字符 秒(Seconds) 0~59的整数 , - * / ...
- win7系统日志分支删除方法
这篇日志有问题,自己亲身尝试失败,这里只提供思路,谢谢(改天突破再做修改) 之前电脑装过德国的叫啥子软件来着,当时在系统自动创建了日志,后来软件卸载了,发现还是有这个日志主键,(我有强迫症)心里不爽, ...