Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create JavaScript Waveform Visualization With Howler.js

I am trying to produce a wave form (https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Visualizations_with_Web_Audio_API) with howler.js . I see the dataArray looping through the draw function. However it only draws a straight line because the v variable always returns 1. I based the code off a pretty common MDN example, this leads me to believe maybe the way I am getting the howler data is incorrect.

HTML

<div id="play">play</div>
<canvas id="canvas"></canvas>

JS

let playing = false
    const playBtn = document.getElementById('play')
    const canvas = document.getElementById('canvas')
    const canvasCtx = canvas.getContext('2d')
    const WIDTH = canvas.width
    const HEIGHT = canvas.height
    let drawVisual = null

    /*
        files
        https://s3-us-west-2.amazonaws.com/s.cdpn.io/481938/Find_My_Way_Home.mp3
    */

    /*
    streams
        'http://rfcmedia.streamguys1.com/MusicPulse.mp3'
    */

    let analyser = null
    let bufferLength = null
    let dataArray = null

    const howler = new Howl({
        html5: true,
        format: ['mp3', 'aac'],
        src:
            'https://s3-us-west-2.amazonaws.com/s.cdpn.io/481938/Find_My_Way_Home.mp3',
        onplay: () => {
            analyser = Howler.ctx.createAnalyser()
            Howler.masterGain.connect(analyser)
            analyser.connect(Howler.ctx.destination)
            analyser.fftSize = 2048
            analyser.minDecibels = -90
            analyser.maxDecibels = -10
            analyser.smoothingTimeConstant = 0.85
            bufferLength = analyser.frequencyBinCount
            dataArray = new Uint8Array(bufferLength)
            canvasCtx.clearRect(0, 0, WIDTH, HEIGHT)

            const draw = () => {
                drawVisual = requestAnimationFrame(draw)
                analyser.getByteTimeDomainData(dataArray)
                canvasCtx.fillStyle = '#000'
                canvasCtx.fillRect(0, 0, WIDTH, HEIGHT)
                canvasCtx.lineWidth = 2
                canvasCtx.strokeStyle = 'limegreen'
                canvasCtx.beginPath()

                let sliceWidth = (WIDTH * 1.0) / bufferLength
                let x = 0

                for (let i = 0; i < bufferLength; i++) {
                    let v = dataArray[i] / 128.0
                    let 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()
        }
    })

    playBtn.addEventListener('click', () => {
        if (!playing) {
            howler.play()
            playing = true
        }
    })
like image 707
NicholasByDesign Avatar asked Dec 20 '19 21:12

NicholasByDesign


Video Answer


1 Answers

To get it working:

  1. Remove html5: true
  2. There is a CORS setup isssue with your audio source. What are your bucket CORS settings? Access to XMLHttpRequest at 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/481938/Find_My_Way_Home.mp3' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

The CORS issue leads to your dataArray being full of 128 basically meaning no sound even though the music is playing.

With that I got your visualizer to work. (You can bypass CORS on chrome "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security)

like image 63
Christian Kovanen Avatar answered Oct 12 '22 23:10

Christian Kovanen