Я могу написать базовый генератор синусоидальной волны для аудио, но я хочу, чтобы он мог плавно переходить с одной частоты на другую. Если я просто перестану генерировать одну частоту и сразу переключусь на другую, сигнал будет прерывистым, и будет слышен «щелчок».
Мой вопрос заключается в том, что является хорошим алгоритмом для генерации волны, которая начинается, скажем, с 250 Гц, а затем переходит на 300 Гц, без каких-либо щелчков. Если алгоритм включает необязательное время скольжения / портаменто, то тем лучше.
Я могу подумать о нескольких возможных подходах, таких как передискретизация, за которой следует фильтр низких частот, или, возможно, использование волновой таблицы, но я уверен, что это достаточно распространенная проблема, поскольку существует стандартный способ ее решения.
Ответы:
Один из подходов, который я использовал в прошлом, заключается в поддержании фазового аккумулятора, который используется в качестве индекса в таблице поиска сигналов. Значение дельты фазы добавляется к аккумулятору на каждом интервале выборки:
Чтобы изменить частоту, вы изменяете дельту фазы, которая добавляется к фазовому аккумулятору в каждом образце, например
где:
Это гарантирует, что выходной сигнал будет непрерывным, даже если вы меняете phase_delta динамически, например, для изменений частоты, FM и т. Д.
Для более плавных изменений частоты (портаменто) вы можете изменять значение phase_delta между его старым значением и новым значением в течение подходящего числа интервалов выборки, а не просто мгновенно изменять его.
Обратите внимание , что
phase_index
и уphase_delta
обоих есть целое и дробное компонент, то есть они должны быть с плавающей точкой или фиксированной точкой. Целочисленная часть phase_index (размер таблицы по модулю) используется в качестве индекса в LUT формы сигнала, а дробная часть может дополнительно использоваться для интерполяции между соседними значениями LUT для вывода более высокого качества и / или меньшего размера LUT.источник
Один из лучших способов создать синусоидальную волну - использовать сложный вектор с рекурсивным обновлением. Т.е.
где z [n] - вектор, , где - угловая частота осциллятора в радианах, а - индекс выборки. И действительная, и мнимая части являются синусоидальными, они сдвинуты по фазе на 90 градусов. Очень удобно, если вам нужны как синус, так и косинус. Для расчета одной выборки требуется только 4 умножения и 4 сложения, и оно НАМНОГО дешевле, чем что-либо, содержащее sin () cos () или справочные таблицы. Потенциальная проблема заключается в том, что амплитуда может дрейфовать со временем из-за проблем с числовой точностью. Однако есть довольно простой способ исправить это. Допустим, что . Мы знаем, что должен иметь единичную величину, т.е.Ω=exp(jω) ω n z[n] z[n]=a+jb z[n]
Таким образом, мы можем проверять время от времени, если это все еще так и исправить соответственно. Точная коррекция будет
Это неуклюжий расчет, но так как очень близок к единице, вы можете аппроксимировать с помощью разложения Тейлора около и мы получаемa⋅a+b⋅b 1/x−−√ x=1
поэтому коррекция упрощается до
Применяя эту простую коррекцию каждые несколько сотен сэмплов, генератор будет стабильно работать вечно.
Для непрерывного изменения частоты множитель W необходимо соответствующим образом обновить. Даже непостоянное изменение множителя будет поддерживать функцию непрерывного генератора. Если требуется линейное изменение частоты, обновление может быть разбито на несколько шагов, или вы можете использовать тот же алгоритм осциллятора для обновления самого множителя (так как это также комплексный вектор с единичным усилением).
источник
С этого сайта :
Похоже, это должно работать.
(На самом деле, если они оба синхронизируются по оси X при переходе, я полагаю, что постепенный переход не требуется.)
источник
Я согласен с предыдущими предложениями по использованию фазового аккумулятора. По сути, управляющий вход представляет собой величину опережения фазы за шаг или за такт (или за прерывание или что-то еще), так что изменение этого значения изменяет частоту без разрыва фазы. Амплитуда волны затем определяется из накопленного значения фазы либо с помощью LUT, либо просто путем вычисления sin (тета) или cos (тета).
По сути, это то, что обычно известно как генератор с числовым управлением (NCO) или прямой цифровой синтезатор (DDS). Выполнение веб-поиска по этим терминам, вероятно, даст больше, чем вы хотите знать о теории и практике, чтобы заставить их работать хорошо.
Добавление дополнительного аккумулятора может позволить плавные переходы между частотами, как вы предложили, если это желательно, также путем контроля скорости изменения значения продвижения фазы. Это иногда называют цифровым дифференциальным анализатором или DDA.
источник
1-й порядок, вы должны отрегулировать начальную фазу новой синусоиды частоты так, чтобы она была такой же, как и фаза предыдущей синусоиды в точке 1-го перехода. Вычислите первую частоту и используйте ее фазу для второй частоты.
Второй вариант может заключаться в повышении d_phase от частоты одной частоты к другой в течение нескольких выборок. Это очистит непрерывность 1-й производной и обеспечит скольжение.
Третий вариант может заключаться в использовании сглаживающего окна, такого как рельефный косинус, для скорости линейного изменения d_phase.
источник