Энергия, переходы через ноль и основа VAD

Два дешёвых признака, которые до сих пор работают в детекции речи.

ZCR (zero-crossing rate) — частота смены знака сигнала; грубо отражает «высокочастотность» звука и помогает отличать шипящие от гласных.

Не для всего нужны нейросети. Многие практичные признаки считаются прямо во временной области одной формулой. Два классических — краткосрочная энергия и частота переходов через ноль. На них строилась детекция голоса задолго до глубокого обучения, и они до сих пор работают как быстрый предварительный фильтр.

Краткосрочная энергия

Энергия кадра — сумма квадратов его отсчётов. У речи энергия высокая, у тишины — близка к нулю. Это самый простой способ найти, где в записи кто-то говорит, а где пауза.

Переходы через ноль (ZCR)

ZCR считает, сколько раз внутри кадра сигнал сменил знак (перешёл через ноль). Высокочастотные звуки (шипящие «с», «ш») колеблются часто — высокий ZCR. Низкочастотные гласные — низкий ZCR. Интересно, что у тишины с шумом ZCR тоже высокий, но энергия низкая — комбинация двух признаков уже неплохо различает речь, шипящие и тишину.

ТипЭнергияZCR
Гласный (а, о)высокаянизкий
Шипящий (с, ш)средняявысокий
Тишинанизкаялюбой

Считаем оба признака

frame = [0.0, 0.5, -0.3, 0.4, -0.6, 0.2, -0.1, 0.3]

energy = sum(x * x for x in frame)

crossings = 0
for i in range(1, len(frame)):
    if (frame[i - 1] < 0) != (frame[i] < 0):
        crossings += 1
zcr = crossings / (len(frame) - 1)

print("Энергия:", round(energy, 3))
print("Переходов через ноль:", crossings)
print("ZCR:", round(zcr, 3))

Вывод:

Энергия: 1.0
Переходов через ноль: 6
ZCR: 0.857

Высокий ZCR при заметной энергии — похоже на шипящий звук. Так, имея лишь две формулы, мы уже что-то «понимаем» про содержимое кадра.

Простейший VAD по порогу энергии

VAD (Voice Activity Detection) — детекция речи. Простейшая версия: считаем энергию по кадрам и сравниваем с порогом.

frames_energy = [0.01, 0.02, 0.8, 1.2, 0.9, 0.03, 0.01, 0.7]
threshold = 0.1

for i, e in enumerate(frames_energy):
    label = "речь" if e > threshold else "тишина"
    print("кадр", i, "энергия", e, "->", label)

Вывод:

кадр 0 энергия 0.01 -> тишина
кадр 1 энергия 0.02 -> тишина
кадр 2 энергия 0.8 -> речь
кадр 3 энергия 1.2 -> речь
кадр 4 энергия 0.9 -> речь
кадр 5 энергия 0.03 -> тишина
кадр 6 энергия 0.01 -> тишина
кадр 7 энергия 0.7 -> речь

Сила связки «энергия + ZCR» в том, что она почти бесплатна по вычислениям и не требует ни нейросети, ни даже преобразования Фурье — только сложения и сравнения знаков. Поэтому такой простой VAD до сих пор живёт там, где важны экономия и скорость: в наушниках с шумоподавлением, в чипах умных колонок, которые должны постоянно «слушать» в режиме ожидания на крошечной батарее. Гонять полноценную нейросеть ради того, чтобы понять «есть звук или тишина», расточительно; дешёвый порог по энергии отсеивает паузы, и тяжёлая модель ASR просыпается только на реальной речи.

Почему именно пара признаков работает лучше каждого по отдельности? Возьмём тихую комнату с лёгким фоновым шипением вентилятора. По одной энергии это похоже на паузу — уровень низкий. Но если порог поставить слишком низко, шипение пролезет как «речь». ZCR здесь спасает иначе: и у шипящих согласных, и у фонового шума переходов через ноль много, поэтому сам по себе высокий ZCR речь не доказывает. А вот сочетание — заметная энергия плюс умеренный ZCR — уже неплохо указывает на гласные, то есть на ядро речи. Один признак легко обмануть, два вместе — гораздо труднее.

Важная честная оговорка: пороговый VAD прост, но хрупок. Стоит появиться громкой музыке, гулу улицы или нескольким говорящим сразу — и фиксированный порог по энергии начинает путать шум с речью и наоборот. Поэтому в шумных условиях его либо делают адаптивным (порог подстраивается под текущий уровень фона), либо заменяют на нейросетевой VAD вроде Silero, который обучен отличать именно человеческий голос, а не просто «громкое от тихого». Классические энергия и ZCR при этом не исчезают — они часто остаются дешёвым первым фильтром перед более умной моделью.

Как работает под капотом

Современные VAD (например, Silero) — это маленькие нейросети, точные даже в шуме. Но их идея та же: по кадрам выдавать «речь / не речь». Энергия и ZCR остаются полезны как лёгкая первая ступень в конвейере — они почти бесплатны по вычислениям и отсекают очевидную тишину до запуска тяжёлых моделей. В разделе про шумоподавление мы вернёмся к VAD подробнее.

Частые ошибки

  • Жёсткий фиксированный порог энергии. В шумной записи тишина «громкая» — порог надо адаптировать.
  • Использовать только энергию. Тихие шипящие можно принять за тишину; ZCR помогает.
  • Считать ZCR панацеей. На сильном шуме ZCR теряет смысл — нужны спектральные признаки.

Итоги

  • Краткосрочная энергия отделяет речь от тишины.
  • ZCR (частота переходов через ноль) различает высоко- и низкочастотные звуки.
  • Комбинация энергии и ZCR — основа классического VAD.
  • Современные VAD — нейросети, но с той же идеей «речь/не речь по кадрам».
Проверьте себя
1. Что показывает краткосрочная энергия кадра?
AВысоту тона
BСилу сигнала: у речи высокая, у тишины около нуля
CЯзык речи
DЧисло каналов
2. Чем характерен высокий ZCR?
AНизкочастотными гласными
BВысокочастотными звуками вроде шипящих
CПолной тишиной без шума
DБольшой громкостью
3. Почему энергию и ZCR используют вместе?
AЧтобы запутать модель
BЭнергия отделяет речь от тишины, ZCR различает типы звуков — вместе надёжнее
CОни одинаковы
DZCR заменяет энергию полностью