Pattr

Библиотека физического моделирования PMPD

В этой статье я хотел бы вас познакомить с библиотекой физического моделирования pmpd для Pure data. Хотя статья не претендует на развёрнутое описание физического моделирования, всё-таки хочется вкратце затронуть его историю и основные принципы. Цель статьи — дать представление о физическом моделировании и о том, какое отношение это имеет к нам, музыкантам, саунд-дизайнерам и вообще всем, кто заинтересован в необычных подходах к созданию звуковых фактур.

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

Поначалу тема может показаться непростой, но уверяю, что это не так. Вся «грязная шахтёрская работа» уже проделана и нам, обладателям библиотеки, стоит только складывать готовые кубики. Как в Lego. Заманчиво? А теперь приступим!

Немного истории

Физическое моделирование — штука не новая. Теория физического моделирования началась в конце 1950-х с так называемых графов связей (bond graphs). Это метод описания физических процессов (к примеру, формирование звука в корпусе флейты), который подразумевает выявление компонентов процесса и построение связей между ними. Графы связей — это развитие электроакустических и электромеханических аналогий, теории, которая проводит параллели между элементами, казалось бы, совершенно различных сфер. Допустим, напряжение — эквивалент силы, ток — скорости, индуктивность — массы, ёмкость — гибкости и т. д. Не вдаваясь в подробности обоих теорий, можно сказать, что они послужили основой для создания специализированных систем физического моделирования.

Cordis и Genesis

Институт ACROE в Гренобле разработал язык программирования Cordis-Anima, который использовался для физического моделирования звуковых (Cordis) и анимированных (Anima) объектов. Genesis является графическим интерфейсом для этого языка. Самая мелкая единица в мире Cordis — это «атом». «Атомы» делятся на 2 типа: matter и link.

Matter и link имеют двухканальную связь: по одному каналу передаётся сила (F), по другому смещение (X), таким образом, инструменты Cordis являются сетью, состоящей из matter, соединённых друг с другом объектами link.

Это основы языка Cordis, но зачем они нам, если у нас совершенно другая среда — pd? А дело в том, что основы библиотеки pmpd практически те же самые. Поэтому скорее заканчиваем с историей и переходим к делу!

PMPD

Маша моделями вселенной
Выходит физик из ворот...
— Д. Хармс «Физик, сломавший ногу»

Да, я не физик. Но временами хочется какой-то пластики, отдачи от программы. Настраивая огибающую ADSR в синтезаторе, мы стремимся к тому, чтобы появилась нужная нам пластика в динамике звучания, все знают, какое непростое это дело. Создавая музыкальные алгоритмы, мы часто обрекаем музыку на холодное и ритмичное звучание. Иногда это элемент стиля, но часто это лишает музыку свободы. Мы вставляем свою голову в качестве шестерёнки в этот холодный механизм, нам нравится, когда мы в нём. Нравится до какой-то поры. Когда механизм становится ясен — интерес теряется. Если механизм совершенно не ясен, интереса не возникнет. Здесь очень тонкий баланс — мы составляем формулу, которая легко понимается, но долго осознаётся. Физические законы нам близки с первых минут жизни, мы пробуем взаимодействовать с миром и со временем познаём его физические свойства, это то, что не вызывает никаких сомнений. Именно поэтому помещение законов физики в структуру инструмента, эффекта, а может быть, и всей композиции, может дать новые, необычные результаты, новое впечатление, новое вдохновение.

Сразу замечу, что в отличие от упомянутой Cordis pmpd не работает на звуковой частоте. То есть это не та среда, где мы можем создать синтетическую модель фортепиано или флейты, но это среда, где мы используем физическое моделирование для управления синтезом. Это более грубый механизм, но это делает его и более понятным.

Итак, из чего же состоит pmpd?

Mass

Объект «mass» (далее - масса) имитирует массу, сосредоточенную в точке. На входе он получает силу (force), на выходе выдаёт позицию (position). Движется согласно второму закону Ньютона: F=ma

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

Link

Объект «link» (далее - связь) принимает позиции двух связанных с ним масс и выдаёт на выход две противоположные силы, которые зависят от относительных позиций и скорости масс.

Связи — это вязко-упругие соединения двух масс.

Упругость описывается законом Гука: F=KX,
где k — упругость, а x — то, насколько растянулась связь (удобно представлять связь как резинку или пружинку, так вот x — это изменение её длины в нейтральном состоянии)

Вязкость описывается:

F=DV,
где D — это демпфирование связи и V — это относительная скорость обоих масс.

Сила, генерируемая вязко-эластичной связью является суммой этих двух сил:

F=KX+DV

Наглядное представление объекта link:

* слова масса связь и сила, написанные курсивом, означает само понятие массы, связи и силы в среде pmpd, к примеру масса означает точечный математический объект, который обладает значением массы, получает тактовые отсчёты, силу и выдаёт позицию. А если написано [mass], значит, что речь идёт о конкретном объекте. Допустим [mass] — это одномерный объект, [mass2D] — двухмерный и т. д.

Система измерения

Pmpd не не конкретизирует систему измерения, поэтому вы сами можете выбрать её для себя. Вы можете считать, что расстояния измеряются в метрах, таким образом единицы упругости будут равны силе, делённой на метр. Здесь всё относительно: масса с весом 10 реагирует на силу в 1 так же, как и масса весом 100 реагирует на силу в 10.

Метроном

Для произведения расчётов необходим единый генератор временных отсчётов, который должен быть послан на каждый объект pmpd, в качестве него выступает знакомый всем объект metro.

Имена

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

Ниже мы видим пример соединения двух связанных масс. Для начала заметим, как функционируют атрибуты объекта. [mass $0-mass 30] — это значит что объект [mass] имеет имя $0-mass и имеет массу 30. У [link] введено несколько больше атрибутов. [link $0-link 0 1 1] — (1) имя, (2) длина в нейтральном состоянии, (3) коэффициент упруости, (4) демпфирование. Запомнить порядок атрибутов для каждого объекта непросто, поэтому у всех объектов pmpd есть help (патч справки, вызывается правым кликом на объекте и далее самый нижний пункт контекстного меню), где можно узнать не только порядок атрибутов, но и сообщения, которые можно посылать на объект для динамического изменения параметров.

Теперь обратим внимание на соединение. [Mass] получает на вход силу, а на 1-й выход отправляет позицию (остальные 2 выхода пока нас не интересуют). [Link] наоборот, на вход получают позицию, а на выход отдают силу.

Поначалу немного вводит в ступор то, что [mass] и [link] образуют замкнутую структуру, но тут всё дело в том, как их мыслить. Нужно представлять их не как объекты, производящие вычисления, а как предметы реального мира. Я представляю, что [mass] и [link], повязанные друг на друга — это просто единая колбаса. Вы копируете их, вставляете, склеиваете, ещё никогда не было так просто управлять колбасой!

Теперь вернёмся к метроному. На скриншоте ниже мы видим, что объекты [s $0-mass] и [s $0-link] передают временные отсчёты сразу нескольким объектам [mass] и [link]. Для этого используется объект [send] (здесь сокращённое имя — [s], но по сути одно и то же). Для того, чтобы [mass] получал отсчёты даже не нужно создавать объект [receive], достаточно просто, чтобы имя [mass] было такое же, что стоит после [s]. Итак, как осуществляется связь. [metro 10] каждые 10 миллисекунд генерирует сообщение bang, которое поступает на триггер [t b b] и раздаётся на все связи с именем $0-link и на все массы с именем $0-mass.

А теперь для наглядности откройте в pure data (у вас должна стоять pd-extended): help → browser
появится браузер, мотайте ползунок вниз, пока не увидите меню pmpd, далее: pmpd → examples → 02_string.pd

Щёлкаем 2 раза и — вуаля, тот самый патч! Это отличный пример того, как работает библиотека и как её можно использовать для генерации звуков. Подвигайте один из крайних ползунков и вы увидите, как это скажется на ползунках в середине. Они качаются как качалась бы натянутая длинная резинка в невесомости. Да, эта несколько непривычная реакция верёвки вызвана тем, что в этом примере не задан параметр гравитации. Хорошо, а теперь попробуйте потрогать средние ползунки. Они вас не будут слушаться. Почему? Потому, как отмечали выше, каждые 10 миллисекунд на них приходят сообщения о позиции от соседних элементов, и ваши движения мышкой, конечно, учитываются, но лишь на сотую долю секунды.

Далее, нажмите cmd-e (или ctrl-e на PC), и подвигайте для наглядности элементы в окне, чтобы понять, как устроены связи. Обратите внимание, что первый и последний ползунок не имеют входов, именно поэтому они двигаются свободно. Остальные постоянно получают позицию от объектов [mass] (в данном случае «колбасой» является ручка ползунка), а [mass] в свою очередь связаны между собой объектами [link]. [Link] — это «верёвочка», на которой висят «колбаски». В этом случае мы получили отличную порцию охотничьих колбасок!

Кстати, справа вниу патча мы видим, что на [dac~] приходит небольшая цепочка синтеза, так что если включить обработку аудио, можно услышать, как наши «колбаски» звучат.

Pmpd и Gem

В списке pmpd → examples много примеров, каждый найдёт для себя то, что его интересует. Допустим, меня не очень интересовали 3D объекты, поэтому я их пропускал. Может, они мне вдруг понадобятся и я к ним вернусь. А пока откройте пример 09_tutorial2D.pd и мы приступим к визуализации нашей физики.

Gem — это библиотека pd, которая добавляет возможность визуализировать алгоритмы pd, она может работать как с простыми 2D и 3D объектами, так и с видеоматериалом, эффектами и т. п. Для тех, кто не знаком с Gem, советую пролистать пару патчей. Они находятся в меню help → browser → Gem → examples

В предыдущем примере мы визуализировали нашу физику простыми ползунками, теперь настало время двигать архитектуру!

В синем прямоугольнике уже знакомый нам тактовый генератор. Под ним, в красном прямоугольнике находится сообщения и объекты для вызова окна Gem. Нажмите на [reset, create, 1], появится новое чёрное окошко со белой фигурой, похожей на велосипедное колесо. Кружки — это массы, а линии — это связи. Хотя на самом деле эти объекты чисто математические, а эти кружки и линии всего-лишь визуальные объекты Gem, в этом патче они тесно связаны и работают как едино целое.

В блоке такового генератора запустите toggle и процесс пойдёт. Колесо опустится вниз и его начнёт «плющить». Тут наглядно иллюстрируется физика. Обратите внимание, что, в отличие от предыдущего примера, здесь действует сила притяжения. Как она реализована? А очень просто! Взгляните ещё раз на блок метронома, если проследить путь сигнала от [metro], через триггер [t b b] он приходит на новое сообщение [force2D 0 -0.1(. Это сообщение отправляется на tut_mass, и со скоростью тактового генератора передаёт силу. Атрибуты 0 и -0.1 означают силу по горизонтали и по вертикали соответственно, отрицательные значения силы по вертикали действуют по направлению вниз, т. о. мы получаем постоянно действующую силу, направленную вниз, что и является в данном случае гравитацией.

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

А теперь, кое-что интересное. Патч, как вы заметили, называется tutorial2d.pd и не случайно. Откройте субпатч [pd structure], в нём вы увидите большой круг из объектов, очень напоминающий наше «колесо». И здесь можно повеселиться! Для начала смело удалите какие-нибудь объекты и вернитесь к чёрному окошку Gem. Вы обнаружите, что в колесе тоже пропали некоторые составляющие. Теперь удалите всё в этом субпатче и создайте объект [tut_mass y x], где вместо y укажите позицию по вертикали и вместо x по горизонтали, позиция должна быть в пределах от -4 до 4, за центр принимается координата 0 0. Создайте ещё один [tut_mass y x], после чего сделайте объект [tut_link].

*link не требует указания позиции, т. к. его позиция всегда относительна и зависит от связанной с ним mass.

Затем соедините аутлет [tut_mass] с первым инлетом [tut_link], а первый аутлет [tut_link] с инлетом [tut_mass]. Теперь аналогично соедините второй [tut_mass] со вторыми инлетом и аутлетом [tut_link]. Вот и получилась ваша первая структура! Вы можете эксперементировать с различными связями, как они будут себя вести: попробуйте создать разомкнутую связь, замкнутую связь, квадрат, треугольник и что только в голову прийдёт.

Параметры упругости связи

Откройте пример 11.comportement.pd. Этот патч похож на предыдущий, но здесь слева есть переключатель, отправляющий сообщения на [s preset]. Запустите метроном, вызовите окно Gem и давайте посмотрим, как этот переключатель работает. По умолчанию включён первый пресет.

1) Если подать силу на объект и ударить им о стену, мы увидим, что он достаточно жёсткий и крепкий, как бы мы его ни били, он быстро восстанавливает свою форму. Здесь мы можем считать, что объект резиновый.

2) Переключите на второй пресет (2-й кубик vradio). Здесь его поведение сильно меняется. Тут это походит больше на желе, нечто дребезжащее. Массы (шары) долго держат инерцию, при сильных ударах о стены объект на момент сплющивается и превращается в линию.

3) В 3-м пресете поведение напоминает 1-й пресет, но объект гораздо сильнее пружинит и связующие линии долго колеблются.

4)В 4-м объект довольно упруг, но шары при ударе долго сохраняют инерцию, поэтому эта масса дребезжит, но она не такая «жидкая», как во 2-м пресете.

Что же происходит? Откройте субпатч [pd init] (внизу справа) и давайте разберёмся, что происходит здесь, ведь именно сюда приходят сообщения через [s preset]. Мы видим цепочки, крайняя левая нас не интересует, а вот остальные 3 как раз и изменяют поведение link. Внизу мы видим, что на [s link] отправляются 3 специализированных сообщения [setK $1(, [setD $1( и [setD2 $1(. Рассмотрим кажное в отдельности.

SetK устанавливает упругость (вспомните формулу F=KX, где K-коэффициент упругости). Он определяет, будет ли связь жёсткой или тянущейся.

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

SetD2 — это сообщение изменяет то, насколько быстро связь тормозит скорость масс. Фактически это параметр «неповоротливости» масс, потому что он ограничивает скорость, с которой способна двигаться масса. Низкие значение делают массы максимально «свободно болтающимся», высокие делают тяжким, неповоротливым, стремящимся во что бы то ни стало достигнуть точки равновесия и замереть.

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

А теперь вернёмся к пресетам и обратим внимание, как реализвана физика в каждом из них.

  • В 1-м пресете высокое значение упругости (K=25), приглушена вибрация связей (D=7) и низкий параметр торможения скорости (D2=1), поэтому прямоугольник шустро летает, отпрыгивая от стен и сохраняет форму.
  • Во 2-м упругость равна всего лишь 1, D=0.2 и D2=0.1, поэтому он такой «жидкий» и вибрирующий.
  • В 3-м пресете упругость аж 30, но оттого, что D2=0.1 он набирает большую скорость от приложенной силы, и поэтому массы так долго дребезжат после ударов, опять же, потому что скорость не демпфируется.
  • В 4-м низкие значения D и D2 (0.2 у обоих), поэтому объект сильно пружинит, инерция не затухает.

iAmbient 2D

Теперь разберёмся ещё с одним важным объектом — [iAmbient2D].

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

Откройте пример 15_constant_force_field.pd. В этом патче внизу слева находятся 2 объекта [iAmbient2D], которые получают bang от метронома. [iAmbient2D], как и другие объекты pmpd обязательно должны получать референсный тактовый сигнал, чтобы производить расчеты. Взглянем на атрибуты первого [iAmbient2D]. У него всего 3 атрибута — имя (0$-mass), 0 и -1. Эти два последних атрибута отвечают за силу, отправляемую объектом по горизонтали и по вертикали соответственно. По вертикали оправляется -1, значит на каждый счёт метронома все объекты с именем $0-mass получают силу -1 по вертикали, а мы знаем, что отрицательная сила по вертикали в pmpd направлена вниз.

Потрогаем конкретный пример. Запустите метроном, нажмите [reset, create, (, чтобы создать окно Gem, и понаблюдайте за мячом. Вот он упал, вот покатился в сторону красного квадрата, но почему-то закрутился. А внутри красного квадрата мяч ведёт себя как в воде, на него действует выталкивающая сила. Что же происходит и что это за красный квадрат?

Как наиграетесь с мячом, можете вызвать help объекта iAmbient2D и разобраться с его атрибутами. Я тоже это сделаю, почему бы не полазить в help-патчах, ведь они аналогичны у всех объектов pmpd!

Итак, цифры перед названием параметра — это номер атрибута. Они сортированы по возможности необходимости использования, что очень удобно. Разберёмся на нашем же примере. В первом объекте [iAmbient2D $0-mass 0 -1] нам понадобилась только сила по вертикали, поэтому остальные атрибуты мы не заполняли, а это значит, что они равны наиболее нейтральным значениям. Во втором объекте мы написали гораздо больше атрибутов [iAmbient2D $0-mass 0 3 0 0 0 -4 0 -4 -2]. С первыми тремя ясно, мы присвоили ему силу 3, направленную вверх. Дальше идут два нуля, это 4-й и 5-й аргумент, находим их в help-файле, читаем rnd X force field и rnd Y force field, что значит максимальную случайную силу.

В pmpd предусмотрена имитация движения молекул и вообще любых хаотичных процессов, поэтому если проставить здесь что-нибудь выше нуля, то на массу постоянно дополнительно будут действовать силы случайной величины и направления. У нас стоят нули потому, что эти параметры нас не интересуют, мы просто хотим их пропустить, чтобы добраться до других параметров. Далее 6-й аргумент и тоже 0, справка нам говорит, что это damping, то есть это силы, которые будут тормозить скорость объекта в данной среде (допустим, в воде этот атрибут был бы актуален, каждый знает по опыту, что в воде двигаться сложнее). А далее остаётся ещё 4 аргумента: -4 0 -4 -2. В справке мы видим, что это ограничение зоны влияние этого объекта. 7-й и 8-й аргументы — координаты начала и конца зоны по оси абцисс, 9-й и 10-й аргументы — начало и конец по оси ординат. В итоге получаем координаты красного прямоугольника.

Теперь, вроде бы, всё ясно, однако, почему же мяч крутится? А дело в том, что когда его левая сторона попадает в область с иными постоянными силами, то массы, которые в неё попали стремятся подняться вверх, в то время как массы в чёрной области находятся под обычной силой -1 по вертикали, которая слабее, чем сила 3 по вертикали. Если сложить векторы -1 и 3, получим силу 2, направленную вверх, именно такая сила действует на каждую массу, попавшую в красную область.

Заключение

Начиная с прошедшего века людям приходят всё более безумные и концептуальные идеи. Но мы знаем, что новое — это забытое старое, только чаще на новом уровне, а безумное часто оказывается чем-то ещё массово не осознанным. Pure data напоминает мне очень продвинутую «реинкарнацию» шарманки или музыкальной шкатулки, а разве то были не привлекательные вещи? Лично я давно подумывал о том, что здорово было бы внедрить в композицию законы физики, поэтому pmpd для меня большое открытие, надеюсь, что и для вас тоже.

Между идеями и возможностями имеется двусторонняя связь, любой новый инструмент рождает новые музыкальные идеи, а временами и целые жанры, поэтому полезно иметь в копилке десяток-другой возможностей, пусть даже ещё толком не осознанных.

Обзор мой далеко не полный, но я постарался осветить наиболее сложные моменты, а далее help и гугл вам в помощь. Удачного патчинга!

Литература

Miranda E.R. - Computer Sound Design. Synthesis techniques and programming (Music Technology Series) — 2002
Cyrille Henry — PMPD reference manual
Wikipedia

17 Feb 2013  strangy