Автор Тема: Игорь, есть вопрос.  (Прочитано 526026 раз)

0 Пользователей и 16 Гостей просматривают эту тему.

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Игорь, есть вопрос.
« Ответ #960 : Сентябрь 17, 2020, 09:59:11 pm »
Вот отображение панорамы с логарифмом, а без него почти в два раза быстрее отрисовывается
Это реально сформированный и отфильтрованный сигнал с полосой панорамы 12кГц
полоса самого фильтра 3кГц
« Последнее редактирование: Сентябрь 17, 2020, 10:02:10 pm от ra0ahc »
Да да, я знаю, у меня ничего не получится )))

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Игорь, есть вопрос.
« Ответ #961 : Сентябрь 17, 2020, 10:03:04 pm »
коэффициенты FIR фильтра
Ну собственно это расчет этого фильтра
Да да, я знаю, у меня ничего не получится )))

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Игорь, есть вопрос.
« Ответ #962 : Сентябрь 17, 2020, 10:04:39 pm »
CMSIS DSP рулит!
Спасибо Геннадию за подсказку.
Да да, я знаю, у меня ничего не получится )))

Оффлайн Relayer

  • Hero Member
  • *****
  • Сообщений: 1006
  • UR5FFR
Re: Игорь, есть вопрос.
« Ответ #963 : Сентябрь 17, 2020, 10:15:03 pm »
Не совсем понял что вы делаете и как рисуете спектр. Логарифм "по быстрому" можно посчитать вот как. Вначале умножаем/делим на 2 столько раз чтобы привести (нормализовать) аргумент к диапазону 1..2. А дальше делаем таблицу и кусочно-линейной аппроксимацией по ней шпарим. Т.к. умножение/деление на 2 - это сдвиги, а аппроксимация по таблице - одно сложение и сдвиг то алгоритм по сути работает без умножений и делений и позволяет эффективную реализацию
В любой схеме есть как минимум одна ненужная деталь :)

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Игорь, есть вопрос.
« Ответ #964 : Сентябрь 17, 2020, 10:37:37 pm »
Кусочик из прорисовки:
 
       arm_sqrt_f32(pOut[ i ] * pOut[ i ] + pOut[i+1] * pOut[i+1],&pO);
        uint16_t y = (uint16_t) (30 * log10f(pO));

y - это амплитуда

По итогу полноценная логарифмическая панорама получается.  НО! этот лог портит скорость прорисовки.
Я тоже думал, что просто таблицу просчитать этих лог, да брать ближайший, но что-то многовато элементов.
Да да, я знаю, у меня ничего не получится )))

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Игорь, есть вопрос.
« Ответ #965 : Сентябрь 17, 2020, 10:44:42 pm »
Вначале умножаем/делим на 2 столько раз чтобы привести (нормализовать) аргумент к диапазону 1..2. А дальше делаем таблицу и кусочно-линейной аппроксимацией по ней шпарим. Т.к. умножение/деление на 2 - это сдвиги, а аппроксимация по таблице - одно сложение и сдвиг то алгоритм по сути работает без умножений и делений и позволяет эффективную реализацию
Я покурю вашу идею, спасибо
Да да, я знаю, у меня ничего не получится )))

Оффлайн Relayer

  • Hero Member
  • *****
  • Сообщений: 1006
  • UR5FFR
Re: Игорь, есть вопрос.
« Ответ #966 : Сентябрь 17, 2020, 10:51:01 pm »
но что-то многовато элементов
Так вот для этого и делается нормализация умножением/делением на 2. Походу получаем вот что
log(x) = log(a*2^n) = log(a) + n*log(2) где 1<a<2
диапазон от 1 до 2 это 6дб. таблицы из 16 элементов вполне хватит
« Последнее редактирование: Сентябрь 17, 2020, 10:53:04 pm от Relayer »
В любой схеме есть как минимум одна ненужная деталь :)

Оффлайн Игорь 2

  • Administrator
  • *****
  • Сообщений: 19666
Re: Игорь, есть вопрос.
« Ответ #967 : Сентябрь 17, 2020, 11:30:03 pm »
Игорь, подскажите пожалуйста, по вашей части.
lg() чем можно по проще заменить?

Чисто с математической точки зрения, любая функция раскладывается в ряд Тейлора. Чем больше членов ряда используете, тем выше точность.
Вот гляньте, я пять членов ряда взял, синий - ln(x), красный - ряд Тейлора.  123123
Перевести логарифм на любое иное основание как два пальца об асфальт.... lllol
Понятно, можно и кусочками лепить - каждое кратное увеличение аргумента логарифмической функции соответствует прибавлению к предыдущему результату функции одного и того же числа, которое, как несложно догадаться, как раз-то и равно логарифму от множителя.  1yep
« Последнее редактирование: Сентябрь 17, 2020, 11:35:34 pm от Игорь 2 »
Ничего невозможного нет

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Игорь, есть вопрос.
« Ответ #968 : Сентябрь 18, 2020, 08:00:36 am »
Да, Игорь , спасибо. Но у меня нет опыта в алгебре. С института прошло более 20 лет, хотя по матану всегда было отлично.
Я не смогу адаптировать ln в lg
Инет внятного ответа не даёт за десятичный логарифм. Есть ещё проблема. Учитывая, что алгоритм работает в критичном по времени месте, то возведение в степень может дать серьезную задержку. Хотя, фактически это умножение, а в stm32 стоит мат сопроцессор , который умножает два числа с плавающей запятой за 18 тактов (без fpu за 900 тактов)
Да да, я знаю, у меня ничего не получится )))

Оффлайн 6Ж2П

  • Hero Member
  • *****
  • Сообщений: 505
Re: Игорь, есть вопрос.
« Ответ #969 : Сентябрь 18, 2020, 08:59:39 am »
Надо просто масштабировать
ln(a)= lg(a)/lg(e) ---> lg(a)=ln(a)*0,43429448190325...

Оффлайн Relayer

  • Hero Member
  • *****
  • Сообщений: 1006
  • UR5FFR
Re: Игорь, есть вопрос.
« Ответ #970 : Сентябрь 18, 2020, 09:13:18 am »
Чисто с математической точки зрения, любая функция раскладывается в ряд Тейлора. Чем больше членов ряда используете, тем выше точность.
Ряд Тейлора - красивая математика, но в данном случае она будет требовать излишних ресурсов. Тут ведь надо приблизительно получить значение логарифма. Мой метод со сдвигами и таблицей будет работаь в РАЗЫ быстрее. Более того, если мы работаем с плавающей точкой то там и сдвиги не особо нужны, потому что плавающее уже представлено в виде мантиссы и порядка, при этом мантисса всегда нормализирована. Для мантиссы тоже делаем lookup таблицу и тогда все вычисление логарифма уложится в два lookup'а, одно умножение и одно сложение :)

PS и вообще - гугль рулит. запрос "fast log approximation" выдает сразу то что надо:
https://www.flipcode.com/archives/Fast_log_Function.shtml
https://stackoverflow.com/questions/39821367/very-fast-approximate-logarithm-natural-log-function-in-c
https://tech.ebayinc.com/engineering/fast-approximate-logarithms-part-i-the-basics/
https://tech.ebayinc.com/engineering/fast-approximate-logarithms-part-iii-the-formulas/

Обратите внимание что в оптимизированных версиях используется именно то что я и предложил - с таблицами :)
« Последнее редактирование: Сентябрь 18, 2020, 09:25:28 am от Relayer »
В любой схеме есть как минимум одна ненужная деталь :)

Оффлайн r1tx

  • Sr. Member
  • ****
  • Сообщений: 490
Re: Игорь, есть вопрос.
« Ответ #971 : Сентябрь 18, 2020, 10:06:20 am »
ra0ahc, а спектрограмму тобишь водопад вы сдвигом части дисплея делаете?

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Игорь, есть вопрос.
« Ответ #972 : Сентябрь 18, 2020, 10:12:38 am »
https://tech.ebayinc.com/engineering/fast-approximate-logarithms-part-i-the-basics/
вот этот быстрее чем родной.

остальные имеет непонятки.


ra0ahc, а спектрограмму тобишь водопад вы сдвигом части дисплея делаете?
нет еще , с фильтрами разбираюсь. Это же все должно "на лету" делаться если дсп в процессоре делать.
Да да, я знаю, у меня ничего не получится )))

Оффлайн Игорь 2

  • Administrator
  • *****
  • Сообщений: 19666
Re: Игорь, есть вопрос.
« Ответ #973 : Сентябрь 18, 2020, 10:37:50 am »
Надо просто масштабировать
ln(a)= lg(a)/lg(e) ---> lg(a)=ln(a)*0,43429448190325...

Вот-вот, 8 класс средней школы... 1yep 44443 pl33
Ничего невозможного нет

Оффлайн ra0ahc

  • Hero Member
  • *****
  • Сообщений: 4872
  • Сергей, RD6AH
Re: Игорь, есть вопрос.
« Ответ #974 : Сентябрь 18, 2020, 11:09:17 am »
Этот алгоритм тоже работает быстрее чем стандартный 
Кстати, это как раз то о чем говорил Андрей.




//log2
#define  LogPrecisionLevel  2
#define  LogTableSize  0b100
double log_table[LogTableSize];
//


void init_log_table(void) {
    for (int i = 0; i < LogTableSize; i++) {
        log_table = log2(1 + (double)i /LogTableSize);
    }
}

double fast_log2(double x) { // x>0
   unsigned  long long t = *(unsigned long long*)&x;
    int exp = (t >> 52) - 0x3ff;
    int mantissa = (t >> (52 - LogPrecisionLevel)) & (LogTableSize - 1);
    return exp + log_table[mantissa];
}


« Последнее редактирование: Сентябрь 18, 2020, 11:22:00 am от ra0ahc »
Да да, я знаю, у меня ничего не получится )))