• music, let's go


    最近研究个新玩意,叫window.AudioContext;不懂?没关系,我也是才接触,这完全可以说个全新领域,
    这玩意干啥的?顾名思义,媒体上下文,也就是你媒体的数据分析,就是一串数据啊?那有啥用呢?对,单纯的数据毫无意义,但是如果把数据结合canvas,就会产生神奇的效果(比如百度的echart),这里的AudioContext结合canvas就能产生一个音乐可视化的效果,就是那种手机MP3播放器的效果,又叫音乐可视化;
    首先原理:
    前端获取到buffer数据,然后运用解析对象,把数据解析,把解析结果放到数组里面,然后连接,最后用canvas画出来;

    后台代码

    const express = require('express');
    const fs = require('fs');
    const app = express();
    app.get('/app/test', function(req,res) {
      fs.readFile('Maksim-克罗地亚狂想曲.mp3', (err, name) => {
          if (err) return
          res.send(name)
      })
    })

    html部分

    <body>
    <input type="range" id="radio"> //改变音量的
    <canvas id="mycanvas"></canvas>
    </body>

    首先前端发起请求,请求音乐的流

          function getdata () {
              var xhr = new XMLHttpRequest()
              xhr.open('get', '/app/test');
               xhr.responseType = 'arraybuffer';
              xhr.onload = function () {
              // 解析后台传来的数据,然后把数据复制到前端的buffer上;
              第一个链接的必须是分析者,分析者获取原始数据
                  ac.decodeAudioData(xhr.response, function (buffer){
                      var buffesource = ac.createBufferSource();// 创建数据,其中buffersource还有个属性是loop就是音乐是不是循环播放
    
                      buffesource.buffer = buffer
                      buffesource.connect(analyser)
                      buffesource.start(0) //这里star可以三个参数,一次意思是,等待多久播放,从哪里开始播放,播放多久
    
                  }, function (err) {
                      console.log(err)
                  })
              }
              xhr.send()
          }

    然后创建音频控制对象

          var ac = new (window.AudioContext || window.webkitAudioContext)() //这是兼容浏览器的写法
          var gainNode = ac[ac.createGain ? 'createGain' : 'createGainNode']() 这个老式和新式api不同
            var analyser = ac.createAnalyser() //创建分析者
            var size = 128
            analyser.fftSize = size * 2;// 这里获取柱子个数就是ffsize的一半
            analyser.connect(gainNode)
            gainNode.connect(ac.destination)

    初始化canvas

            function caninit () {
                var line = ctx.createLinearGradient(0,0,0,600)
                line.addColorStop(0,'red')
                line.addColorStop(.5, 'yellow')
                line.addColorStop(1, 'green')
                ctx.fillStyle = line
            }
            caninit()

     赋值原始数据到数组

            function asyc () {
                var arr = new Uint8Array(analyser.frequencyBinCount)
                analyser.getByteFrequencyData(arr)
                draw(arr)
                nextFrame(asyc)
            }
    定一个unit8数组,然后把数据赋值进去.注意这里不是不是8位无符号数组,那么analyser.getByteFrequencyData这个方法会报错,说第一个参数必须uint8array

    最后画出效果

            function draw (arr) {
                ctx.clearRect(0, 0, width, height)
                var w = width / size
                for (var i = 0; i < arr.length; i++) {
                  var h = (arr[i] / 512) * height;
                  ctx.fillRect(w * i, height - h, w *.6, h)
                }
            }

    ok可以了,页面效果是这样的

    全部代码正在整理上传,各位有兴趣可以写几个echart的类型表玩玩啊

  • 相关阅读:
    Windows光标形状
    函数对象(仿函数 functor)
    构造函数的初始化列表抛出异常
    <<Windows via C/C++>>学习笔记 —— 线程优先级【转】
    单例模式
    c++中的重载(Overload)、覆盖(重写,Override) 、隐藏与访问权限控制及using声明
    RTTI: dynamic_cast typeid
    抽象类 虚函数 声明与实现
    typedef 函数指针 数组 std::function
    Client Window坐标 RECT相关函数
  • 原文地址:https://www.cnblogs.com/lyz1991/p/5763282.html
Copyright © 2020-2023  润新知