Аудио синтезатор с непрерывной формой волны - PullRequest
7 голосов
/ 27 января 2012

Я начинаю писать мягкий синтезатор со своеобразной характеристикой: у осцилляторов будет ручка «непрерывной формы волны», которая позволит пользователям непрерывно выбирать синусоидальные, квадратные и зубчатые волны.То есть, если ручка находится полностью влево, выходной сигнал будет синусоидальным, если он посередине, это будет зубчатая волна, а если он направо, то это будет прямоугольная волна.и затем промежуточные позиции будут выводить волны, которые являются «интерполированными» версиями классических волн.- Положение ручки и типы волн можно изменить, но желательно иметь непрерывный способ изменения форм волн -

Я подумал о нескольких способах реализации генератора:

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

  2. Аналогично 1. но применяем обратное преобразование Фурье вместо синусов и сумм (хорошо, на данный момент я не уверен, что они на самом деле одно и то же).

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

  4. Начните с двух волн зубьев пилы(они содержат как четные, так и нечетные гармоники), инвертируют одну и суммируют их, а также управляют амплитудой каждой из них с помощью ручки.Форма волны не будет

У меня есть несколько вопросов:

A.Я читал, что методика № 1 очень ресурсоемкая и неосуществима.Это справедливо для процессоров ARM, таких как тот, что на iPad?

B.Какой бы метод я ни выбрал, можно ли решить проблему сглаживания, просто подключив фильтр нижних частот к выходу генератора?

C.Любое другое предложение о том, как реализовать такой генератор?

D.Какие-либо предложения по использованию инструментария C ++?Я искал STK из CCRMA, но я не знаю, есть ли другие более подходящие библиотеки.

Пожелайте мне удачи!;)

Редактировать: Кто-то указал мне на din прошлой ночью.Кривые Безье являются еще одним вариантом для рассмотрения.

Ответы [ 4 ]

5 голосов
/ 27 января 2012

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

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

Надеюсь, это поможет.

2 голосов
/ 27 января 2012

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

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

Чтобы избежать этого, вы должны генерировать сигналы с ограниченной полосой частот. То есть сигналы, которые не имеют гармоник выше некоторого выбранного значения <Найквиста. Делать это нетривиально. Эта статья <a href="https://ccrma.stanford.edu/~stilti/papers/blit.pdf" rel="nofollow"> здесь стоит прочитать. Существует два устоявшихся практических подхода к решению этой проблемы: BLIT (Band Limited Impulse Train) и MinBLEP. Оба подхода пытаются сгладить разрывы, порождающие гармоники, вставляя «вещи» в соответствующие точки сигнала.

Имея это в виду, ваши возможности начинают уменьшаться. Вероятно, лучшим компромиссом между легкостью и звуком было бы создание серии ограниченных по диапазону волновых таблиц. Тем не менее, вам все равно придется исследовать какую-то форму сглаживания для обработки интерполированных волн.

iDevice ARM вполне способен выполнять DSP в режиме реального времени. Общий совет: пишите жесткий код, используйте встроенные функции и избегайте деления. Ваш цикл рендеринга будет вызываться 44 100 раз в секунду, поэтому, если ваш код завершится в течение 1/44100 с (0,023 мс), у вас не возникнет проблем. На практике вы должны иметь возможность запускать несколько генераторов одновременно без каких-либо проблем. Об этом свидетельствуют все эти музыкальные приложения в магазине приложений.

STK - отличная вступительная библиотека. (Книга Перри Кука «Синтез звука в реальном времени для интерактивных приложений» также является хорошим основанием и заслуживает прочтения.) Хотя STK специально не оптимизирован, и я не уверен, насколько хорошо он поддается генерированию ваших «непрерывных» сигналов , kvraudio.com и musicdsp.org должны быть в вашем списке чтения.

1 голос
/ 27 января 2012

A. Я читал, что методика № 1 очень ресурсоемкая и неосуществима. Это справедливо для процессоров ARM, таких как тот, что на iPad?

Это делает простую задачу сложной (каламбур). Accelerate.framework предоставляет оптимизированные варианты этих функций (fwiw), но все еще усложняет простую проблему. Как общее примечание: вычисления с плавающей точкой на устройствах являются медленными. Реализация с плавающей запятой может значительно снизить стоимость вашей программы. Скорее всего, это приведет к существенному ухудшению характеристик, полифонии или качества. Не зная требований, трудно сказать, можно ли обойтись с помощью вычислений с плавающей запятой.

B. Какой бы метод я ни выбрал, можно ли решить проблему сглаживания, просто подключив фильтр нижних частот к выходу генератора?

Это не сработает для сигналов, генерируемых во временной области, если вы не произвели чрезмерную выборку.

C. Любое другое предложение о том, как реализовать такой генератор?

см. Ниже

D. Какие-либо предложения по использованию инструментария C ++? Я искал STK из CCRMA, но я не знаю, есть ли другие более подходящие библиотеки.

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

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

Вариант 2. Аналогичен 1. но применяет обратное преобразование Фурье вместо синусов и сумм (хорошо, на данный момент я не уверен, действительно ли они одно и то же).

Это относительно медленно на настольных компьютерах.

Вариант 4. Начните с двух волн зубьев пилы (они содержат как четные, так и нечетные гармоники), инвертируйте одну и суммируйте их, а также управляйте амплитудой каждой из них с помощью ручки. Форма волны не будет

Вы можете сделать это достаточно эффективно (например, с помощью BLIT) для генерации без псевдонимов. Тем не менее, BLIT ограничен несколькими сигналами (вы можете использовать его для Saw и Square). Вы можете оглянуться назад на историю и спросить «Как они решили эту проблему в аппаратных и программных синтезаторах около 2000 года». Это было одно решение. Еще было:

Вариант 3. Сгенерируйте таблицу формы волны для каждого возможного положения ручки и используйте метод синтеза таблицы колебаний для генерации выходного сигнала.

Учитывая возможности устройства, я бы рекомендовал реализацию int или BLIT.

За столом легко работать и работать, и он обеспечивает хороший звук и производительность процессора. Он также легко настраивается для компромиссов ЦП / Память / Качество.

Если вы хотите, чтобы псевдоним был свободен (или близок), выберите BLIT (или его родственник). Причина в том, что вам понадобится хороший кусок памяти и достаточное количество избыточной дискретизации для минимального или отсутствия звукового алиасинга с помощью волновых таблиц.

Реализация:

В сети существует множество реализаций BLIT (и семейных).

Вот салфетка-каракули для столов:

enum { WF_Sine, WF_Saw, WF_Square, WF_COUNT };
enum { TableSize = SomePowerOfTwo };

struct sc_waveform {
    uint32_t at[TableSize];
};

enum { NPitches = Something };

sc_waveform oscs[WF_COUNT][NPitches];

После инициализации используйте аддитивный синтез для заполнения oscs.

Во время воспроизведения используйте:

  • интерполяция и передискретизация для чтения из таблиц
  • или достаточное количество передискретизации сигнала и затем понижающей дискретизации (что эффективно для ЦП).

Для справки: я бы оценил линейную интерполяцию таблицы, которая потребляла безответственный объем памяти (учитывая доступный объем) без передискретизации, должна поддерживать частоты псевдонимов на уровне или ниже -40 дБ, если вы были не чтобы слышать самые высокие частоты, и вы рендерились на частоте 44,1 кГц. Это наивный подход грубой силы! Вы можете сделать лучше с небольшой дополнительной работой.

Наконец, вы также должны найти соответствующую информацию, если вы используете Google "Vector Synthesis" - то, что вы описываете, является его примитивной формой.

1 голос
/ 27 января 2012

Преобразование Фурье является линейным, поэтому, принимая БПФ, например, Квадратные и пильные волны и линейное перекрестное затухание каждой гармоники, а затем возвращение ее во временную область, либо посредством iFFT, либо путем суммирования синусов, должны давать точно такой же выходной сигнал, что и прямое перекрестное затухание пильных и квадратных сигналов. Я не уверен, что это именно то, что вы хотели сделать, но если это так, нет необходимости делать FFT или вычислять промежуточные таблицы.

Существует много других способов плавного «затухания» между сигналами, конечно, вы можете использовать фазовое искажение, например, с кривой искажения, состоящей из линейных сегментов, которые вы перемещаете из позиций, которые генерируют квадрат, в позиции, которые генерируют пилу. , Это, вероятно, очень сложно реализовать способом, который по своей природе ограничен по полосе.

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

...