javascript

时间:2018-08-15 12:35:55

标签: javascript audio audiocontext

我一直在尝试AudioContext api,试图进行一些基本的可视化。就像其中一个五颜六色的条形上升和下降。

我用来自mdn的音频文章介绍了可视化效果,我还查看了一些chrome插件和codepens。而且我自己也做了一些实现。 而且不管我做什么,我不禁会注意到,由于frequencyData,我所有的竖线都倾向于从左向右倾斜。

我有点不明白为什么数据数组开头的值总是接近最大值(255)。我需要一些帮助来解决这个问题。 下面是我的一些代码:

function frequencyToIndex(freq, fftSize, sampleRate = 44100) {
  let nyquist = sampleRate / 2;
  let fftBin = fftSize /2;

  let index = Math.round(freq / nyquist * fftSize)

  if(index <= 0) return 0
  if(index > fftBin) return fftBin
  return index
}

function byteFrequencyAverage(analyser, frequencies, minHz, maxHz, norm = 255) {
  let sampleRate = analyser.context.sampleRate
  let fftSize = analyser.fftSize

  let start = frequencyToIndex(minHz, fftSize, sampleRate)
  let end = frequencyToIndex(maxHz, fftSize, sampleRate)

  let count = end - start
  let sum = 0

  while(start < end) {
    sum += frequencies[start]
    start +=1
  }

  return count ? sum/count : 0
}

// https://www.teachmeaudio.com/mixing/techniques/audio-spectrum/
let bands = {
  subbas:{
    from: 20,
    to: 60
  },
  bass: {
    from: 61,
    to: 250
  },
  lowmid: {
    from: 251,
    to: 500
  },
  mid: {
    from: 501,
    to: 2000
  },
  uppermid: {
    from: 2001,
    to: 4000
  },
  presence: {
    from: 40001,
    to: 6000
  },
  akward: {
    from: 6001,
    to: 8000
  }
}

var Bars = (function(canvas) {
  const WIDTH =canvas.width;
  const HEIGHT =canvas.height;

  let context = canvas.getContext('2d')
  let audioCtx = new (window.AudioContext || window.webkitAudioContext)();
  let analyser = audioCtx.createAnalyser();

  let audio = document.querySelector("#soundcloud");

  function initSource() {
    let dataArray  = new Uint8Array();
    let bufferLength = 0;

    let source = audioCtx.createMediaElementSource(audio);

    source.connect(analyser);
    analyser.connect(audioCtx.destination);

    analyser.fftSize = 1024;
    bufferLength = analyser.frequencyBinCount;

    dataArray = new Uint8Array(bufferLength);

    context.clearRect(0, 0, WIDTH, HEIGHT);
    return { dataArray: dataArray, bufferLength: bufferLength }
  }

  function withAudioDetails(dataArray, bufferLength) {
    return function draw() {
      requestAnimationFrame(draw);
      analyser.getByteFrequencyData(dataArray);

      context.fillStyle = 'rgb(0, 0, 0)';
      context.clearRect(0, 0, WIDTH, HEIGHT);

      let freqs = Object.keys(bands)
        .map(k => byteFrequencyAverage(analyser, dataArray, bands[k].from, bands[k].to))
        .map(Math.floor)

      let barWidth = 20;
      let x = 0;

      for(let i = 0; i < freqs.length; i++) {
        context.fillStyle = `rgb(${freqs[i] + 100}, 50, 50)`
        context.fillRect(x, HEIGHT - freqs[i], barWidth, freqs[i])

        x += barWidth + 1;
      }

      // mdn example
      // let barWidth = (WIDTH / bufferLength) * 2.5;
      // let barHeight;
      // let x = 0;

      // for(let i = 0; i < bufferLength; i++) {
      //   barHeight = dataArray[i]/2;
      //   console.log(dataArray[i], i)

      //   context.fillStyle = 'rgb(' + (barHeight+100) + ',50,50)';
      //   context.fillRect(x,HEIGHT-barHeight/2,barWidth,barHeight);

      //   x += barWidth + 1;
      // }
    }
  }

  return {
    initSource: initSource,
    withAudioDetails: withAudioDetails
  }
})

因此,当我运行此命令时,我只会得到4-5小节。和左边的火箭,右边的高度总是很低。这与我在手机上使用某些媒体播放器或说Linux上使用cava时所看到的完全不同。 我已附上图片Image from cavaImage from webpage进行比较。

我可以做的一件事是缩小高值并缩小低值。但是我不确定那是个好主意。

谢谢。

0 个答案:

没有答案