Аудио синтезатор с непрекъсната вълнова форма

Започвам да пиша мек синтезатор с особена характеристика: Осцилаторите ще имат копче за "непрекъсната форма на вълната", което ще позволи на потребителите да избират синусоидални, квадратни и зъбни вълни по непрекъснат начин. Тоест, ако копчето е докрай наляво, изходът ще бъде синусоида, ако е в средата, ще бъде вълна на трион, ако е докрай вдясно, ще бъде правоъгълна вълна и тогава междинните позиции ще изведат вълни, които са "интерполирани" версии на класическите вълни. -- Позициите на копчетата и типовете вълни могат да се променят, но е желателно да имате непрекъснат начин за промяна на формите на вълните --

Помислих за няколко начина за прилагане на осцилатора:

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

  2. Подобно на 1. но приложете обратно преобразуване на Фурие вместо синусите и сбора (ОК, на този етап не съм сигурен дали всъщност са едно и също нещо.)

  3. Генерирайте таблица с вълнови форми за всяка възможна позиция на копчето и използвайте техника за синтез на вълнова таблица, за да генерирате изходния сигнал.

  4. Започнете с 2 зъбни вълни (те съдържат както четни, така и нечетни хармоници), обърнете една и ги сумирайте и контролирайте амплитудата на всяка една от тях с копчето. Вълновите форми нямаше да бъдат

Имам няколко въпроса:

О. Чел съм, че техника номер 1 изисква много процесор и не е наистина осъществима. Това важи ли за ARM процесори като този на iPad??

Б. Каквато и техника да избера в крайна сметка, може ли проблемът с псевдонимите да бъде разрешен просто чрез свързване на нискочестотен филтър към изхода на осцилатора?

В. Всяко друго предложение за това как да се приложи такъв осцилатор?

Г. Някакви предложения кой C++ инструментариум да използвам? Гледах STK от CCRMA, но не знам дали има други по-подходящи библиотеки.

Пожелай ми късмет! ;)

Редактиране: Някой ме насочи към din снощи. Кривите на Безие са друга възможност за разглеждане.


person Rafael Vega    schedule 26.01.2012    source източник
comment
Искате ли да генерирате проби от формата на вълната или да я приложите към друг сигнал? Обмисляте ли конкретен подход за интерполация?   -  person Dmitry Shkuropatsky    schedule 27.01.2012
comment
Искам да използвам това като звукогенериращ осцилатор за синтезатор. След това ще приложа филтриране и може би някои ефекти, за да направя звуците по-интересни. Подходите, които разгледах, са описани в 1 до 4, не съм сигурен какво имате предвид под интерполационен подход.   -  person Rafael Vega    schedule 27.01.2012
comment
Уау!! Благодаря на всички за отговорите, сега имам малко домашно :) Първо ще започна лесно: използвайте квадратните, синусовите и зъбните осцилатори в STK и просто преминавайте между трите звука, за да видите как звучи. Ако все пак имам нужда от нещо по-сложно, ще проуча другите дадени предложения. --- Ще дам на този още малко време, преди да отбележа приет отговор ---   -  person Rafael Vega    schedule 27.01.2012


Отговори (4)


Не съм сигурен, че не усложнявате прекалено много. Ако разбирам правилно, всичко, което правите с вашето копче за непрекъсната вълнова форма, е ефективно смесване на различни количества от 3-те вълнови форми. Така че, просто генерирайте всичките 3 вълнови форми през цялото време, след което ги сумирайте заедно с различни печалби според комбинацията от вълнови форми, които сте описали.

За синтез на вълнова форма с ограничен диапазон, за да избегнете псевдонимите, вероятно ще намерите повечето от това, от което се нуждаете тук.

Надявам се това да помогне.

person Redeye    schedule 26.01.2012
comment
Това е, което в крайна сметка направих, обикновен кросфейдър свърши работа! :) - person Rafael Vega; 13.02.2012

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

За съжаление, отговорът е „не“. Псевдонимите се причиняват от наличието на хармонични честоти над честотата на Найкуист (т.е. половината от честотата на дискретизация). Ако тези хармоници присъстват във формата на вълната на вашия осцилатор, филтрирането не може да помогне. (Подходящо агресивно филтриране ще унищожи характера на вълните, които сте генерирали.) Свръхсемплирането (друг отговор споменава това) може, но е скъпо.

За да избегнете това, трябва да генерирате вълнови форми с „ограничена лента“. Тоест вълнови форми, които нямат хармоници над някаква избрана стойност ‹ Найкуист. Правенето на това е нетривиално. Тази статия тук си заслужава да бъде прочетена. Има два установени практически подхода за решаване на този проблем: BLITs (Band Limited Impulse Train) и MinBLEPs. И двата подхода се опитват да изгладят генериращите хармоници прекъсвания чрез вмъкване на „неща“ в подходящи точки във формата на вълната.

Имайки това предвид, вашите възможности започват да се свиват. Вероятно най-добрият компромис между лекота и звук би бил генерирането на серия от вълнови таблици с ограничен диапазон. Все пак ще трябва да проучите някаква форма на антиалиасинг, за да се справите с интерполираните вълни.

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

STK е страхотна интро библиотека. (Книгата на Пери Кук „Аудио синтез в реално време за интерактивни приложения“ също е добра основа и си заслужава да бъде прочетена.) STK обаче нарочно не е оптимизиран и не съм сигурен колко добре би се поддал на генерирането на вашите „непрекъснати“ вълнови форми . kvraudio.com и musicdsp.org трябва да е в списъка ви за четене.

person Tim    schedule 26.01.2012
comment
просто исках да добавя, че с решение 1. нискочестотен филтър преди синтеза всъщност би работил добре, защото знаете честотите на всички осцилатори, преди да ги пробвате, така че можете просто да пропуснете хармониците, чиято честота е по-висока от тази на Найкуист честота. - person Thies Heidecke; 27.01.2012

Преобразуването на Фурие е линейно, така че като вземем FFT на напр. квадратни и трионни вълни и линейно кръстосване на всеки хармоник и след това връщане обратно във времевия домейн, или чрез iFFT, или чрез сумиране на синусите, трябва да даде точно същия изход като простото кръстосване на трион и квадратни сигнали директно. Не съм сигурен дали това е, което искахте да направите, но ако е, няма нужда да правите FFT или да изчислявате междинни таблици.

Разбира се, има много други начини за плавно „избледняване“ между вълновите форми – можете да използвате фазово изкривяване, например, с крива на изкривяване, състояща се от линейни сегменти, които премествате от позиции, които генерират квадрат, до позиции, които генерират трион. Това вероятно е много трудно да се приложи по начин, който по своята същност е ограничен в честотната лента.

Псевдонимите на практика често могат да бъдат решени чрез свръхсемплиране и филтриране или просто филтриране. Използването на техники с ограничена лента е по-добро, тъй като псевдонимът винаги ще причини известен шум, но често можете да го филтрирате достатъчно ниско, за да бъде нечуваем, което е важното за аудио синтеза.

person user450018    schedule 26.01.2012

О. Чел съм, че техника номер 1 изисква много процесор и не е наистина осъществима. Това важи ли за ARM процесори като този на iPad?

Това прави един прост проблем сложен (игра на думи). Accelerate.framework предоставя оптимизирани варианти на тези функции (fwiw), но все още усложнява прост проблем. Като обща бележка: изчисленията с плаваща запетая на устройствата са бавни. Внедряването с плаваща запетая може да компрометира значително вашата програма. Това вероятно ще доведе до значително компрометиране на характеристиките, полифонията или качеството. Без да знаете изискванията, е трудно да се каже дали бихте могли да минете с изчисления с плаваща запетая.

Б. Каквато и техника да избера в крайна сметка, може ли проблемът с псевдонимите да бъде разрешен просто чрез свързване на нискочестотен филтър към изхода на осцилатора?

Това няма да работи за сигнали, генерирани във времевия домейн, освен ако не превишите семплирането.

В. Всяко друго предложение за това как да се приложи такъв осцилатор?

виж отдолу

Г. Някакви предложения кой C++ инструментариум да използвам? Гледах STK от CCRMA, но не знам дали има други по-подходящи библиотеки.

STK е по-скоро инструмент за обучение, отколкото инструментариум, предназначен за вградени синтезатори. Съществуват по-подходящи реализации.

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

Вариант 2. Подобен на 1. но приложете обратно преобразуване на Фурие вместо синусите и сбора (ОК, на този етап не съм сигурен дали всъщност са едно и също нещо.)

Това е относително бавно на настолни компютри.

Вариант 4. Започнете с 2 зъбни вълни (те съдържат както четни, така и нечетни хармоници), обърнете едната и ги сумирайте и контролирайте амплитудата на всяка една от тях с копчето. Вълновите форми нямаше да бъдат

Можете да направите това доста ефективно (напр. с BLIT) за генериране без псевдоним. Въпреки това, BLIT е ограничен до шепа вълнови форми (можете да го използвате за Saw и Square). Можете да погледнете назад в историята и да попитате Как са решили този проблем в хардуерните и софтуерните синтезатори, прибл. 2000. Това беше едно от решенията. Друг беше:

Опция 3. Генериране на таблица с вълнови форми за всяка възможна позиция на копчето и използване на техника за синтез на вълнова таблица за генериране на изходния сигнал.

Имайки предвид възможностите на устройството, бих препоръчал int реализация на това или BLIT.

Масата е лесна за обработка и внедряване и осигурява добър звук и резултати на процесора. Освен това е много конфигурируем за компромиси CPU/Memory/Quality.

Ако искате свободен псевдоним (или близък), изберете 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 dB, ако не звуково овлажняване на най-високите части и сте изобразили на 44,1kHz. Това е наивен подход на груба сила! Можете да се справите по-добре с малко допълнителна работа.

И накрая, трябва също да намерите подходяща информация, ако потърсите в Google Vector Synthesis -- това, което описвате, е негова примитивна форма.

person justin    schedule 27.01.2012
comment
+1 Това е много илюстративен отговор, научих много от него. - person Rafael Vega; 13.02.2012