Интерполяция таблицы синусов

Я хочу собрать систему SDR, которая сначала настраивает AM, позже FM и т. Д. Система, которую я планирую использовать для этого, будет иметь поисковую таблицу синусоиды для прямого цифрового синтеза (DDS). Я ожидаю, что для правильной настройки мне понадобится возможность точно контролировать частоту синусоидальной волны, подаваемой на микшер (в данном случае множитель). Я ожидаю, что линейная интерполяция будет близкой, но думаю, что нелинейный метод даст лучшие результаты.

Какой хороший и быстрый метод интерполяции использовать для таблиц синусов. Умножение и сложение обходятся недорого в целевой системе; разделение стоит дорого.

Изменить: я планирую реализовать константы с функциями умножения / сдвига для нормализации констант до масштабированных целых чисел. Промежуточные значения будут использовать широкие сложения, а умножения будут использовать 18 или 17 бит. «Предварительное вычисление» с плавающей запятой можно использовать, но не на целевой платформе. Когда я говорю «деление дорого», я имею в виду, что оно должно быть реализовано с использованием множителей и большого количества кода. Это немыслимо, но этого следует избегать. Однако настоящие методы IEEE с плавающей запятой потребуют значительного количества ресурсов на этой платформе, а также специальной реализации.

Любой опыт SDR был бы полезен.


person NoMoreZealots    schedule 22.07.2009    source источник
comment
Вы оценили линейную интерполяцию? Быстрая программа на ПК, запускающая ожидаемые входные данные, должна дать вам величину ошибки любого предлагаемого решения.   -  person Mark Ransom    schedule 25.07.2009
comment
Я не делал DDS, но сделал FM и синтез фазовых искажений. Я только что прочитал немного о DDS. Звучит так, как будто часто используется линейная интерполяция, но я думаю, что вы могли бы немного снизить уровень шума с помощью чего-то лучше, чем линейное. Когда вы начинаете реализацию, вы должны выполнить БПФ на выходе и пропустить известные волны через вход, чтобы увидеть, каков ваш минимальный уровень шума и есть ли какие-либо артефакты.   -  person Nosredna    schedule 25.07.2009


Ответы (6)


Если вы не получите очень хороших результатов с линейной интерполяцией, вы можете попробовать тригонометрические отношения.

Формулы суммы и разности

sin(A+B)=sinA*cosB + cosA*sinB
sin(A-B)=sinA*cosB - cosA*sinB
cos(A+B)=cosA*cosB - sinA*sinB
cos(A-B)=cosA*cosB + sinA*sinB

и вы можете предварительно рассчитать значения sin и cos для диапазонов A, B, т. е.

A range: 0, 10, 20, ... 90
B range: 0.01 ... 0.99
person Nick Dandoulakis    schedule 22.07.2009
comment
Звучит как неплохая идея. Я должен об этом подумать. Я планирую использовать платформу FPGA и кодировать ее на VHDL, поэтому мне нравится тот факт, что это может работать с использованием только умножителей и полных сумматоров. Мне нужно будет написать тестовый код, чтобы увидеть, приведет ли он меня туда, где я хочу быть. - person NoMoreZealots; 23.07.2009
comment
Либо диапазон A должен быть с шагом 1 градус, либо диапазон B должен быть расширен до 9,99 - либо вам придется повторить операцию много раз, чтобы добраться до синуса (27,5). - person Jonathan Leffler; 25.07.2009
comment
@ Джонатан Леффлер, я думаю, ты прав, но я понял. С 18-битными множителями это доходит до того, что пересечение нуля требует 5 записей таблицы, чтобы перейти от 1 до -1, что является самой крутой частью кривой, с 2 таблицами 1k (фактически дает 20-битное разрешение при поиске, что быстро использование CLB в качестве мини-ПЗУ.). Для математических методов потребуется больше множителей и сумматоров, и они не приблизят меня к моему диапазону разрешения для увеличения сложности. - person NoMoreZealots; 05.08.2009

таблица интерполяции для гладких функций = ick hurl bleah. ИМХО, я бы использовал интерполяцию таблицы только для какой-то действительно странной функции или там, где вам абсолютно необходимо было избежать разрывов (обратите внимание, что производные для интерполированных таблиц, тем не менее, прерывистые). К тому времени, когда вы закончите поиск в таблице и необходимый код интерполяции, вы, возможно, уже оценили один или два полинома, по крайней мере, если умножение не вызывает у вас изжоги.

IMHO вам гораздо лучше использовать приближение Чебышева для каждого сегмента (например, от -90 до +90 градусов или от -45 до +45 градусов, а затем другие сегменты той же ширины) синусоидального сигнала и выбор полинома минимальной степени, который уменьшает вашу ошибку до желаемого значения. Если сегмент достаточно мал, вы можете обойтись квадратичным или даже линейным многочленом; существует компромисс между точностью, количеством сегментов и степенью полинома.

См. мое сообщение в этом другом вопросе, это сэкономит вам проблема с расчетом коэффициентов (по крайней мере, если верить моей математике).

(редактировать: в случае, если это не было ясно, вы выполняете приближение Чебышева во время разработки на своем любимом мощном ПК, чтобы во время выполнения вы могли использовать микроконтроллер с грязным мешком или FPGA или что-то еще с простым полиномом степени 1–4. Не переходите к четвертой степени, если не знаете, что делаете, лучше 3 или ниже.)

person Jason S    schedule 23.07.2009
comment
На самом деле я до сих пор не совсем понимаю, где находится точка останова Precomputed PC / Embedded System с этим алгоритмом. Похоже, что это будет стоить 6 множителей. Придется сравнить Ника. D отвечает на это для 18-битных умножителей. Я буду использовать FP для бедняков, масштабированные константы с аппаратным битовым сдвигом. - person NoMoreZealots; 23.07.2009

Почему стол? Эта очень быстрая функция имеет наихудший пик шума при -90 дБ, когда сигнал при -20 дБ. Это безумно хорошо.

Для передискретизации звука я всегда использую один из интерполяторов из статьи о слонах. Это обсуждалось в предыдущий вопрос SO.

Если у вас процессор, у которого нет fp, вы все равно можете делать эти вещи, но они сложнее. Я был здесь. Я чувствую твою боль. Удачи! Раньше я делал преобразование fp в целое для развлечения, но теперь вам придется заплатить мне за это. :-)


Интересные онлайн-ссылки, которые относятся к вашей проблеме:

http://www.audiomulch.com/~rossb/code/sinusoids/

http://www.dattalo.com/technical/theory/sinewave.html


Изменить: дополнительные мысли на основе ваших комментариев

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

Предположим, вы разбили квадрант на 90 частей (на самом деле вы, вероятно, использовали бы 256 частей, но оставим 90 для удобства и ясности). Закодируйте их как 16 бит. На данный момент это 180 байт таблицы.

Теперь для каждой из этих степеней у нас будет 9 (на самом деле, вероятно, 8 или 16) промежуточных баллов.

В качестве примера возьмем диапазон от 3 до 4 градусов.

sin(3)=0.052335956 //this will be in your table as a 16-bit number
sin(4)=0.069756474 //this will be in your table as a 16-bit number

Итак, мы собираемся взглянуть на грех (3.1)

sin(3.1)=0.054978813 //we're going to be tricky and store the result
                     // in 8 bits as a percentage of the distance between
                     // sin(3) and sin(4)

Что вам нужно сделать, так это выяснить, как грех (3.1) находится между грехом (3) и грехом (4). Если это на полпути между ними, закодируйте это как байт 128. Если это четверть пути, закодируйте это как 64.

Это дополнительные 90 байт, и вы закодировали до десятых долей градуса в 16-битном разрешении всего за 180 + 90 * 9 байт. Вы можете расширять по мере необходимости (возможно, до 32-битных углов и 16-битных углов анимации) и очень быстро линейно интерполировать между ними. Чтобы свести к минимуму место для хранения, вы пользуетесь тем фактом, что последовательные значения близки друг к другу.


Редактировать 2: лучший способ кодировать промежуточные углы в таблице

Я только что вспомнил, что, сделав это, я очень компактно выразил разницу между ожидаемым значением в соответствии с линейной интерполяцией и фактическим значением. Эта ошибка всегда в одном направлении.

Сначала я вычислил максимальную ошибку в диапазоне, а затем основал на ней шкалу.

Сработало отлично. Я чувствую, что должен написать код в записи блога, чтобы проиллюстрировать это. :-)

person Community    schedule 24.07.2009
comment
@Nosredna: Я думаю, вам чего-то не хватает: эти дополнительные 90 байт не одинаковы для каждой из 90 частей; вам нужно будет добавить для вашей схемы 90 байт x 90 штук = 8100 байт. - person Jason S; 25.07.2009
comment
(вы можете использовать формулы суммы / разности углов в соответствии с предложением Ника Д.) - person Jason S; 25.07.2009
comment
Да! Я облажался. Исправление. - person Nosredna; 25.07.2009

Интерполяция в таблице синусов - это эффективная передискретизация. Очевидно, что вы можете получить отличные результаты с помощью одного вызова sin, поэтому каким бы ни было ваше решение, оно должно превзойти его. Для повторной выборки с фиксированным фильтром у вас по-прежнему будет только фиксированный набор доступных точек (повышающий дискретизатор 3: 1 означает, что у вас будет две новые точки, доступные между каждой точкой в ​​вашей таблице). Насколько дорого стоит память в целевой системе? Моя основная рекомендация - просто улучшить разрешение таблицы и использовать линейную интерполяцию. Вы получите те же результаты, что и меньшая таблица, и простой апсемплинг, но с меньшими вычислительными затратами.

person Sam Harwell    schedule 22.07.2009
comment
К сожалению, я не буду вызывать функцию sin. Я могу написать программу C на моем ПК, чтобы сгенерировать для меня таблицу синусов, но не C lib на цели. Память не из дешевых, я могу обменять Logic на быструю память, но это ограниченный системный ресурс. Я должен уметь конвейерно обрабатывать математику, пока она не станет слишком сумасшедшей. - person NoMoreZealots; 23.07.2009

Рассматривали ли вы использование серии Тейлора для триггерных функций (см. здесь)? Это включает в себя умножение и деление, но в зависимости от того, как представлены ваши числа, вы можете превратить деление в умножение (или битовый сдвиг, если вам очень повезет). Вы можете вычислить столько членов ряда, сколько вам нужно, и таким образом получить свою точность.

В качестве альтернативы, если эта синусоида будет аналоговым сигналом в какой-то момент, вы можете просто использовать подход таблицы поиска и использовать аналоговый фильтр для удаления частоты дискретизации из результирующей формы волны. Если ваша частота дискретизации в 100 раз превышает синусоидальную частоту, ее будет легко удалить. Для этого вам понадобится переменный фильтр. Я никогда не делал ничего подобного, но знаю, что есть цифровые потенциометры, которые принимают двоичное число и изменяют свое сопротивление. Это может быть основой переменного RC-фильтра - возможно, с некоторыми операционными усилителями для усиления и т. Д.

Удачи!

person Stephen Friederichs    schedule 24.07.2009
comment
ИМО, Тейлор добирается слишком медленно. И фильтрация меняет фазу. - person Nosredna; 24.07.2009
comment
Разделение немыслимо, я сам подумал об этом, НО это ОЧЕНЬ дорого на этой платформе и должно быть зарезервировано для приложений, которые не могут сделать по-другому. - person NoMoreZealots; 25.07.2009
comment
Ряды Тейлора не используют деление ... и в большинстве случаев от них следует отказаться в пользу приближения Чебышева, поскольку они гарантируют сходимость и ошибку, которая преднамеренно равномерно распределена. - person Jason S; 25.07.2009

Люди написали удивительно умный код для быстрого вычисления sin () в системах с крошечным объемом памяти, в которых даже нет инструкции аппаратного умножения, не говоря уже о инструкции деления.

В порядке возрастания сложности:

  • Используйте прямоугольную волну. Многие AM-радиостанции используют прямоугольные волны в своем кольцевом демодуляторе, и я не понимаю, почему ваш AM демодулятор требует чего-то более сложного.

  • Приближайте sin (), ища «ближайшее значение» в необработанной таблице из 256 значений за четверть цикла. Да, вы видите ужасно выглядящие ступеньки, но (с небольшой аналоговой фильтрацией) это часто работает хорошо. (На самом деле, это часто перебор, и достаточно более короткого стола).

  • Приближайте sin (), просматривая 2 ближайших значения в необработанной таблице и выполняя линейную интерполяцию между ними.

  • Приближенный sin () с 16 короткими кубическими сплайнами с одинаковым интервалом в x за четверть цикла «дает точность лучше, чем 16-битную» для sin (x).

Wikibooks: Fixed-Point Numbers ссылается на некоторые умные реализации последних трех .

person David Cary    schedule 01.05.2013