• HTML5 WebAudioAPI(三)--绘制频谱图


    HTML

    <style>
        #canvas {
            background: black;
        }
    </style>
    <div class="container">
        <button class="btn btn-primary" id="playBtn">
            <i class="glyphicon glyphicon-pause"></i>
        </button>
    </div>
    <canvas id="canvas" width="800" height="300"></canvas>

    实例1,绘制频谱图:

    var url='../content/audio/海阔天空.mp3';
    if (!window.AudioContext) {
        alert('您的浏览器不支持AudioContext');
    } else {
        //创建上下文
        var ctx = new AudioContext();
        var source = null;
        //使用Ajax获取音频文件
    
        var request = new XMLHttpRequest();
        request.open('GET', url, true);
        request.responseType = 'arraybuffer';//配置数据的返回类型
        //加载完成
        request.onload = function () {
            var arraybuffer = request.response;
            ctx.decodeAudioData(arraybuffer, function (buffer) {
                //创建分析器
                var analyser = ctx.createAnalyser();
                source = ctx.createBufferSource();
                //将source与分析器链接
                source.connect(analyser);
                //将分析器与destination链接,这样才能形成到达扬声器的通路
                analyser.connect(ctx.destination);
                //将解码后的buffer数据复制给source
                source.buffer = buffer;
                //播放
                source.start(0);
    
                //开始绘制频谱图
                function drawSpectrum() {
                    var canvas = document.getElementById('canvas'),
                        cwidth = canvas.width,
                        cheight = canvas.height - 2,
                        meterWidth = 10,//能量条的宽度
                        gap = 2,//能量条的间距
                        meterNum = 800 / (10 + 2),//计算当前画布上能画多少条
                        ctx = canvas.getContext('2d');
                    var capHeight = 2;//
                    var array = new Uint8Array(analyser.frequencyBinCount);
                    analyser.getByteFrequencyData(array);
                    console.info(array.length);
                    var step = Math.round(array.length / meterNum);//计算从analyser中的采样步长
    
                    //清理画布
                    ctx.clearRect(0, 0, cwidth, cheight);
                    //定义一个渐变样式用于画图
                    var gradient = ctx.createLinearGradient(0, 0, 0, 300);
                    gradient.addColorStop(1, '#0f0');
                    gradient.addColorStop(0.5, '#ff0');
                    gradient.addColorStop(0, '#f00');
                    ctx.fillStyle = gradient;
                    //对信源数组进行抽样遍历,画出每个频谱条
                    for (var i = 0; i < meterNum; i++) {
                        var value = array[i * step];
                        ctx.fillRect(i * 12/*频谱条的宽度+条间距*/, cheight - value + capHeight,
                            meterWidth, cheight);
                    }
                    requestAnimationFrame(drawSpectrum)
                }
                requestAnimationFrame(drawSpectrum)
            }, function (e) {
                console.info('处理出错');
            });
        }
        request.send();
    
    
    
    
        //绑定播放按钮
        $('#playBtn').click(function () {
            var icon = $(this).find('i');;
            icon.toggleClass('glyphicon-play').toggleClass('glyphicon-pause');
            //停止播放
            source.stop();
        });
    }

    实例2,绘制缓慢下落的帽头

    var url='../content/audio/海阔天空.mp3';
    if (!window.AudioContext) {
        alert('您的浏览器不支持AudioContext');
    } else {
        //创建上下文
        var atx = new AudioContext();
        var source = null;
        //使用Ajax获取音频文件
        var request = new XMLHttpRequest();
        request.open('GET', url, true);
        request.responseType = 'arraybuffer';//配置数据的返回类型
        //加载完成
        request.onload = function () {
            var arraybuffer = request.response;
            atx.decodeAudioData(arraybuffer, function (buffer) {
                //创建分析器
                var analyser = atx.createAnalyser();
                source = atx.createBufferSource();
                //将source与分析器链接
                source.connect(analyser);
                //将分析器与destination链接,这样才能形成到达扬声器的通路
                analyser.connect(atx.destination);
                //将解码后的buffer数据复制给source
                source.buffer = buffer;
                //播放
                source.start(0);
    
    
                //开始绘制频谱图
                var canvas = document.getElementById('canvas'),
                    cwidth = canvas.width,
                    cheight = canvas.height - 2,
                    meterWidth = 10,//能量条的宽度
                    gap = 2,//能量条的间距
                    meterNum = 800 / (10 + 2);//计算当前画布上能画多少条
                var ctx = canvas.getContext('2d');
                var capHeight = 2,//冒头的高度
                    capStyle = '#fff',//冒头的颜色
                    capYPositionArray = [];//将上一面各个冒头的位置保存到这个数组
                //定义一个渐变样式用于画图
                var gradient = ctx.createLinearGradient(0, 0, 0, 300);
                gradient.addColorStop(1, '#0f0');
                gradient.addColorStop(0.5, '#ff0');
                gradient.addColorStop(0, '#f00');
                //绘制频谱图
                function drawSpectrum() {
                    var array = new Uint8Array(analyser.frequencyBinCount);
                    analyser.getByteFrequencyData(array);
                    var step = Math.round(array.length / meterNum);//计算从analyser中的采样步长
                    //清理画布
                    ctx.clearRect(0, 0, cwidth, cheight);
                    //对信源数组进行抽样遍历,画出每个频谱条
                    for (var i = 0; i < meterNum; i++) {
                        var value = array[i * step]; //取样作为y轴的值
                        //绘制缓慢降落的冒头
                        if (capYPositionArray.length < Math.round(meterNum)) {
                            capYPositionArray.push(value);//初始化保存冒头位置的数组,将第一个画面位置保存
                        }
                        ctx.fillStyle = capStyle;
                        //1.开始绘制冒头
                        if (value < capYPositionArray[i]) {
                            //使用前一次数据
                            ctx.fillRect(i * 12, cheight - (--capYPositionArray[i]), meterWidth, capHeight);
                        } else {
                            //否则,直接使用当前数据并记录
                            ctx.fillRect(i * 12, cheight - value, meterWidth, capHeight);
                            capYPositionArray[i] = value;
                        }
                        //2.开始绘制频谱条
                        ctx.fillStyle = gradient;
                        ctx.fillRect(i * 12/*频谱条的宽度+条间距*/, cheight - value + capHeight,
                            meterWidth, cheight);
                    }
                    requestAnimationFrame(drawSpectrum);
                }
                requestAnimationFrame(drawSpectrum);
            }, function (e) {
                console.info('处理出错');
            });
    
        }
        request.send();
        //绑定播放按钮
        $('#playBtn').click(function () {
            var icon = $(this).find('i');;
            icon.toggleClass('glyphicon-play').toggleClass('glyphicon-pause');
            //停止播放
            source.stop();
        });
    }

    内容来源:http://www.cnblogs.com/Wayou/p/3543577.html

    更多参考:

    HTML5 WebAudioAPI简介(一)

    HTML5 WebAudioAPI-实例(二)

  • 相关阅读:
    coding++:拦截器拦截requestbody数据如何防止流被读取后数据丢失
    好记性-烂笔头:controller-接收参数方式及注意事项
    coding++:MySQL-ERROR:Column 'complaint_settlement_id' in field list is ambiguous
    coding++:SpringBoot 处理前台字符串日期自动转换成后台date类型的三种办法
    coding++:Arrays.asList()
    coding++:thymelef 模板报错 the entity name must immediately follow the '&' in the entity reference
    coding++:kafka问题:zookeeper is not a recognized option zookeeper参数不支持
    coding++:mybatis 嵌套查询子查询column传多个参数描述
    POJ 1816 Trie
    POJ 2945 Trie
  • 原文地址:https://www.cnblogs.com/tianma3798/p/6033643.html
Copyright © 2020-2023  润新知