HTML5 getUserMedia/AudioContext 打造音谱图形化

需求是分析音频,用图形化展示。

思路:

  1、回想当年使用的播放器,如XX静听 一般就2种图形化展示 一个是条形柱 一个是波纹

  2、分析数据转化成图像 这个是canvas常用的,之前做过的canvas分析图像数据,做滤镜做变形都是一把好手,这里当然 图形化也交给canvas了。

  3、既然是分析音频,那当然要将音频转化成数据,才可以进行分析,而关于音频的HTML API 就有 audio标签 ,而麦克风访问就有getUserMedia了。什么?你问我咋知道这个api的?我只能告诉你 去查MDN 、W3C 这类网站...

首先我们要得到音频数据,这里我们用了2个途径得到,一个是音频流,一个是麦克风

1、api兼容

window.AudioContext = (window.AudioContext || window.webkitAudioContext || window.mozAudioContext);
window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame;
try {
    audioCtx = new AudioContext;
    console.log(‘浏览器支持AudioContext‘);
} catch(e) {
    console.log(‘浏览器不支持AudioContext‘, e);
};

2、得到麦克风数据

//开始监听
if (navigator.getUserMedia) {
    console.log(‘浏览器支持getUserMedia‘);
    apiMedia.className = "checked";
    navigator.getUserMedia(
    // 我们只获取麦克风数据,这里还可以设置video为true来获取摄像头数据
    {
        audio: true
    },
    onSccess, onErr)
} else {
    console.log(‘浏览器不支持getUserMedia‘);
    apiMedia.className = "false";
};

通过onSccess来得到数据,介入分析

// Success callback
function onSccess(stream) {
    //将声音输入对像
    source = audioCtx.createMediaStreamSource(stream);
    source.connect(analyser);
    analyser.connect(distortion);
    distortion.connect(biquadFilter);
    biquadFilter.connect(convolver);
    convolver.connect(gainNode);
    gainNode.connect(audioCtx.destination);

    visualize();//分析音频
}

同样,文件的也是一样的

if (mediaSetting == "file") {
    loadFile();
    //得到数据源
    source=audioCtx.createMediaElementSource(audio);
    //连接节点
    source.connect(analyser);
    analyser.connect(distortion);
    distortion.connect(gainNode);
    gainNode.connect(audioCtx.destination);
}
visualize();//分析音频

得到了数据,接下来就交个canvas君吧

//波纹1
if (visualSetting == "wave1") {
    analyser.fftSize = 2048;
    var bufferLength = analyser.fftSize;
    console.log(bufferLength);
    var dataArray = new Uint8Array(bufferLength);
    canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);

    draw = function() {
        drawVisual = requestAnimationFrame(draw);
        analyser.getByteTimeDomainData(dataArray);

        canvasCtx.fillStyle = ‘#000‘;
        canvasCtx.fillRect(0, 0, WIDTH, HEIGHT);
        canvasCtx.lineWidth = 2;
        canvasCtx.strokeStyle = ‘#4aeb46‘;
        canvasCtx.beginPath();

        var sliceWidth = WIDTH * 1.0 / bufferLength;
        var x = 0;

        for (var i = 0; i < bufferLength; i++) {
            var v = dataArray[i] / 128.0;
            var y = v * 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();
    };
    draw();
}
//circle
else if (visualSetting == "circle") {
    // analyser.fftSize = 1024;
    // var bufferLength = analyser.fftSize;
    // var dataArray = new Uint8Array(bufferLength);
    analyser.fftSize = 128;
    var frequencyData = new Uint8Array(analyser.frequencyBinCount);
    var count = analyser.frequencyBinCount;
    var circles = [];
    var circleMaxWidth = (HEIGHT*0.66) >> 0;
    canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);
    canvasCtx.lineWidth = 1;

    for(var i = 0; i < count; i++ ){
        circles.push(i/count*circleMaxWidth)
    }

    draw = function() {
        canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);
        analyser.getByteFrequencyData(frequencyData);
        drawVisual = requestAnimationFrame(draw);
        for(var i = 0; i < circles.length; i++) {
            var v = frequencyData[i] / 128.0;
            var y = v * HEIGHT / 2;
            var circle = circles[i];
            canvasCtx.beginPath();
            canvasCtx.arc(WIDTH/2,HEIGHT/2, y/2, Math.PI * 2, false);
            canvasCtx.stroke()
        }                        

    };
    draw();
}
//柱形条
else if (visualSetting == "bar") {
    analyser.fftSize = 256;
    var bufferLength = analyser.frequencyBinCount;
    console.log(bufferLength);
    var dataArray = new Uint8Array(bufferLength);
    canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);

    var gradient = canvasCtx.createLinearGradient(0, 0, 0, 200);
    gradient.addColorStop(1, ‘#0f0‘);
    gradient.addColorStop(0.5, ‘#ff0‘);
    gradient.addColorStop(0, ‘#f00‘);
    var barWidth = 10;
    var gap = 2; //间距
    var capHeight = 2;//顶部高度
    var capStyle = ‘#fff‘;
    var barNum = WIDTH / (barWidth + gap); //bar个数
    var capYPositionArray = [];
    var step = Math.round(dataArray.length / barNum); 

    draw = function() {
        drawVisual = requestAnimationFrame(draw);
        analyser.getByteFrequencyData(dataArray);
        canvasCtx.clearRect(0, 0, WIDTH, HEIGHT);

        for (var i = 0; i < barNum; i++) {
            var value = dataArray[i * step];
            if (capYPositionArray.length < Math.round(barNum)) {
                capYPositionArray.push(value);
            };
            canvasCtx.fillStyle = capStyle;
            //顶端帽子
            if (value < capYPositionArray[i]) {
                canvasCtx.fillRect(i * 12, HEIGHT - (--capYPositionArray[i]), barWidth, capHeight);
            } else {
                canvasCtx.fillRect(i * 12, HEIGHT - value, barWidth, capHeight);
                capYPositionArray[i] = value;
            };
            canvasCtx.fillStyle = gradient;//渐变
            canvasCtx.fillRect(i * 12 , HEIGHT - value + capHeight, barWidth, HEIGHT-2); //绘制bar
        }
    };
    draw();
}

完整代码 github

时间: 2024-11-10 20:25:17

HTML5 getUserMedia/AudioContext 打造音谱图形化的相关文章

基于Java Web的图形化电网线损计算

引言 在各种电力系统应用软件中, 电力图形化表达的重要组成部分.鉴于目前各种电力系统大多数为B/S结构, 而基于浏览器的矢量图编辑和展示技术已成为当下的热门课题.电力系统的发展迫切需要推出一种图形标准来避免重复的劳动和不同厂商图形格式之间的不兼容. 文献中阐述了多比图形控件在电力系统软件领域的应用及其关键问题,并且指出多比图形控件可以提升基于 Web的电力系统软件图形化的特性,不过对于基于多比图形控件的图形系统如何构建以及如何有效的将多比图形控件应用到电力系统软件中在文中并没有深入探讨.本文将集

信息图形化的一些看法

1. 信息图形化的意义:        在信息无处不在的时代,人们对信息的接收将更加懒惰,人们只想花最少的时间来阅读最有价值的信息. 因此,更易识易记,更轻松阅读,直观,感知易,更适合于移动阅读.快速传达的图形化信息将成为信息传播的主流形态.    信息图形化的特点:简明直观,生动悦读,准确可信,通用易识. 2. 信息图形化的设计原则:    简明易懂,更有效的信息传达(归纳梳理信息,找出最重要的信息数据):    直观生动,更有趣的信息传达(将枯燥无味的信息用生动的图形层次清晰地表现出来): 

JS图形化插件利器组件系列 —— Gojs组件

阅读目录 一.组件效果预览 二.初次接触 1.Gojs简介 2.使用入门 三.综合效果 1.自定义流程的使用 2.工业流程图 四.总结 正文 前言:之前分享过两篇关于流程画图的前端组件,使用的jsPlumb.这个组件本身还不错,使用方便.入门简单.轻量级,但是使用一段时间下来,发现一些弊病,比如组件不太稳定,初始进入页面的时候连线的样式有时会乱掉,刷新页面之后才能恢复正常,而且连线样式比较单一,容易让人产生视觉疲劳,加之最近公司在大力推行所谓的“工业4.0”,除了对自动化控制要求的提高之外,对这

几款开源的图形化Redis客户端管理软件

您的评价: 收藏该经验 阅读目录 Redis Desktop Manager Redis Client Redis Studio 原文  http://ourjs.com/detail/555975b9329934463f00000f Redis是一个超精简的基于内存的键值对数据库(key-value),一般对并发有一定要求的应用都用其储存session,乃至整个数据库. 参见: node.js与redis结合使用 . 不过它公自带一个最小化的命令行式的数据库管理工具,有时侯使用起来并不方便.不

升级_开阔视野之Oracle图形化升级(dbca建库后升级)—10.2.0.1.0升为10.2.0.5.0

***********************************************声明***********************************************************************  原创作品,出自 "深蓝的blog" 博客,欢迎转载,转载时请务必注明出处,否则追究版权法律责任. 表述有错误之处,请您留言或邮件([email protected])指明,不胜感激. 本文转载必须保留此处:http://blog.csdn.net

python+QT designer 做图形化界面EXE程序

1.安装python 2.安装QT designer 或QT creator 3.打开QT designer 绘制你想要的图形化界面 类似这样 之后将文件保存,以ui后缀形式保存 4.下载安装pyside 直接easy_install 或pip安装 可能会保存,我安装的时候,提示 msvc 版本问题 查看许多国外论坛后,可以选择,pyside网站下载 对应Python版本的 whl安装包,下载成功之后,进入对应目录路径,直接 pip install  *.whl    *为包名 安装成功 5.将

Linux 图形化操作

//Linux图形化操作 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <curses.h> /*文件链接时需要加载curses共享库文件*/ int main(int arg, char *args[]) { //开启图形模式 initscr(); //不回显(不在屏

高可用(HA)集群的搭建 --图形化搭建(针对rhel6.5)

高可用(HA)集群的搭建 --图形化搭建(针对rhel6.5) 实验环境:iptables selinux关闭,三台主机做好解析 实验主机IP: 172.25.0.251 172.25.0.2 172.25.0.3 高可用集群包括RHCS,pacemaker+lvs,heartbeat,keepalievd. 在做实验前,先了解RHCS套件,6以下才有,7就取消了. 一些服务进程的含义如下: Luci/ricci>>web方式的集群管理(配置)工具: Ccs>>集群配置服务,(例如

PySide——Python图形化界面入门教程(六)

PySide——Python图形化界面入门教程(六) ——QListView和QStandardItemModel 翻译自:http://pythoncentral.io/pyside-pyqt-tutorial-qlistview-and-qstandarditemmodel/ 上一个教程中,我们讨论了Qt的QListWidget类,它用来实现简单的单列列表框(list boxes).然而,我们还需要更加灵活的widget来实现列表,Qt为此提供了QListView 来实现多种多样的项.它是一