Воспроизведение движущейся формы волны для аудиофайла wav в html

Как создать движущуюся волну для аудиофайла/тега в HTML? При нажатии кнопки воспроизведения звуковой элемент HTML должен воспроизводиться, и соответствующая движущаяся волновая форма для него должна быть сгенерирована.... как реализовать это?

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
        <title id='title'>HTML Page setup Tutorial</title> 
        <script src='riffwave.js'></script>

        <script type="text/javascript">

    function myFunction()
    {
    var data = []; // just an array
for (var i=0; i<10000; i++) data[i] = /*Math.round(255 * Math.random())*/i; // fill data with random samples
var wave = new RIFFWAVE(data); // create the wave file
var audio = new Audio(wave.dataURI); // create the HTML5 audio element
audio.play();


    }
    </script>
    </head>
<body>

<button type="button" onclick="myFunction()">Click Me!</button>
</body>
</html>

Я хочу создать такую ​​форму сигнала ввести описание изображения здесь

Ответ 1

То же, что и ниже, но затем с canvasjs:

Демо: http://seapip.com/canvas/visualizer4/

/*
Speed has to be bigger then refresh!!!
*/

//Speed to move from right to left, also the visible amount of time on the x axis (in milliseconds)
var speed = 10000;

//Time in milliseconds to redraw chart
var refresh = 30;

//Without var to make it a global variable accessable by the html onclick attribute 
audioElement = document.getElementById('audioElement');
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var audioSrc = audioCtx.createMediaElementSource(audioElement);
var analyser = audioCtx.createAnalyser();

// Bind our analyser to the media element source.
audioSrc.connect(analyser);
audioSrc.connect(audioCtx.destination);

//Get frequency data
var frequencyData = new Uint8Array(analyser.frequencyBinCount);

//The animation reference
var animation;

//Create chart
var dps = []; // dataPoints
var chart = new CanvasJS.Chart("chart", {
    interactivityEnabled: false,
    width: 500,
    height: 200,
    axisX: {
        title: "Time",
        valueFormatString: "mm:ss"
    },
    axisY: {
        title: "dB"
    },
    data: [{
        type: "line",
        dataPoints: dps
    }]
});
chart.render();

//On play
audioElement.onplay = function() {
    //Start drawing
    animation = setInterval(function() {
        drawWave();
    }, refresh);
};

//On pause
audioElement.onpause = function() {
    //Stop drawing
    clearInterval(animation);
};

//On ended
audioElement.onended = function() {
    //Stop drawing
    clearInterval(animation);

    //Reset time
    time = 0;

    //Reset dataPoints
    dps = [];

    //Prevent audio from looping (you can remove this if you want it to loop)
    audioElement.pause();
};

//Max dB
var max = analyser.maxDecibels;

//Min dB
var min = analyser.minDecibels;

//Time
var time = 0;

//Our drawing method
function drawWave() {

    // Copy frequency data to frequencyData array.
    analyser.getByteFrequencyData(frequencyData);

    //Total loudness of all frequencies in frequencyData
    var totalLoudness = 0;
    for(var i = 0; i < frequencyData.length; i++) {
        totalLoudness += frequencyData[i];
    }

    //Average loudness of all frequencies in frequencyData on scale from 0 to 255
    var averageLoudness = totalLoudness / frequencyData.length / 255;

    //Decibels
    var decibels = min + averageLoudness * Math.abs(min - max);

    //Increase time
    time += refresh;

    //Add to chart
    dps.push({
        x: new Date(time),
        y: decibels
    });

    //Maximum x values to draw based on speed ad refresh
    if(dps.length > speed / refresh) {
        dps.shift();
    }

    //Draw new chart
    chart.render(); 
}


<audio id="audioElement" src="audio/Odesza - Above The Middle.mp3"></audio>
<div id="chart"></div>
<div>
  <button onclick="audioElement.play()">Play the Audio</button>
  <button onclick="audioElement.pause()">Pause the Audio</button>
  <button onclick="audioElement.volume+=0.1">Increase Volume</button>
  <button onclick="audioElement.volume-=0.1">Decrease Volume</button>
</div>

Имейте в виду, что #chart - это div вместо элемента canvas, мне потребовалось несколько минут, чтобы узнать, почему диаграмма сначала не показывалась: P




То же, что и ниже, но с графикой справа налево. Переменная stepSize задает как скорость анимации, так и размер шагов, если вы хотите, чтобы были сделаны более крупные шаги, тогда она должна двигаться быстрее, и если вы хотите, чтобы были сделаны меньшие шаги, она должна двигаться медленнее.

Демо: http://seapip.com/canvas/visualizer3

//Step size (pixels per 20ms)
var stepSize = 0.5;

//Without var to make it a global variable accessable by the html onclick attribute 
audioElement = document.getElementById('audioElement');
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var audioSrc = audioCtx.createMediaElementSource(audioElement);
var analyser = audioCtx.createAnalyser();

// Bind our analyser to the media element source.
audioSrc.connect(analyser);
audioSrc.connect(audioCtx.destination);

//Get frequency data (800 = max frequency)
var frequencyData = new Uint8Array(400);
//Use below to show all frequencies
//var frequencyData = new Uint8Array(analyser.frequencyBinCount);

//Create canvas
var canvas = document.getElementById("wave");
canvas.style.width = "500px";
canvas.style.height = "100px";

//High dpi stuff
canvas.width = parseInt(canvas.style.width) * 2;
canvas.height = parseInt(canvas.style.height) * 2;

//Get canvas context
var ctx = canvas.getContext("2d");

//Stroke color
ctx.strokeStyle = "#ffff00";

//Draw thicker lines due to high dpi scaling
ctx.lineWidth = 2;

//Store y values
var drawY = [canvas.height];

//The animation reference
var animation;

//On play
audioElement.onplay = function() {
    //Start drawing
    animation = setInterval(function() {
        drawWave();
    }, 20);
};

//On pause
audioElement.onpause = function() {
    //Stop drawing
    clearInterval(animation);
};

//On ended
audioElement.onended = function() {
    //Stop drawing
    clearInterval(animation);

    //Clear previous y values
    drawY = [canvas.height];

    //Prevent audio from looping (you can remove this if you want it to loop)
    audioElement.pause();
};

//Our drawing method
function drawWave() {

    // Copy frequency data to frequencyData array.
    analyser.getByteFrequencyData(frequencyData);

    //Total loudness of all frequencies in frequencyData
    var totalLoudness = 0;
    for(var i = 0; i < frequencyData.length; i++) {
        totalLoudness += frequencyData[i];
    }

    //Average loudness of all frequencies in frequencyData
    var averageLoudness = totalLoudness / frequencyData.length;

    //Scale of average loudness from (0 to 1), frequency loudness scale is (0 to 255)
    var y = averageLoudness / 255;
    //Multiply with canvas height to get scale from (0 to canvas height)
    y *= canvas.height;
    //Since a canvas y axis is inverted from a normal y axis we have to flip it to get a normal y axis value
    y = canvas.height - y;

    //Store new y value
    drawY.push(y);

    //Clear previous drawing
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    //Draw line
    for(var i = drawY.length; i > 0; i--) {

        //calculate x values
        var x1 = canvas.width - (drawY.length - i - 1) * stepSize;
        var x2 = canvas.width - (drawY.length - i) * stepSize;

        //Stop drawing y values if the x value is outside the canvas
        if(!x2) {
            break;
        }
        ctx.beginPath();
        ctx.moveTo(x1, drawY[i - 1]);
        ctx.lineTo(x2, drawY[i]);
        ctx.stroke();
    }
}


<audio id="audioElement" src="audio/Odesza - Above The Middle.mp3"></audio>
<canvas id="wave"></canvas>
<div>
  <button onclick="audioElement.play()">Play the Audio</button>
  <button onclick="audioElement.pause()">Pause the Audio</button>
  <button onclick="audioElement.volume+=0.1">Increase Volume</button>
  <button onclick="audioElement.volume-=0.1">Decrease Volume</button>
</div>




Вот то, что я думаю, вы, вероятно, хотели, ось x - это время, а ось y - средняя громкость всех частот. Имейте в виду, что браузеры, такие как хром, не правильно рисуют график на вкладке фона, поскольку ограничивают интервал обновления и вывод аудиоанализатора.

Демо: http://seapip.com/canvas/visualizer2

//Without var to make it a global variable accessable by the html onclick attribute 
audioElement = document.getElementById('audioElement');
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var audioSrc = audioCtx.createMediaElementSource(audioElement);
var analyser = audioCtx.createAnalyser();

// Bind our analyser to the media element source.
audioSrc.connect(analyser);
audioSrc.connect(audioCtx.destination);

//Get frequency data (800 = max frequency)
var frequencyData = new Uint8Array(400);
//Use below to show all frequencies
//var frequencyData = new Uint8Array(analyser.frequencyBinCount);

//Create canvas
var canvas = document.getElementById("wave");
canvas.style.width = "1000px";
canvas.style.height = "100px";

//High dpi stuff
canvas.width = parseInt(canvas.style.width) * 2;
canvas.height = parseInt(canvas.style.height) * 2;

//Get canvas context
var ctx = canvas.getContext("2d");

//Set stroke color to yellow
ctx.strokeStyle = "#ffff00";

//Draw twice as thick lines due to high dpi scaling
ctx.lineWidth = 2;

//Save x and y from the previous drawing
var drawX = 0;
var drawY = 0;

//Total duration (Seconds)
var duration;

//The animation reference
var animation;

//Audio is loaded
audioElement.oncanplaythrough = function() {

    //Get duration
    duration = audioElement.duration;

    //On play
    audioElement.onplay = function() {
        //Start drawing
        drawWave();
    };

    //On pause
    audioElement.onpause = function() {
        //Stop drawing
        cancelAnimationFrame(animation);
    };

    //On ended
    audioElement.onended = function() {
        //Stop drawing
        cancelAnimationFrame(animation);

        //Clear previous drawing
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        //Clear previous x and y values
        drawX = 0;
        drawY = 0;

        //Prevent audio from looping (you can remove this if you want it to loop)
        audioElement.pause();
    };
};

//Our drawing method
function drawWave() {

    //Current time (seconds)
    var currentTime = audioElement.currentTime;

    // Copy frequency data to frequencyData array.
    analyser.getByteFrequencyData(frequencyData);

    //Total loudness of all frequencies in frequencyData
    var totalLoudness = 0;
    for(var i = 0; i < frequencyData.length; i++) {
        totalLoudness += frequencyData[i];
    }

    //Average loudness of all frequencies in frequencyData
    var averageLoudness = totalLoudness / frequencyData.length;

    //Get the previous x axis value
    var previousDrawX = drawX;

    //Scale of progress in song (from 0 to 1)
    drawX =  currentTime / duration;
    //Multiply with canvas width to get x axis value
    drawX *= canvas.width;

    //Get the previous y axis value
    var previousDrawY = drawY;

    //Scale of average loudness from (0 to 1), frequency loudness scale is (0 to 255)
    drawY = averageLoudness / 255;
    //Multiply with canvas height to get scale from (0 to canvas height)
    drawY *= canvas.height;
    //Since a canvas y axis is inverted from a normal y axis we have to flip it to get a normal y axis value
    drawY = canvas.height - drawY;

    //Draw line
    ctx.beginPath();
    ctx.moveTo(previousDrawX, previousDrawY);
    ctx.lineTo(drawX, drawY);
    ctx.stroke();

    //Animate
    animation = requestAnimationFrame(drawWave);
}


<audio id="audioElement" src="audio/Odesza - Above The Middle.mp3"></audio>
<canvas id="wave"></canvas>
<div>
  <button onclick="audioElement.play()">Play the Audio</button>
  <button onclick="audioElement.pause()">Pause the Audio</button>
  <button onclick="audioElement.volume+=0.1">Increase Volume</button>
  <button onclick="audioElement.volume-=0.1">Decrease Volume</button>
</div>




Пример визуализации холста

Демо: http://seapip.com/canvas/visualizer/

//Without var to make it a global variable accessable by the html onclick attribute 
audioElement = document.getElementById('audioElement');
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var audioSrc = audioCtx.createMediaElementSource(audioElement);
var analyser = audioCtx.createAnalyser();

// Bind our analyser to the media element source.
audioSrc.connect(analyser);
audioSrc.connect(audioCtx.destination);

//Get frequency data (400 = max frequency)
var frequencyData = new Uint8Array(400);
//Use below to show all frequencies
//var frequencyData = new Uint8Array(analyser.frequencyBinCount);

//Create canvas
var canvas = document.getElementById("wave");
canvas.style.width = "500px";
canvas.style.height = "100px";

//High dpi stuff
canvas.width = parseInt(canvas.style.width) * 2;
canvas.height = parseInt(canvas.style.height) * 2;

//Get canvas context
var ctx = canvas.getContext("2d");

//Set stroke color
ctx.strokeStyle = "#ffff00"

//Draw twice as thick lines due to high dpi scaling
ctx.lineWidth = 2;

//Animation reference
var animation;

//On play
audioElement.onplay = funtion() {
    drawWave();
};

//On pause
audioElement.onpause = funtion() {
    cancelAnimationFrame(animation);
};

//On ended
audioElement.onended = funtion() {
    cancelAnimationFrame(animation);
};

//Our drawing method
function drawWave() {
    // Copy frequency data to frequencyData array.
    analyser.getByteFrequencyData(frequencyData);

    //Draw the wave
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    for(var i = 1; i < frequencyData.length; i++) {
        var x1 = canvas.width / (frequencyData.length - 1) * (i - 1);
        var x2 = canvas.width / (frequencyData.length - 1) * i;
        var y1 = canvas.height - frequencyData[i - 1] / 255 * canvas.height;
        var y2 = canvas.height - frequencyData[i] / 255 * canvas.height;
        if(x1 && y1 && x2 && y2) {
            ctx.beginPath();
            ctx.moveTo(x1, y1);
            ctx.lineTo(x2, y2);
            ctx.stroke();
        }
    }

    //Animate
    animation = requestAnimationFrame(drawWave);
}


<audio id="audioElement" src="audio/Odesza - Above The Middle.mp3"></audio>
<canvas id="wave"></canvas>
<div>
  <button onclick="document.getElementById('audioElement').play()">Play the Audio</button>
  <button onclick="document.getElementById('audioElement').pause()">Pause the Audio</button>
  <button onclick="document.getElementById('audioElement').volume+=0.1">Increase Volume</button>
  <button onclick="document.getElementById('audioElement').volume-=0.1">Decrease Volume</button>
</div>




Плагины и руководства по визуализации аудио:

https://wavesurfer-js.org/

http://waveformjs.org/#weird

https://www.bignerdranch.com/blog/music-visualization-with-d3-js/

https://github.com/wayou/HTML5_Audio_Visualizer

https://www.patrick-wied.at/blog/how-to-create-audio-visualizations-with-javascript-html

https://p5js.org/examples/examples/Sound_Frequency_Spectrum.php