Это ВЕБ-цепочка, целиком внутри WebView. Companion здесь не участвует ни в каком
виде: премиум-эффектов (сатуратор, биткрашер) на этой странице нет физически, кнопок на
локскрине не будет, звук идёт из браузера. Всё, что касается Companion, — на странице
dashboard.html, и там обязателен зелёный индикатор.
Зачем эта страница. Device-прогон 0.A показал CPU-запас 17× и детерминизм
corr 1.0, но звук на слух плохой. ADR-0020 фиксирует: причина — реализация DSP, а не
предел стека, и предлагает вариант A — остаться на едином Faust-ядре (паритет
web↔Companion, ADR-0015), а качество решить инженерно. Эта страница сравнивает
V1 (текущая цепочка) и V2 (редизайн) и измеряет разницу —
«на слух» для приёмки ADR-0020 явно объявил недостаточным.
Что изменено в V2 (3 эффекта из ADR-0020): 1. Дисторшн → ADAA1. В Faust один sample rate, поэтому истинный оверсэмплинг
внутри process невыразим (это важное ограничение, ADR-0020 предполагал
оверсэмплинг). Вместо него — aa.tanh1: антиалиасинг методом
антипроизводной 1-го порядка. Давит алиасинг на самой нелинейности и снимает
необходимость в post-LPF 12 кГц, которым V1 глушила верх. 2. Lo-fi → анти-image + TPDF-дизер. V1 ставила LPF только ПЕРЕД децимацией.
Но sample-and-hold — это ZOH, он порождает образы выше новой частоты Найквиста;
именно они и есть «писк», и pre-LPF их не убирает. V2 добавляет post-LPF после
квантования и TPDF-дизер (декоррелирует ошибку квантования → окраска вместо
«цифровой грязи»). 3. Реверб → re.zita_rev1_stereo. V1 — два независимых
mono_freeverb, псевдо-стерео. V2 — настоящий стерео-ревербератор с
pre-delay 20 мс, раздельным T60 по НЧ/СЧ и equal-power wet/dry (V1 линейно
микшировала → провал громкости на середине регулятора).
Детерминизм не нарушен.no.noise в Faust — LCG с фиксированным
seed 12345, сбрасываемым на init, так что дизер воспроизводим. Ползунок
dither = 0 даёт бит-точный режим для §11, если понадобится.
Паритет — проверить при переносе в Companion.aa.tanh1 делит на
разность отсчётов, и библиотека требует double. Web-цепочка компилируется с
-double; сборка NDK в Companion должна использовать ту же точность,
иначе ADR-0015 (паритет web↔native) поедет. Фактические флаги компиляции попадают
в отчёт ниже.
§13.0 Компиляция
не запускалось
Каждый DSP компилируется независимо и ловит свою ошибку — неверная сигнатура в одном
эффекте не роняет остальные измерения. Компиляция идёт на устройстве
(@grame/faustwasm@0.16.3), первый вызов заметно дольше.
§13.1 Алиасинг и THD дисторшна
Главное число этой страницы. Синус подаётся в изолированную нелинейность,
выход раскладывается FFT (32768, окно Ханна). Бины делятся на три группы:
основной тон, гармоники k·f0 и всё остальное — это и есть
алиасинг (продукты, отражённые от Найквиста).
Тоны 5000 и 7000 Гц выбраны так, что при 48 кГц ни один отражённый продукт не
попадает на кратную f0 частоту — иначе алиасинг был бы неотличим от гармоники
(по этой причине 1000 Гц для такого теста непригоден).
Критерий приёмки:aliasToSignalDb у V2 должен быть заметно ниже
V1. Разница в 10–20 дБ — это и есть инженерное доказательство варианта A.
Результат прогона 2026-08-01 (Pixel 4a): критерий НЕ выполнен. 5 кГц −0.74 дБ
(V2 хуже), 7 кГц +0.96 дБ — вместо 10–20 дБ. Абсолютный пол алиасинга ~−43 дБ у обеих
версий. Улучшилось только отношение alias/гармоники на 7 кГц (+8.9 → −15.85 дБ), но
из-за роста гармоник после снятия post-LPF 12 кГц, а не из-за падения алиасинга.
Вывод: ADAA1 не заменяет оверсэмплинг — истинный оверсэмплинг доступен только
нативно (ADR-0022/0023), и замена в ADR-0020 требует пересмотра.
не запускалось
§13.2 АЧХ полной цепочки
Логарифмический свип 20 Гц → 20 кГц рендерится дважды: без обработки (референс) и
через цепочку. Отношение спектров по третьоктавным полосам даёт АЧХ. Показывает,
сколько верха съедает lo-fi и что реально делает EQ. Метод приблизительный
(цепочка нелинейна, энергия перераспределяется), годится для «где завал», не для
сертификации.
не запускалось
§13.3 Реверб: T60, стерео, Faust vs нативная свёртка
Импульс через ревербератор, обратное интегрирование Шрёдера по кривой затухания →
оценка T60 (по наклону −5…−25 дБ). Корреляция L/R по хвосту: у настоящего стерео она
заметно ниже 1, у псевдо-стерео близка к 1.
Третьим прогоняется нативный ConvolverNode с синтезированным IR
(экспоненциально затухающий декоррелированный шум) — это прямой A/B «Faust-реверб vs
нативная свёртка», который ADR-0020 назвал условием выбора между A и C.
Исправлено после прогона 2026-08-01. Тогда t60Sec вышел
null у обеих Faust-версий, а нативная свёртка померилась штатно — то есть
ломалось измерение, а не ревербы. Причина: импульс подавался в нулевой отсчёт, когда
revMix ещё не разогнался через si.smoo, поэтому сквозь микс
проходил сухой импульс и забивал интеграл Шрёдера. Теперь меряется чистый wet
(отдельные DSP без сухого пути и без слайдера микса), импульс сдвинут на 0.25 с, а
рядом считается tailRmsDb — он отличает «хвоста нет» (−100 дБ и ниже) от
«измерение не сошлось».
не запускалось
§13.4 Цена качества по CPU
Тот же оффлайн-прокси, что в §10.2 (renderSpeed = длительность / время рендера).
ADAA и zita дороже наивных версий — надо убедиться, что запас 17× не съеден.
Ниже 3–5× появляется риск glitch на слабом CPU.
не запускалось
§13.5 Слепое прослушивание
Переключение без перезапуска трека — обе цепочки собраны заранее и работают
параллельно, звучит только выбранная. Слушать: «писк» lo-fi, грязь дисторшна,
объём и хвост реверба, провал громкости при среднем reverbMix.
Три ручки выше есть только у V2 — ими и ищется рабочая точка lo-fi. Меньше бит =
грязнее и характернее; анти-image на 0 оставляет ZOH-образы (тот самый «писк»),
на 1 давит их вместе с характером. Найденные значения потом переносятся в
companion-poc/effect.dsp, а не остаются на этой странице.