Анализ аудио через AudioContext и AnalyserNode

Для анализа аудио в браузере используется Web Audio API, основными объектами которого являются AudioContext и AnalyserNode. AudioContext создаёт среду для обработки аудиосигналов и обеспечивает маршрутизацию данных между различными узлами (nodes). Создание нового контекста выглядит так:

const audioCtx = new (window.AudioContext || window.webkitAudioContext)();

Этот объект является точкой входа для всех аудиоопераций. Через него создаются источники звука, фильтры, анализаторы и выходные узлы. Важно помнить, что AudioContext может быть приостановлен браузером до взаимодействия пользователя с документом.

Использование AnalyserNode

AnalyserNode позволяет получить текущие данные аудиосигнала в реальном времени для визуализации или анализа. Создать такой узел можно следующим образом:

const analyser = audioCtx.createAnalyser();

Основные свойства AnalyserNode:

  • fftSize — размер FFT (быстрого преобразования Фурье), определяющий разрешение спектра. Обычно значения кратны степени двойки (например, 256, 512, 1024, 2048). Чем больше fftSize, тем точнее спектр, но выше нагрузка на процессор.
  • minDecibels и maxDecibels — диапазон амплитуд для визуализации.
  • smoothingTimeConstant — коэффициент сглаживания амплитуды, значение от 0 до 1. Позволяет сглаживать колебания между кадрами.

Для получения спектра используется метод getByteFrequencyData():

const dataArray = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(dataArray);

frequencyBinCount всегда равен fftSize / 2, что определяет количество точек спектра.

Подключение источника аудио

Источником может быть как аудиофайл, так и микрофон. Для работы с файлом используется AudioBufferSourceNode:

fetch('audio.mp3')
  .then(response => response.arrayBuffer())
  .then(arrayBuffer => audioCtx.decodeAudioData(arrayBuffer))
  .then(audioBuffer => {
    const source = audioCtx.createBufferSource();
    source.buffer = audioBuffer;
    source.connect(analyser);
    analyser.connect(audioCtx.destination);
    source.start();
  });

Для микрофона применяется MediaStreamAudioSourceNode:

navigator.mediaDevices.getUserMedia({ audio: true })
  .then(stream => {
    const source = audioCtx.createMediaStreamSource(stream);
    source.connect(analyser);
    analyser.connect(audioCtx.destination);
  });

Оба подхода позволяют передавать аудиосигнал в AnalyserNode для анализа.

Визуализация спектра

Спектр можно визуализировать с помощью <canvas> и методов requestAnimationFrame для анимации. Пример:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

function draw() {
  requestAnimationFrame(draw);
  
  analyser.getByteFrequencyData(dataArray);

  ctx.fillStyle = 'black';
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  const barWidth = canvas.width / dataArray.length;
  dataArray.forEach((value, i) => {
    const barHeight = value;
    ctx.fillStyle = `rgb(${barHeight + 100},50,50)`;
    ctx.fillRect(i * barWidth, canvas.height - barHeight, barWidth, barHeight);
  });
}

draw();

Такой подход позволяет получить реалистичную визуализацию амплитуд различных частот в реальном времени.

Связь с Babylon.js

В Babylon.js аудиоанализ часто используется для создания визуальных эффектов, синхронизированных с музыкой. Для интеграции:

  1. Создаётся AudioContext и AnalyserNode.
  2. Полученные спектральные данные преобразуются в массив чисел.
  3. Значения амплитуды применяются к свойствам объектов сцены, например, к масштабированию, цвету или положению.

Пример модификации масштаба объекта по амплитуде низких частот:

const sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter: 2}, scene);

function update() {
  requestAnimationFrame(update);
  analyser.getByteFrequencyData(dataArray);
  
  const lowFreq = dataArray.slice(0, 10).reduce((a, b) => a + b, 0) / 10;
  sphere.scaling.y = 1 + lowFreq / 255;
}

update();

Преобразование данных для 3D-визуализации

  • getByteFrequencyData возвращает массив значений от 0 до 255. Для корректного отображения в сцене Babylon.js их часто нормализуют до диапазона [0, 1].
  • Можно использовать сглаживание нескольких кадров, чтобы визуальные эффекты выглядели более плавными.
  • Для создания эффектов частиц или динамических текстур амплитуду определённого диапазона частот можно применять к интенсивности свечения, скорости движения частиц или цветовой гамме.

Оптимизация

  • Установка fftSize слишком высоким увеличивает нагрузку на CPU, особенно при обновлении сцены 60 fps. Часто достаточно значения 512–1024.
  • Использование smoothingTimeConstant позволяет сгладить дергание объектов, уменьшив визуальный шум.
  • Не обязательно подключать AnalyserNode к destination, если звук не нужно воспроизводить. Можно анализировать аудио полностью в фоне:
source.connect(analyser);
// analyser.connect(audioCtx.destination); // опционально

Использование нескольких анализаторов

В сценах с комплексными эффектами можно создать несколько AnalyserNode с разными fftSize или диапазонами частот, чтобы управлять различными аспектами анимации. Например:

  • Один анализатор для низких частот, управляющий масштабом объектов.
  • Другой для высоких частот, управляющий цветами или прозрачностью.

Это позволяет добиться богатой, синхронизированной визуальной реакции сцены на аудиосигнал.


Хотя работа с AudioContext и AnalyserNode требует внимательного управления потоками и нагрузкой на процессор, они дают полный контроль над аудиоанализом и позволяют создавать впечатляющие визуальные эффекты в Babylon.js.