Как стать автором
Обновить

Комментарии 28

Статья выглядит так, как будто автор не знаком с комплексными числами.
хотя в других реализациях эти вызовы будут

Скорее всего не во внутреннем цикле — там просто будут использоваться табличные значения.
Кстати насколько разошлись значения синуса и косинуса от реальных на последнем шаге?

Оригинальная статья умалчивает, но я провел собственное расследование: ссылка
Результаты:


BEFORE: Sin = +0.00000000000000000000 (expected 0), Cos = +1.00000000000000000000 (expected 1)
AFTER:  Sin = -0.00000000000000035196 (expected 0), Cos = +1.00000000000642160630 (expected 1)
ERROR:  Sin = -0.00000000000000035196 (expected 0), Cos = +0.00000000000642160630 (expected 0)
ERROR:  Sin = -3.51959e-16 (expected 0), Cos = +6.42161e-12 (expected 0)

То есть, на 1 миллион итераций точность около 10-12 знаков.
Для сравнения:
Точность float (32): 7-8 знаков
Точность double (64): 15-17 знаков
Точность long double (80): 18-19 знаков
Я использовал long double.

От шага же зависит. Чем меньше шаг, тем меньше врёт.
Для генератора сигналов на бюджетных МК — вполне годно. Там вытянуть амплитуду можно в аналоговой части

Там нет монотонной зависимости, сначала точность растёт, но всё же с определённого момента начинает падать.

Ох, не первых лабах по симуляции показывают как уменьшение дельты приводит к взрыву. А всё из-за флотов и ошибки в точности, при маленькой дельте, ошибка одной итерации начинает приближаться к самой дельте. Пробуйте.
да пробовал, еще на фиксированной точке для аудио нужд с частотой колебаний от 10Гц, до нескольких кГц. Т.е. дельта не сферическая, а вполне себе злободневная.
Пользоваться, в принципе, можно. Еще и короче (и шустрее) библиотечных вариантов получается. С фиксированной точкой дружит.

А, например, arm_sin_f32 считает синус по табличке с шагом чуть ли не в 1 градус и кубической интерполяции. К этой библиотеке тоже есть вопросы по точности.

Чем меньше шаг — тем больше самих шагов.

Гражданин Герцель вам 5 умножений во внутреннем цикле поможет сэкономить, с осциллятором второго порядка, вместо честного поворота умножением на матрицу:
en.wikipedia.org/wiki/Goertzel_algorithm#Power-spectrum_terms
и который вполне себе устойчивый и без накопления ошибок
Если посмотреть с дурой стороны, я бы назвал это не накоплением ошибок, а дискретизацией. На самом деле в самой волне, при генерации ее поворотом, ни каких ошибок и отклонений нету, есть только несоответствие заданной частоте и оно довольно мизерное, но не генерируемой.
Всё-таки Гёрцель.
Ссылаемся на Википепию? Хорошо…
В русскоязычной литературе нет устоявшегося варианта транскрипции фамилии автора алгоритма. Распространены варианты «Алгоритм Герцеля», «Алгоритм Гертцеля», «Алгоритм Горцеля» и другие.

Ваша же ссылка
Это отличный результат.
Тогда не понятно, почему автор вызывает внутри внешнего цикла:
for( int i=0; i<128; i++ )
    {
        const float wi = (float)i*(2.0f*3.1415927f/4096.0f);
        const float sii = sinf( wi );
        const float coi = cosf( wi );

ведь по сути там такой-же трюк подходит

Эта часть отрабатывает в 4096 раз реже, так что экономия будет уже не столь существенна.

Как бы, для кого — открытие, а для кого — серые будни, известные еще с 8-биток.
Добавить еще пару действий и получится резонансный фильтр 2го порядка, LP/HP/BP.
Имхо, 128х полосовыми фильтрами можно было бы менее ресурсоемко сделать подобие FFT, хватая по 1 сэмплу.
Быстрый FFT уже изобретен.
быстрый быстрый?
НЛО прилетело и опубликовало эту надпись здесь
иногда синусы и косинусы даже табличные либо не могут обеспечить видимую точность (и такое бывает), иногда оин не доступны в компиляторе, не работаю потому что их забыли реализовать (спасибо менеджерам спешившим продать новый новую железку), и просто желание программиста без конкретных явных причин, только какие-то лично-субъективные

Вот недавно на хабре была статья, как числа округлять. Сегодня: как применять школьную формулу тригонометрии. Это все сложно. Напишите пожалуйста, как извлекать квадратный корень числа с плавающей точкой в C++. Это будет очень актуально для хабра.

Корень тоже был, см. 0x5F3759DF

1/на корень, если что

Таких констант можно кучу напридумывать для любого показателя степени от -1 до 1, о чем в статье «Магическая константа» 0x5f3759df и говорится.

И ещё вот (что кстати на PC-платформе не имеет смысла, потому что там есть FPU с 80-битной точностью для промежуточных вычислений).
если числа меньше 1, что характерно для DSP, я бы почитал чего есть быстрого.
Посмотрите, как организован внутренний цикл, тот, что выполняется 4096 раз: ни одного вызова функций sin() или cos(), хотя в других реализациях эти вызовы будут.
В других реализациях этих вызовов тоже нет — там используются предварительно подсчитанные табличные данные. Более того — трюк с последовательным поворотом вектора для вычисления FFT хорошо известен и в частности используется в книге «Numerical Recipes» (страница 612 в третьем издании).
Продолжайте писать. Не все начинали тут с восьмибиток и реайлтайма.

Статья полезная. Тут рядом где-то статья была, как человек графики для Телеграма оптимизиировал — думаю, ему бы понравилось.
Если тригонометрические функции по какой-то причине так неприятны, то почему бы не перейти к показательным функциям с помощью формулы Эйлера?
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории