Получение сырых данных Audio в js

260
17 марта 2018, 19:42

Допустим есть некий sampe.mp3. Я хочу с помощью javascript извлечь сырые данные и нарисовать график этого звука. Как это сделать?

Answer 1

<html> 
<head> 
<meta charset="utf-8"> 
<title>Визуализатор</title> 
<style> 
#canvas{ 
    position: absolute; 
    top: 50px; 
    left: 0px; 
    background: #333; 
} 
#progress{ 
    position: absolute; 
    top: 50px; 
    left: 0px; 
    background: rgba(255, 155, 0, 0.5); 
    width: 0px; 
    height: 256px; 
} 
</style> 
</head> 
<body bgcolor=#444> 
<audio id=audio src="http://auto-gurov.vv.si/1/sound.mp3" controls></audio> 
<canvas id=canvas width=512 height=256></canvas> 
<div id=progress></div> 
<script> 
var audio = document.getElementById("audio"); 
var ctx = canvas.getContext("2d"); 
var color_L = "#7cf", color_R = "#f7c"; // Цвета осциллограмм левого и правого стереоканалов 
var audioCtx = new (window.AudioContext || window.webkitAudioContext)(); 
audio.onplay = function(){b = setInterval(function(){progress.style.width = Math.floor(audio.currentTime / audio.duration * canvas.width) + "px"}, 100)}; 
audio.onended = function(){  
    this.currentTime = 0; 
    clearInterval(b); 
    progress.style.width = "0px"; 
} 
var source = audioCtx.createBufferSource(); 
var request = new XMLHttpRequest(); 
request.open('GET', audio.src, true); 
request.responseType = 'arraybuffer'; 
request.onload = function(){ 
    var audioData = request.response; 
    audioCtx.decodeAudioData(audioData, function(buffer){ 
        source.buffer = buffer; 
        data_L = buffer.getChannelData(0); 
        data_R = buffer.getChannelData(1); // Если аудиофайл моно - поменяйте в этой сроке единицу на ноль. 
         // При несоответствии количества стереоканалов - ошибка в консоли и код не работает. 
        for(var i = 0; i < data_L.length; i++){ 
            var x = Math.floor(i / data_L.length * canvas.width); 
            var L = data_L[i] * canvas.height / 4; 
            var R = data_R[i] * canvas.height / 4; 
            if(Math.floor(i / 16) == i / 16){ // Число 16 для больших аудиофайлов лучше побольше. Нужно подбирать. 
                ctx.fillStyle = color_L; 
                ctx.fillRect(x, canvas.height * 0.25 + L, 1, -L); 
                ctx.fillStyle = color_R; 
                ctx.fillRect(x, canvas.height * 0.75 + R, 1, -R); 
            } 
        } 
    }, 
    function(e){"Error with decoding audio data" + e.err}); 
} 
request.send(); 
canvas.onmousedown = progress.onmousedown = function(e){ 
    progress.style.width = e.pageX + "px"; 
    audio.currentTime = e.pageX / canvas.width * audio.duration; 
} 
canvas.ondblclick = function(){audio.play()}; 
ctx.fillStyle = color_L; 
ctx.fillRect(0, canvas.height * 0.25, canvas.width, 1); 
ctx.fillStyle = color_R; 
ctx.fillRect(0, canvas.height * 0.75, canvas.width, 1); 
</script> 
</body> 
</html>

На этом сайте график почему-то не рисуется, только кастомный прогресс воспроизведения, но код рабочий. Поэтому прикрепляю картинку, как должен выглядеть график:

READ ALSO
Vuetify отключить анимацию

Vuetify отключить анимацию

Тесты perfomance показывают что анимация переходов и окон, потребление взлетает до небесМожно ли из Vuetify вырезать анимации ? Или переопределить...

264
Как загрузить React компонент динамически?

Как загрузить React компонент динамически?

Помогите разобраться с проблемой, как загрузить React компонент динамическиЯ на ходил статьи по этому поводу, но не могу добиться рабочего...

210
Обращение к имени переменной

Обращение к имени переменной

Добрый деньВопрос: пусть есть let foo = 123; и let bar = 'foo'; Как из bar обратиться к содержимому foo?

240
Нашёл задачку, как решить? [требует правки]

Нашёл задачку, как решить? [требует правки]

Нужно реализовать метод closestElement который принимает два параметра @param arrayToLook {arrayNumber} не пустой массив целых чисел от -10000 до 10000 @param valueToCheck {Number}...

295