Это снова мой детектор храпа.
Я довольно хорошо обнаружил сигнал, когда там что-то есть - может отслеживать от храпа стены до дыхания, которое вы даже не можете услышать в записи. Проблема в том, что я не могу сказать, когда сигнал упал ниже обнаруживаемого уровня, а приложение просто «слышит». И, к сожалению, храп / дыхание часто бывает нерегулярным, поэтому простая автокорреляционная или подобная временная схема интервалов вряд ли сильно поможет. (И вполне вероятно, что в некоторых случаях шум более равномерный, чем дыхание.)
Итак, есть ли какие-то хитрости, которые мне не хватает для выяснения, когда нет сигнала? Кажется, что я нахожусь здесь в трудном положении, учитывая, что «сигнал» с самого начала такой шумный.
(И, возможно, это связано с другой проблемой, с которой я столкнулся: странно, я не могу точно (или даже приблизительно) измерить уровень сигнала, даже если он достаточно громкий. Так как мне все равно нужно использовать скользящие средние и отношения для обнаружения сигнала, информация об уровне теряется. Я ищу некоторые приемы, чтобы восстановить ее.)
Основная техника
(Для йоды)
Аудиосигнал дискретизируется (как правило, на 8000 Гц по разным причинам), а затем FFT-форматируется в 1024 блоках. (В моих экспериментах фильтры Хемминга и перекрывающиеся блоки, похоже, оказали небольшое влияние, хотя они могут быть пересмотрены позже.)
БПФ делится на «полосы» (в настоящее время 5, слегка искаженные по размеру, чтобы разместить больше деталей на нижнем уровне), и «спектральная разность» и уровень каждой полосы суммируются. Долгосрочные средние значения ограниченных пиков используются в качестве «пороговых значений», а дальнейшие корректировки смещения используются для поддержания «порогового» уровня примерно на 20%.
Каждому значению «за порог» присваивается вес 1 (под порогом присваивается вес 0), но затем этот вес корректируется с помощью кажущейся «изменчивости» (примерно на 2 Гц) в полосе, чтобы придать полосам больший вес которые несут более очевидный сигнал.
Веса полос суммируются, а затем суммированные веса последующих блоков суммируются в течение примерно секунды, чтобы получить текущий «счет». Это снова сравнивается со скользящим средним порогом (плюс несколько эвристик) для обнаружения начала / смещения храпа.
Обновить
Мне вдруг пришло в голову, что, если мой алгоритм эффективно поддерживает сигнал постоянного уровня (в соответствии с моей проблемой уровня сигнала), способ эффективно измерить SNR - это измерение шума, когда сигнала нет.
Удобно, что храп прерывист, с большим количеством "мертвого воздуха" между ними. И я уже обнаруживаю конверты храпа. Поэтому все, что находится за пределами конверта (между концом одного храпа и началом следующего), по-видимому, является шумом! Это я могу (с некоторой скромной степенью точности / повторяемости) измерить. (Конечно, потребовалось три попытки, чтобы придумать наполовину приличный алгоритм - реальность никогда не соответствует теории.)
У меня пока нет полного ответа, но я добился прогресса.
(Хотя описанная выше методика дает мне довольно хороший прокси-сервер для SNR, у меня все еще возникают проблемы с оценкой фактического уровня сигнала. Мои индикаторы «относительного уровня» могут быть за пределами шкалы для едва слышимого дыхания и, тем более, для шумового окна. Мне нужен какой-то прокси для абсолютного уровня.)