PitchDetection: определение высоты тона

Библиотека ml5.js предоставляет удобный интерфейс для работы с машинным обучением в браузере на JavaScript. Одной из мощных возможностей является определение высоты звука (Pitch Detection) с использованием моделей, обученных на аудиосигналах. Этот функционал особенно полезен в музыке, интерактивных приложениях и звуковых экспериментах.


Подключение библиотеки и подготовка проекта

Для работы с PitchDetection требуется подключить ml5.js через CDN или локальный пакет. В HTML-документе это выглядит так:

<script src="https://cdnjs.cloudflare.com/ajax/libs/ml5/0.12.2/ml5.min.js"></script>

Также необходимо подготовить аудиоисточник. Чаще всего используется микрофон, подключаемый через p5.js или напрямую через Web Audio API.

let mic;
function setup() {
  mic = new p5.AudioIn();
  mic.start();
}

Важно: разрешение на доступ к микрофону должно быть предоставлено пользователем, иначе PitchDetection работать не будет.


Инициализация PitchDetection

Основной класс для определения высоты звука — ml5.PitchDetection. Он создается с указанием модели, аудиоисточника и опционального обратного вызова при готовности модели.

let pitch;
let model_url = 'https://cdn.jsdelivr.net/gh/ml5js/ml5-data-and-models/models/pitch-detection/crepe/';
pitch = ml5.pitchDetection(model_url, getAudioContext(), mic.stream, modelLoaded);

function modelLoaded() {
  console.log('Модель загружена и готова к использованию');
}

Параметры:

  • model_url — путь к предобученной модели. В ml5.js доступна модель CREPE, точная и быстрая для работы с голосом и музыкальными инструментами.
  • audioContext — контекст аудио Web Audio API.
  • stream — поток с микрофона.
  • callback — функция, вызываемая после загрузки модели.

Определение высоты звука в реальном времени

После загрузки модели можно вызывать метод getPitch для получения текущей высоты звука. Результат — это частота в герцах (Hz).

function getPitchValue() {
  pitch.getPitch(function(err, frequency) {
    if (err) {
      console.error(err);
    } else if (frequency) {
      console.log(`Частота: ${frequency.toFixed(2)} Hz`);
    }
    getPitchValue(); // рекурсивный вызов для непрерывного отслеживания
  });
}

Особенности работы:

  • Метод работает асинхронно и возвращает null, если звук слишком слабый или микрофон тишинит.
  • Для непрерывного отслеживания используется рекурсивный вызов.
  • Частота может быть преобразована в музыкальные ноты, используя формулы стандартного темперированного строя.

Преобразование частоты в ноту

Чтобы сопоставить частоту с музыкальной нотой, применяют стандартную формулу:

function frequencyToNote(frequency) {
  const noteNames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'];
  let midi = 69 + 12 * Math.log2(frequency / 440); // 440 Hz = A4
  let noteIndex = Math.round(midi) % 12;
  let octave = Math.floor(Math.round(midi) / 12) - 1;
  return noteNames[noteIndex] + octave;
}

Пример использования:

pitch.getPitch((err, frequency) => {
  if (frequency) {
    let note = frequencyToNote(frequency);
    console.log(`Нота: ${note}`);
  }
});

Настройка чувствительности и фильтрация шумов

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

const minFrequency = 50; // Гц
pitch.getPitch((err, frequency) => {
  if (frequency && frequency > minFrequency) {
    console.log(`Чистая частота: ${frequency} Hz`);
  }
});

Для улучшения стабильности результата часто используют скользящее среднее по последним N измерениям:

let buffer = [];
const bufferSize = 5;

pitch.getPitch((err, frequency) => {
  if (frequency) {
    buffer.push(frequency);
    if (buffer.length > bufferSize) buffer.shift();
    let average = buffer.reduce((a,b) => a+b, 0) / buffer.length;
    console.log(`Средняя частота: ${average.toFixed(2)} Hz`);
  }
});

Применение PitchDetection

  • Музыкальные приложения: визуализация нот, интерактивные синтезаторы, обучение вокалу.
  • Интерактивные инсталляции: управление объектами в браузере с помощью звука.
  • Анализ голоса: определение интонации, тональности речи, эмоциональной окраски.

Преимущества ml5.js:

  • Работа прямо в браузере без серверной части.
  • Простота интеграции с p5.js и Web Audio API.
  • Поддержка реального времени и высокая точность модели CREPE.

Оптимизация производительности

  • Минимизировать частоту вызовов getPitch, чтобы снизить нагрузку на CPU.
  • Использовать Web Workers для тяжелой обработки сигналов при сложных приложениях.
  • Ограничивать частотный диапазон, если известно, какие ноты или диапазоны используются.

PitchDetection в ml5.js объединяет мощь предобученных моделей с простотой JavaScript, предоставляя разработчикам инструмент для точного и интерактивного анализа звука. Тщательная настройка фильтров, буферизация и преобразование частот в ноты позволяют создавать полноценные музыкальные и аудиоинтерактивные приложения прямо в браузере.