STFT и спектрограмма: спектр во времени
Решаем проблему обычного ДПФ: оно показывает «средний» спектр, а нам нужно видеть, как спектр меняется во времени.
STFT (кратковременное преобразование Фурье) — нарезка сигнала на короткие кадры и ДПФ каждого кадра; результат — спектрограмма, картина «частота × время».
Обычное ДПФ имеет фундаментальный недостаток: оно даёт один спектр на весь сигнал. Но реальные сигналы — речь, музыка — меняются: сначала звучит одна нота, потом другая. ДПФ всего сигнала покажет обе ноты сразу, но не скажет, какая была раньше. STFT решает это: считает спектр маленькими кусочками и показывает эволюцию частот во времени.
Идея: режем на кадры
Сигнал делят на короткие кадры (например, по 8–1024 отсчёта), каждый умножают на окно и считают ДПФ. Получается набор спектров — по одному на каждый момент времени. Возьмём сигнал, у которого в первой половине низкий тон, во второй — высокий, и проанализируем по кадрам.
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)]
def peak_bin(frame):
X = dft(frame); N = len(frame)
mags = [abs(X[k]) for k in range(N // 2 + 1)]
return mags.index(max(mags))
fs = 8.0
frame1 = [math.sin(2 * math.pi * 1 * n / fs) for n in range(8)] # низкий тон
frame2 = [math.sin(2 * math.pi * 3 * n / fs) for n in range(8)] # высокий тон
print("Кадр 1: пик на бине", peak_bin(frame1), "->", peak_bin(frame1) * fs / 8, "Гц")
print("Кадр 2: пик на бине", peak_bin(frame2), "->", peak_bin(frame2) * fs / 8, "Гц")
Вывод:
Кадр 1: пик на бине 1 -> 1.0 Гц Кадр 2: пик на бине 3 -> 3.0 Гц
Первый кадр показал 1 Гц, второй — 3 Гц. Мы увидели, что частота выросла со временем — то, чего обычное ДПФ всего сигнала не показало бы.
Спектрограмма: рисуем частоту во времени
Если выложить спектры кадров в строки (время по вертикали, частота по горизонтали) и закрасить ячейки по амплитуде, получится спектрограмма. Нарисуем её ASCII-символами.
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)]
def mag(frame):
X = dft(frame); N = len(frame)
return [round(abs(X[k]) / (N / 2), 2) for k in range(N // 2 + 1)]
fs = 8.0
frames = [
[math.sin(2 * math.pi * 1 * n / fs) for n in range(8)],
[math.sin(2 * math.pi * 2 * n / fs) for n in range(8)],
[math.sin(2 * math.pi * 3 * n / fs) for n in range(8)],
]
print("частоты: 0 1 2 3 4 Гц")
for i, fr in enumerate(frames):
row = "".join("#" if v > 0.5 else ("." if v > 0.1 else " ") for v in mag(fr))
print(f"кадр {i}: |{row}|")
Вывод:
частоты: 0 1 2 3 4 Гц кадр 0: | # | кадр 1: | # | кадр 2: | # |
Решётка «#» ползёт слева направо — это чирп, тон с растущей частотой. Спектрограмма наглядно показала движение частоты во времени; так выглядят свистки, сирены, восходящие глиссандо.
Кадр, перекрытие и компромисс
Длина кадра задаёт фундаментальный компромисс между разрешением по времени и по частоте. Короткий кадр — хорошо видно когда сменилась частота (точность по времени), но плохо какая именно (грубое разрешение по частоте fs/N). Длинный кадр — наоборот. Это проявление принципа неопределённости в DSP: нельзя одновременно точно знать и время, и частоту события. Чтобы сгладить швы между кадрами, их берут с перекрытием (обычно 50%) и оконной функцией.
Как работает под капотом
STFT — это мост между DSP и аудио-AI. Спектрограмма — это, по сути, «изображение» звука: по нему распознавалки речи и музыки работают как с картинкой, подавая её в нейросеть. Популярный вариант — мел-спектрограмма, где частотная ось искажена под восприятие человеческого уха (мел-шкала), что делает признаки ближе к тому, как слышим мы. На спектрограмме видны форманты гласных, гармоники нот, шумовые согласные — поэтому она основной инструмент анализа речи. Связь с курсом «Распознавание речи»: там спектрограмма — вход модели, а здесь мы видим, как она устроена изнутри.
Частые ошибки
- Брать слишком длинный кадр для быстрых событий. Короткий щелчок «размажется» по времени и потеряет локализацию.
- Анализировать кадры без окна и перекрытия. На стыках появятся артефакты, спектрограмма «зарябит».
- Ждать одновременно идеального разрешения по времени и частоте. Это запрещено принципом неопределённости — всегда компромисс.
Итог
- STFT режет сигнал на кадры и считает ДПФ каждого — спектр становится функцией времени.
- Спектрограмма — картина «частота × время», по сути «изображение» звука.
- Длина кадра — компромисс между разрешением по времени и по частоте.
- Спектрограмма (и мел-вариант) — основной вход для распознавания речи и музыки.