Допустим есть некий sampe.mp3. Я хочу с помощью javascript извлечь сырые данные и нарисовать график этого звука. Как это сделать?
<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>
На этом сайте график почему-то не рисуется, только кастомный прогресс воспроизведения, но код рабочий. Поэтому прикрепляю картинку, как должен выглядеть график:
Ещё одна реализация рисования осциллограммы, и на этот раз без canvas, а путём программного создания графического рисунка стандартного формата прямо в оперативной памяти, (на примере формата BMP) и передачи его в элемент img в качестве src:
<html>
<head>
<meta charset="utf-8">
<title>Визуализатор</title>
</head>
<body bgcolor=#444>
<img id=oscillogram width=512 height=256><br><br>
<script>
var osc = document.getElementById("oscillogram");
var w = osc.width,h = osc.height;
var w3 = w * 3, w3h = w3 * h;
var RGB = [[114, 196, 243],[243, 114, 196]]; // цвета для осциллограмы
var view = new DataView(new ArrayBuffer(54 + w3h));
view.setUint8(0, 66, true);
view.setUint8(1, 77, true);
view.setUint32(2, w3h + 54, true);
view.setUint32(6, 0, true);
view.setUint32(10, 54, true);
view.setUint32(14, 40, true);
view.setUint32(18, w, true);
view.setUint32(22, h, true);
view.setUint16(26, 1, true);
view.setUint16(28, 24, true);
view.setUint32(30, 0, true);
view.setUint32(34, w3h, true);
for(i = 38; i < 54; i += 4)view.setUint32(i, 0, true);
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var source = audioCtx.createBufferSource();
var request = new XMLHttpRequest();
request.open('GET', "sound.mp3", true); // тут путь к подключаемому аудиофайлу
request.responseType = 'arraybuffer';
request.onload = function(){
audioCtx.decodeAudioData(request.response, function(buffer){
source.buffer = buffer;
for(c = 0; c < 2; c++){
var data = buffer.getChannelData(c);
for(i = 0; i < data.length; i += Math.floor(data.length/10000)){
var lp = data[i] * h / 4;
for(j = 0; j < Math.abs(lp); j++){
for(t = 0; t < 3; t++)view.setUint8(54 + Math.floor(h * (0.75 - c / 2) + (lp >= 0 ? j : -j)) * w3 + Math.floor(i / data.length * w) * 3 + t,RGB[c][2 - t], true);
}
}
}
osc.src = URL.createObjectURL(new Blob([view], {type: "image/bmp"}));
},
function(e){console.log("Ошибка чтения аудиоданных " + e.err)});
}
request.send();
</script>
</body>
</html>
Есть нюансы - для правильного отображения должна быть задана ширина img id=oscillogram, кратная четырём, код работает пока только со стерео-аудиофайлами. Быстро декодируются аудиоданные только маленьких аудиофайлов, одна песня требует около минуты ожидания.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Возможно ли выполнить запрос который обновит не только данные в записи таблицы, но и uid(primary key) записи на новый(последний) без риска получить...
используется joomla сайт мультиязычный, есть самописные модули, при поиске по модулю выходила ошибка