Аудио плеер на JS: визуализация частот Canvas

5 (100%) 10 vote[s]

Если нужно вставить на сайт аудио плеер, обычно используется стандартный способ, типа:

<audio controls>
   <source src="Ссылка" type="audio/mp3" />     
        <a href="Ссылка" type="audio/mp3"></a>
 </audio>

В результате получаем незатейливый аудио плеер:



Queen — These Are The Days Of Our Lives (минус)



Если музыки немного, и есть желание сделать вывод аудио посимпатичнее, можно красиво визуализировать частоты при помощи Canvas.

2D аудио визуализация: частоты

Queen - These Are The Days Of Our Lives (минус)

Описание, как сделать аудио плеер

По сути, мы будем визуализировать анимированную гистограмму. Каждый такт будет соответствовать частотному диапазону и «танцевать» вместе с исполняемой музыкой.

Частотный диапазон зависит от частоты дискретизации сигнала (источника звука) и размера БПФ ( или FFT, это сокращение для быстрого преобразования Фурье, используется для преобразования сигнала из временной области (амплитуда-время) в частотную область (амплитуда-частота) ) . Во время воспроизведения звука значения меняются, и гистограмма анимируется.

Количество баров равно  размеру FFT / 2.   В нашем примере N — й  бар (слева направо) соответствует диапазону частот N * (частота дискретизации/ FFT Size). Если мы имеем частоту дискретизации, равную 44100 Гц и FFT  размер равен 512, то первый столбец представляет частоты от 0 до 44100/512 = 86,12 Гц. и т. д.

Поскольку объем данных, возвращаемых узлом анализатора, составляет половину размера быстрого преобразования Фурье, мы сможем построить диапазон частот только до половины частоты дискретизации. Но этого достаточно, поскольку частоты во второй половине частоты дискретизации не имеют значения.

Высота каждого столбца показывает силу конкретного диапазона частот. Это представление того, какая часть каждой частоты присутствует в сигнале (то есть, насколько частота «громкая»).

HTML:

<html>
  <head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
 <style>
	
#myCanvas {
  animation: color-me-in 5s infinite;
}

@keyframes color-me-in {
  50% {
    background: #64e4ed;
  }
  50% {
    background: #025721;
  }
  50% {
    background: #01232e;
  }
  50% {
    background: #64e4ed;
  }
}

div audio {
  display: block;
  margin-bottom:10px;
  margin-left:10px;
}

#myCanvas {
width: 100%;
height: 25% !important;
  border:1px solid;
  margin-left:auto;
  margin-right:auto;
  
}
.main {
  margin: 30px;
  border:1px solid #014347;
  border-radius:15px;
  background: linear-gradient(to top, #64bee8, #012c40);
  padding:10px;
  width:90%;
  
  box-shadow: 5px 5px 5px grey;
  text-align:center;
  font-family: "Open Sans";
  font-size: 12px;
}

div.controls:hover {
  color:blue;
  font-weight:bold;
}
   
div.controls label {
  display: inline-block;
  text-align: center;
  width: 10%;
}

div.controls label, div.controls input, output {
    vertical-align: middle;
    padding: 0;
    margin: 0;
   font-family: "Open Sans",Verdana,Geneva,sans-serif,sans-serif;
  font-size: 12px;
}
</style>
</head>
<body>
  <h2>2D аудио визуализация: частоты</h2>
   <h3>Queen - These Are The Days Of Our Lives (минус)</h3>

<div class="main">
 <audio src="https://www.babulya.com.ua/wp-content/uploads/2019/06/Queen-These-Are-The-Days-Of-Our-Lives.mp3" id="player" controls loop  crossorigin="anonymous" type="audio/mp3"></audio>
  <canvas id="myCanvas" width=1200 height=250></canvas>
</div>

<script>
//построить эквалайзер с несколькими фильтрами
var audioCtx = window.AudioContext || window.webkitAudioContext;

var canvas;
var audioContext, canvasContext;
var analyser;
var width, height;

var dataArray, bufferLength;

window.onload = function() {
  audioContext= new audioCtx();
  
  canvas = document.querySelector("#myCanvas");
  width = canvas.width;
  height = canvas.height;
  canvasContext = canvas.getContext('2d');
  
  buildAudioGraph();
  
  requestAnimationFrame(visualize);
};

function buildAudioGraph() {
  var mediaElement = document.getElementById('player');
      mediaElement.onplay = (e) => {audioContext.resume();}

  // исправлено для политики автозапуска
  mediaElement.addEventListener('play',() => audioContext.resume());

  var sourceNode =   audioContext.createMediaElementSource(mediaElement);
  
  // Создать узел анализатора
  analyser = audioContext.createAnalyser();
  
  // Попробуйте изменить на более низкие значения: 512, 256, 128, 64 ...
  analyser.fftSize = 512;
  bufferLength = analyser.frequencyBinCount;
  dataArray = new Uint8Array(bufferLength);
  
  sourceNode.connect(analyser);
  analyser.connect(audioContext.destination);
}

function visualize() {
  // очистить canvas
  canvasContext.clearRect(0, 0, width, height);
  
  // Или используйте заливку RGBA, чтобы получить небольшой эффект размытия
  //canvasContext.fillStyle = 'rgba (0, 0, 0, 0.5)';
  //canvasContext.fillRect(0, 0, width, height);
  
  // Получить данные анализатора
  analyser.getByteFrequencyData(dataArray);

   var barWidth = width / bufferLength;
      var barHeight;
      var x = 0;
   
      // значения изменяются от 0 до 256, а высота холста равна 100. Давайте изменим масштаб
      // перед отрисовкой. Это масштабный коэффициент
      heightScale = height/128;
  
      for(var i = 0; i < bufferLength; i++) {
        barHeight = dataArray[i];


        canvasContext.fillStyle = 'rgb(' + (barHeight+0) + ',4,160)';
        barHeight *= heightScale;
        canvasContext.fillRect(x, height-barHeight/2, barWidth, barHeight/2);

        // 2 - количество пикселей между столбцами
        x += barWidth + 2;
      }
  
  // вызовите снова функцию визуализации со скоростью 60 кадров / с
  requestAnimationFrame(visualize);
  
}

</script>
</body>
</html>

Дополнительно на свой вкус можно поменять CSS стили, попробовать воспроизвести несжатый звуковой файл (например, в формате .wav). Файлы .mp3 обрезаются на частоте выше 15000 гц, поскольку для уха они не столь существенны, но объем занимают огромный. Посмотрите, как тогда гистограмма распространится вплоть до правого края.

См. расширенный вариант аудио плеера с эквалайзером и возможностью выбора трека из выпадающего списка.

Читайте больше по теме:

Подписаться
Уведомление о
guest
0 комментариев
Inline Feedbacks
View all comments
Просмотры: 2091

Популярные записи