Такой вопрос:
Если необходимо детектировать 8 частот, которые приходят в случайном порядке ( DTMF передача данных), то при успешном детектировании одной из частот (когда модуль искомой частоты перевалит за порог), следует обнулять I и Q ? Верно ли я понимаю?
И еще: если на входе алгоритма присутствует шум, или просто звук, который не содержит искомой компоненты, то модуль растет со временем. Допустим, я ставлю порог равным 5000. Из-за шума модуль постепенно доползет до 5000 за несколько секунд, и произойдет ложное детектирование, хотя искомый сигнал так и не пришел. Что в этом случае необходимо делать? Есть мысль обнулять I и Q с определенной периодичностью, но тогда теряется смысл SDFT. Есть мысль резать шум, то есть принимать все семплы, которые ниже определенного уровня, равными нулю. Но это как-то слишком топорно.
Модифицированный алгоритм Герцеля
- Бахурин Сергей
- Администратор
- Сообщения: 1116
- Зарегистрирован: 05 окт 2010, 19:55
- Контактная информация:
Re: Модифицированный алгоритм Герцеля
Вероятно, что у вас просто ошибка. Модуль не должен расти со временем.
- Santik
- Сообщения: 609
- Зарегистрирован: 28 дек 2010, 08:04
- Откуда: Мирный (Якутия)
- Контактная информация:
Re: Модифицированный алгоритм Герцеля
Re: Модифицированный алгоритм Герцеля
Хм. Взял реализацию, предложенную вами несколько сообщений назад. В ней ошибки вроде нет.
Единственное что заменил, так это инициализацию массива ADC[]:
Код: Выделить всё
#define N 147 //размер окна
#define K 294 //кол-во семплов всего
for (int i =0; i<K; i++)
{
//вторая половина 294 семплов (от 147 до 293) равна постоянному уровню 100
if ((i/147)%2)
{
ADC[i]=100;
}
else
{
//первая половина (от 0 до 146) равна искомой частоте со сдвигом фазы.
ADC[i] = (unsigned char) 100*sin((c*i + M_PI/5))+100;
}
}
После 147 семпла (номер 146) идут нули. Ровно 147 семплов, до 294 семпла (293 номер). Модуль растет все равно. Даже если обнулить I и Q, все равно растет из-за наличия искомой частоты на 147 семплов назад.
То есть рост модуля происходит за счет:
Код: Выделить всё
u = I[0] + ADC[n] - ((n>=N) ? ADC[n-N] : 0.0);
Получается, что надо еще 147 семплов не посылать в буфер искомую частоту. То есть , как я понял , получается примерно так:
[0..146] = sin(2pi*17000t) => рост модуля, на номере 146 модуль максимален
[147..293] = 100 => рост модуля продолжается за счет предыдущих 147 семплов. Можно словить ложное детектирование
[294..440] = роста нет, все предыдущие 147 семплов равны нулю.
Последний раз редактировалось Heavy 03 мар 2016, 18:36, всего редактировалось 1 раз.
Re: Модифицированный алгоритм Герцеля
Нет, там на счет округления намекали. С этим можно бороться. У Лайонса написано как. Но это добавляет еще кучу вычислительных операций. Тестирую алгоритм на QT и на STM32F103VET. На QT буфер генерю программно, на STM буфер шлю через звуковую карту, звук генерю тоже через QT. С генерацией буфера и звука проблем нет. Пока что хотя бы на QT отладить.Santik писал(а):Может на этот эффект Вам намекали здесь?
http://electronix.ru/forum/index.php?sh ... 33098&st=0
Re: Модифицированный алгоритм Герцеля
Прихожу к выводу, что после детектирования частоты необходимо не только обнулить I и Q, но еще и предыдущие N семплов принять равными 0.
Re: Модифицированный алгоритм Герцеля
Записал видео с своей реализацией https://youtu.be/FhoelOKbjfk?t=964 . Сильно не пинайте за путаницу в терминологии, и за неуверенность в некоторой матчасти. Видео около часа длительностью. Примерно с 16 минуты запускаю алгоритм, и начинаю тестить и показывать что получается. В итоге прихожу в ступор.
Re: Модифицированный алгоритм Герцеля
Не знаю, нашел ли автор топика ответы на свои вопросы. Видео я смотреть не стал.
Поскольку мне была интересна эта тема, я решил попробовать реализовать приведенный алгоритм.
В исходном варианте у меня модуль не уменьшался. То есть, если фильтр сработал на какую-то частоту, то его значение не уменьшалось, даже если этой частоты уже нет в сигнале.
Однако вот такая модификация: умножение на коэффиент 0.9995 значений a и b
a = 0.9995 * Math.Cos(2.0 * Math.PI * k0 / filterConfig.FrameSamplesCount);
b = 0.9995 * Math.Sin(2.0 * Math.PI * k0 / filterConfig.FrameSamplesCount);
при каждом вычислении модуля, будет уменьшать его.
И еще, чтобы величина модуля оставалась постоянной от частоты, его можно вычислять так:
value = Math.Sqrt(i1 * i1 + q1 * q1) / k0;
k0 это "номер гармоники"
Вот что у меня получилось: https://github.com/jauseg/GoertzelOnTheFly
Как это прикрутить к ардуинке со светодиодной лентой я пока еще не придумал.
Поскольку мне была интересна эта тема, я решил попробовать реализовать приведенный алгоритм.
В исходном варианте у меня модуль не уменьшался. То есть, если фильтр сработал на какую-то частоту, то его значение не уменьшалось, даже если этой частоты уже нет в сигнале.
Однако вот такая модификация: умножение на коэффиент 0.9995 значений a и b
a = 0.9995 * Math.Cos(2.0 * Math.PI * k0 / filterConfig.FrameSamplesCount);
b = 0.9995 * Math.Sin(2.0 * Math.PI * k0 / filterConfig.FrameSamplesCount);
при каждом вычислении модуля, будет уменьшать его.
И еще, чтобы величина модуля оставалась постоянной от частоты, его можно вычислять так:
value = Math.Sqrt(i1 * i1 + q1 * q1) / k0;
k0 это "номер гармоники"
Вот что у меня получилось: https://github.com/jauseg/GoertzelOnTheFly
Как это прикрутить к ардуинке со светодиодной лентой я пока еще не придумал.