Home  >  Article  >  Web Front-end  >  Detailed explanation of HTML5 music visualization code

Detailed explanation of HTML5 music visualization code

黄舟
黄舟Original
2017-03-17 16:23:033612browse

I made an H5 music visualization in my spare time. The main part of the code is below. Contains comments for some AudioContext APIs.

  • AudioContext api part is equivalent to the raw material of the house.

musicVisualizer.ac = new(window.AudioContext || window.webkitAudioContext)();
//实例化一个音频类型window.AudioContext,后面是为了兼容Chrome浏览器


function musicVisualizer(obj) {
    this.source = null; //初始化音频资源变量
    this.analyser = musicVisualizer.ac.createAnalyser(); //这一步是非常重要的,createAnalyser()可以创建一个/AnalyserNode/用来获取音频的各项数据,实现音乐可视化
    this.size = obj.size; //这里是 index.js里面实例化原型的参数obj中的大小属性
    this.analyser.fftSize = this.size * 2;
    //fftsize(AnalyserNode的一个属性)是一个无符号长整型的值, 用于确定频域的 FFT (快速傅里叶变换) 的大小.fftSize 属性的值必须是从32到32768范围内的2的非零幂; 
    其默认值为2048.总之最后获取到的数组长度应该是fftSize值的一半,还应该保证它是以2为底的幂。
    this.xhr = new XMLHttpRequest();//这个就很熟悉了对于大家而言,创建ajax对象
    this.analyser.connect(musicVisualizer.ac.destination);
    //musicVisualizer.ac.destination是音频要最终输出的目标,所有节点中的最后一个节点应该再连接到musicVisualizer.ac.destination播放声音
    this.visualizer = obj.visualizer;
    //这里是 index.js里面实例化原型的参数obj中的canvas绘画音乐节点实现节奏可视化
    this.visualize();
}
musicVisualizer.prototype.load = function(url, fun) {
    this.xhr.abort();//停止正在进行的ajax请求
    this.xhr.open("GET", url);
    this.xhr.responseType = "arraybuffer";
    var self = this;
    this.xhr.onload = function() {
        fun(self.xhr.response);
    };
    this.xhr.send();
};
musicVisualizer.prototype.decode = function(arraybuffer, fun) {
    musicVisualizer.ac.decodeAudioData(arraybuffer, function(buffer) {
//decodeAudioData用于异步解码音频文件中的arrayBuffer数据
        fun(buffer);
    }, function(err) {
        console.log(err);
    });
};
musicVisualizer.prototype.stop = function() {
    this.source[this.source.stop ? "stop" : "noteOff"](0);
};
musicVisualizer.prototype.visualize = function() {
    var arr = new Uint8Array(this.analyser.frequencyBinCount);
//frequencyBinCount通常是可视化数据值的数量,为fftSize的一半
    requestAnimationFrame = window.requestAnimationFrame || webkitRequestAnimationFrame || mozRequestAnimationFrame;
    //window.requestAnimationFrame() 方法告诉浏览器您希望执行动画,并请求浏览器调用指定的函数在下一次重绘之前更新动画。该方法将在重绘之前调用的回调作为参数。
    var self = this;

    function v() {
        self.analyser.getByteFrequencyData(arr);
//getByteFrequmencyData把当前频率数据复制到传入其中的Uint8Array
        self.visualizer(arr);
        requestAnimationFrame(v);
    }
    requestAnimationFrame(v);
};
musicVisualizer.prototype.play = function(url) {
    var self = this;
    this.source && this.stop();
    this.load(url, function(arraybuffer) {
        self.decode(arraybuffer, function(buffer) {
            var bs = musicVisualizer.ac.createBufferSource();
//createBufferSource() 
方法用于创建一个新的AudioBufferSourceNode接口, 该接口可以通过AudioBuffer 对象来播放音频数据. 
AudioBuffer对象可以通过AudioContext.createBuffer 来创建或者通过 AudioContext.decodeAudioData成功解码音轨后获取.


            bs.connect(self.analyser);
            bs.buffer = buffer;
            bs[bs.start ? "start" : "noteOn"](0);
            self.source = bs;
        });
    });
};
  • H5 canvas visualization part. Raw material adhesive

var size = 64;
var box = $("#box")[0];
var height, width;
var canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
box.appendChild(canvas);
var Dots = [];
draw.type = "column";
window.onresize = resize;
var line;


var mv = new musicVisualizer({
    size: size,
    visualizer: draw
});





var clickMusic = (function () {
    var lis = $(".music li");
    lis.click(function() {
        var i = $(this).index();
        lis.css('color', 'white');
        lis.eq(i).css('color', 'grey');
        mv.play('./musics/' + lis.eq(i).html());
    });
})();



function random(m, n) {
    return Math.round(Math.random() * (n - m) + m);
}

function getDots() {
    Dots = [];
    for (var i = 0; i < size; i++) {
        var x = random(0, width);
        var y = random(0, height);
        var color = "rgba(" + random(0, 255) + "," + random(0, 255) + "," + random(0, 255) + ",0)";
        Dots.push({
            x: x,
            y: y,
            color: color,
            cap: 0,
            dx: random(1, 4)
        });
    };
}


var resize = (function () {
    height = box.clientHeight;
    width = box.clientWidth;
    canvas.height = height;
    canvas.width = width;
    line = ctx.createLinearGradient(0, 0, 0, height);
    line.addColorStop(0, "pink");
    line.addColorStop(0.5, "grey");
    line.addColorStop(1, "lightblue");
      getDots();
})();

function draw(arr) {
    ctx.clearRect(0, 0, width, height);
    var w = width / size;
    var cw = w * 0.6;
    var ch = cw;
    ctx.fillStyle = line;
    for (var i = 0; i < size; i++) {
        var o = Dots[i];
        if (draw.type == "column") {
            var h = arr[i] / 256 * height;
            ctx.fillRect(w * i, height - h, cw, h);
            ctx.fillRect(w * i, height - (o.cap + ch), cw, ch);
            o.cap--;
            if (o.cap < 0) {
                o.cap = 0;
            }
            if (h > 0 && o.cap < h + 30) {
                o.cap = h + 30 > height - ch ? height - ch : h + 30;
            }
        } else if (draw.type == "dot") {
            ctx.beginPath();
            var r = 10 + arr[i] / 256 * (height > width ? width : height) / 10;
            ctx.arc(o.x, o.y, r, 0, Math.PI * 2, true);
            var circle = ctx.createRadialGradient(o.x, o.y, 0, o.x, o.y, r);
            circle.addColorStop(0, "white");
            circle.addColorStop(1, o.color);
            ctx.fillStyle = circle;
            ctx.fill();
            o.x += o.dx;
            o.x = o.x > width ? 0 : o.x;
        }
    }
}


var changeStyle = (function () {
    var spans = $(".musicList span");
    spans.click(function() {
        var i = $(this).index();
        spans.removeClass(&#39;selected&#39;)
            .eq(i).addClass(&#39;selected&#39;);
        draw.type = spans.eq(i).attr(&#39;type&#39;);
    });
})();

The above is the detailed content of Detailed explanation of HTML5 music visualization code. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn