Детект частоты, пиков и огибающей

Осваиваем три ходовых измерения: какая частота в сигнале, где у него пики и какова его огибающая.

Детектирование в DSP — извлечение из сигнала конкретной характеристики: доминирующей частоты, моментов пиков, формы огибающей. Это мостик от «обработки» к «пониманию» сигнала.

Часто от сигнала нужно не очистить его, а измерить: какая нота играет (частота), где удары пульса (пики), как нарастает и спадает громкость (огибающая). Эти три задачи решаются короткими, но очень практичными приёмами. Они лежат в основе тюнеров, пульсометров, детекторов событий.

Детект частоты: пик спектра

Чтобы узнать главную частоту сигнала, считаем спектр (ДПФ) и находим бин с максимальной амплитудой. Его частота k*fs/N — и есть доминирующая. Так работает гитарный тюнер.

import math, cmath

def dft(x):
    N = len(x)
    return [sum(x[n] * cmath.exp(-2j * math.pi * k * n / N) for n in range(N))
            for k in range(N)]

fs, N = 64.0, 64
mystery = [math.sin(2 * math.pi * 8 * n / fs) for n in range(N)]   # тайный тон
X = dft(mystery)
mags = [abs(X[k]) for k in range(N // 2 + 1)]
peak = mags.index(max(mags))
print("Доминирующая частота:", peak * fs / N, "Гц")

Вывод:

Доминирующая частота: 8.0 Гц

Алгоритм безошибочно определил 8 Гц по пику спектра. Для точности «между бинами» применяют интерполяцию вершины, но идея та же: ищем максимум спектра.

Поиск пиков сигнала

Пик — отсчёт, который больше обоих соседей. Поиск локальных максимумов нужен для подсчёта пульса (R-зубцы ЭКГ), детектирования ударов, шагов по акселерометру.

data = [1, 3, 7, 4, 2, 8, 6, 9, 5, 2]
peaks = [i for i in range(1, len(data) - 1)
         if data[i] > data[i - 1] and data[i] > data[i + 1]]
print("Индексы пиков:", peaks)
print("Значения пиков:", [data[i] for i in peaks])
print("Найдено пиков:", len(peaks))

Вывод:

Индексы пиков: [2, 5, 7]
Значения пиков: [7, 8, 9]
Найдено пиков: 3

Три локальных максимума. На практике добавляют порог (игнорировать мелкие пики) и минимальное расстояние между пиками (чтобы не считать один пик дважды из-за дрожания).

Огибающая: выпрямить и сгладить

Огибающая — это «контур громкости» сигнала, плавная кривая, повторяющая, как меняется его амплитуда. Классический способ: взять модуль сигнала (выпрямление) и сгладить ФНЧ. Так детектор огибающей в синтезаторе следит за громкостью.

import math

def convolve_same(x, h):
    M = len(h); pad = M // 2; out = []
    for i in range(len(x)):
        s = 0.0
        for j in range(M):
            idx = i - pad + j
            if 0 <= idx < len(x):
                s += x[idx] * h[j]
        out.append(s)
    return out

# Тон 8 Гц, громкий в первой половине, тихий во второй
sig = [math.sin(2 * math.pi * 8 * n / 64) * (1 if n < 32 else 0.3) for n in range(64)]
rect = [abs(v) for v in sig]                 # выпрямление
env = convolve_same(rect, [1/8] * 8)         # сглаживание
print("Огибающая (каждый 8-й отсчёт):", [round(env[i], 3) for i in range(0, 64, 8)])

Вывод:

Огибающая (каждый 8-й отсчёт): [0.302, 0.604, 0.604, 0.604, 0.392, 0.181, 0.181, 0.181]

Огибающая держится около 0.6 в громкой первой половине и падает до ~0.18 во второй — ровно как менялась амплитуда (1.0 → 0.3). Контур громкости извлечён.

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

Каждый приём опирается на изученную теорию. Детект частоты — это ДПФ плюс поиск максимума; ограничен разрешением fs/N, поэтому для точной частоты нужны длинная запись или интерполяция пика. Поиск пиков — анализ во временной области; его надёжность повышают предварительной фильтрацией (убрать шум, иначе появятся ложные пики) и порогами. Детект огибающей через «модуль + ФНЧ» работает потому, что выпрямление переносит информацию об амплитуде в низкие частоты, а ФНЧ их выделяет. Более точный способ огибающей — аналитический сигнал через преобразование Гильберта, но «выпрямить и сгладить» — быстрый и наглядный приближённый метод.

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

  • Искать пики в шумном сигнале без фильтрации. Шум создаёт множество ложных локальных максимумов; сначала сглаживают.
  • Доверять одному бину при детекте частоты. Из-за утечки и разрешения пик может «съехать»; помогают окно и интерполяция.
  • Сглаживать огибающую слишком слабо. Без достаточного ФНЧ огибающая «дрожит» в такт несущей вместо плавного контура.

Итог

  • Доминирующую частоту находят как пик спектра (бин с максимумом).
  • Пики сигнала — отсчёты больше обоих соседей; на практике с порогом и фильтрацией.
  • Огибающую получают выпрямлением (модуль) и сглаживанием ФНЧ.
  • Все три приёма надёжнее на предварительно очищенном сигнале.
Проверьте себя
1. Как определить доминирующую частоту сигнала?
AНайти максимум во временной области
BНайти бин с максимальной амплитудой в спектре (ДПФ)
CПосчитать среднее сигнала
DВзять первый отсчёт
2. Что такое пик (локальный максимум) сигнала?
AСамый первый отсчёт
BОтсчёт, который больше обоих соседей
CСреднее значение
DОтсчёт, равный нулю
3. Как получить огибающую сигнала простым способом?
AВзять модуль сигнала и сгладить ФНЧ
BПосчитать ДПФ
CВозвести в квадрат и не сглаживать
DВзять каждый второй отсчёт