Pull to refresh

Создание полноценных приложений на Max 7. Часть 1 — Постановка задачи, визуальное программирование

Programming *Data visualization *Visual programming *
Tutorial
При решении задач визуализации информации, очевидно, возникает вопрос о практической реализации задуманного. Данный цикл статей посвящен процессу проектирования приложений с помощью визуального программирования в Max 7 от компании Cycling '74. Начнем изучение вопроса, от простого к сложному. Пройдем путь от любительской заготовки до полноценного «однофайлового» приложения (standalone .exe).

Уровень: легкий



Конечный результат


Наверняка кто-нибудь использует какую-либо программу и не догадывается, что она сделана с помощью Max. Такой программой, например, является DAW Ableton Live. Догадаться можно по интерфейсу объектов, а так же из-за Max for Live. Конечно, в таких серьезных проектах используется не только Max, но и дополнительные библиотеки, файлы, скрипты и т.д. Так же и некоторые современные программы на iPad для работы со звуком. В данном цикле статей мы попытаемся разобраться в процессе проектирования подобных сложных приложений, начиная с самых простых примеров.

Оглавление


1. Визуальное программирование
→ 1.1. Понятия
2. Интерфейс Max 7
3. Принцип построения программ в Max
→ 3.1. Модульные объекты со входами и выходами
→ 3.2. Инкапсуляция [p patchname]
→ 3.3. Самостоятельный патч
→ 3.4. [bpatcher]
4. Структура программы
→ 4.1. Проектное пространство
→ 4.2. Первые шаги
→ 4.3. Bang, Metro, Counter, Number
→ 4.4. Избавляемся от лишнего
→ 4.5. Другие объекты
→ 4.6. Логические операторы, регулярные выражения
→ 4.7. Логические выражения
5. Полезные модули
Прилагаемые файлы
Полезные ссылки


§ 1. Визуальное программирование


Визуальное программирование — способ создания программы для ЭВМ путём манипулирования графическими объектами вместо написания её текста. [1]


Данный способ программирования позволит читателю отойти от написания строк кода на языках типа C/C++, всё представляется в виде модулей и связями между ними. Процесс разработки становится более наглядным и быстрым, при этом программа выполняется в реальном времени, пока вы ее делаете, т.е. для любых изменений в структуре результат отображается сразу же, без компиляции. По сути, вы строите логическую блок-схему работы программы.

Для решения задач визуализации будем использовать визуальный язык программирования — Max (MSP). В основном, Max предназначен для создания интерактивных объектов искусства, но так же может быть применим при решении огромного пласта задач. Во многих областях можно найти что-то, что можно визуализировать красиво. Вспомните эти шпионские фильмы, в которых на компьютерах героев изображены различные красивые интерфейсы неведомых программ. Да и в реальности — например, визуализация информации, поступающей с датчиков. К тому же он позволяет вести разработку как на машинах с ОС Windows, так и на компьютерах с Mac OS.

§ 1.1. Понятия


Для описания процесса осуществления задуманного, введем следующие понятия:

  • Объект — элемент программы, выполняющий какие либо операции, либо отображающие информацию. Может иметь или не иметь входные и выходные значения.
  • Модуль — группа объектов, объединенных в субпатч с целью выполнения заданной работы.
  • Патч, субпатч — в Max 7 исходные файлы проектируемой программы сохраняются в формате .maxpatch, .maxhelp или .json и называются патчами. Субпатч в свою очередь — это дочерний элемент патча, может хранится как в отдельном файле, так и внутри патча.
  • Инлет [inlet] — объект, создающий коммутацию модулей друг с другом. Является входным параметром модуля.
  • Аутлет [outlet] — объект, создающий коммутацию модулей друг с другом. Является выходным значением модуля.
  • Вход модуля — место соединения внешних объектов с модулем, входные параметры.
  • Выход модуля — место соединения внешних объектов с модулем, посылает на выход результат работы модуля.


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

§ 2. Интерфейс Max 7


Примечание. В данной статье я постараюсь не углубляться в очевидные вещи. Очень много дополнительной информации о работе объектов и модулей доступно в справке — правой кнопкой мыши по объетку, затем «Open имя_объекта help». Поэтому при описании элементов программы предпочтение будет отдаваться в основном их предназначению, а не синтаксису или структуре.

В основном мы будем пользоваться режимами: конструктора и презентации, а так же заглядывать в окна консоли (Max console), инспектора объектов (Inspector, CTRL+I) и инспектора патча (Inspector Window, CTRL+SHIFT+I).



  1. Главное меню программы
  2. [inlet]-объекты. Входы модуля.
  3. Компоненты (объекты) модуля, исполняемая часть.
  4. [outlet]-объекты. Выходы модуля.
  5. Inspector. Параметры выделенного объекта.
  6. Заблокировать/разблокировать редактирование патча.
  7. Переключатель между режимами конструктора и презентации.
  8. Вкл/выкл сетку.
  9. Область программы.


§ 3. Принцип построения программ в Max


§ 3.1. Модульные объекты со входами и выходами


Процесс создания программ сводится к построению блок-схемы из модулей и связей между ними. Можно использовать встроенные в Max модули, но интересней всего писать их самому. Это очень удобно как при вызове их изнутри программы, так и при использовании в процессе программирования в целом. В обычном программировании данная модель представлена в виде ООП, ну или можно представить один модуль как одну функцию, параметры которой — входы [inlets] модуля, а return — выход, причем выходов может быть много [outlets].

Примечание: Для добавления объекта в патч кликните 2 раза мышкой по пустому месту, либо нажмите клавишу N, вводите название, нажимаете Enter и дальше можно уже соединять его с другими.

Есть несколько способов добавления самописных модулей:

— инкапсуляция [p patchname],
— самостоятельный патч,
— [bpatcher].

§ 3.2. Инкапсуляция [p patchname]


Данное понятие аналогично понятию инкапсуляции в обычных языках программирования. В данном случае всё элементарно — выделяем объекты, которые хотим объединить в группу/модуль/файл и нажимаем CTRL+E (Edit — Encapsulation). При завершении инкапсуляции таким образом на выходе получаем модуль — [p patchname], где patchname — любая фраза на английском. Так же доступны и цифровые символы.

Объединяемые объекты после завершения данного процесса исчезают из окна патча Max. На самом деле Max внутри оригинально патча создает субпатч, куда и переносит все выделенные объекты и их связи. В зависимости от наличия внешних связей, инкапсулятор может автоматически вставить объекты входы [inlet] и выходы [outlet], а так же соединить их с внешними объектами. Это очень удобно, когда разрабатываешь программу не задумываясь о нагромождении объектов, ведь при достижении определенного количества, структура программы перестанет быть читаемой и вы сами в ней запутаетесь. Для решения проблем организации структуры программы и предназначена инкапсуляция в Max.

Особенности: это инструмент группировки/разграничения объектов по различным признакам. Данный способ создания модулей предполагает уникальность каждого модуля. Т.е. если вы создадите один модуль таким образом и продублируете его — это будут уже два разных модуля. Внесение изменений в один из них не повлечет за собой изменение остальных дубликатов.

Применение: уникальные группы объектов, простые или сложные вычисления, которые используются в программе только в одном месте.

§ 3.3. Самостоятельный патч


Для создания модулей можно воспользоваться и другим способом. Достаточно создать новый файл, добавить и соединить нужные блоки, расположить объекты, отвечающие за принятие входа [inlet], и за отправку на выход — [outlet] и сохранить файл в любой папке (например создать отдельную папку «tools» и кидать туда патчи со своим префиксом). Далее уже в рабочем патче добавляем объект с именем [название_файла] (без разрешения файла .maxpat) и всё готово.

Данный способ можно использовать в комбинации с инкапсуляцией, описанной выше. Это даже еще удобнее. Можно инкапсулировать нужные объекты, открыть получившийся модуль (в заблокированном режиме два раза левой кнопкой мыши по блоку) и сохранить его как самостоятельный патч.

Особенности: удобная вещь для создания модулей по типу «черный ящик» — один раз написав модуль, мы уже не возвращаемся без надобности к его структуре и т.д. Мы видим только 3 вида информации: входы, название модуля и выходы. Важно, что при дублировании таких модулей, их содержание не становится уникальными, т.е. изменения в одном из дубликатов повлечет за собой изменения во всех них. Если точнее, то в таком случае редактируется не дубликаты модулей, а сам оригинальный файл модуля.

Применение: удобно применять этот способ при создании модулей для каких либо отдельных вычислений. Особенности позволяют многократно дублировать модули.

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

§ 3.4. [bpatcher]


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

Данный способ расширяет границы применения самостоятельных патчей. Для того, чтобы добавить модуль в рабочий патч, просто создаем объект [bpatcher], а в инспекторе его свойств указываем путь к файлу модуля.

Особенности: можем видеть структуру и связи модуля, а так же презентационную часть.

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

§ 4. Структура программы


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

Лично для меня данный способ проектирования программ является более наглядным. К тому же не нужно дублировать кучу символьного кода, а в некоторых случаях это очень утомляет.

Наглядные примеры модулей, созданных перечисленными способами, представлены в файле tut01_subpatches.maxpat

§ 4.1. Проектное пространство


Для создания сложных программ с большим количеством библиотек в Max 7 предусмотрена возможность создания проектов. Данная функция представлена в виде списка патчей и других файлов, использующихся в проекте. Справа в миниатюре показано содержание уже готового крупного проекта по визуализации цифровой обработки сигналов. Как можно наблюдать, в списке видим не только сами файлы патчей .maxpat, но и файлы других типов.

В дальнейшем можно будет использовать такой список «для себя», просто чтобы знать где что лежит и какие модули использованы в данном проекте. Хотя, компилировать программу можно хоть из главного патча, хоть из меню с проектом. Отличие в том, что при открытии проекта можно задать открываемый патч по-умолчанию — открываешь проект и вместе со списком файлов открывается и назначенный патч.

§ 4.2. Первые шаги


Начнем наш тернистый путь познания о программировании в среде Max 7 созданием нового проекта. File → New Project. Рекомендуется сохранять все проекты в отдельную папку, например — C:\Max Projects\… Расположение папки с проектами в корне диска крайне удобно, особенно когда меняешь версию программы или ОС.

После сохранения проекта откроется окно со списком патчей проекта, но пока он пуст. Добавим новый файл в проект:
+ → Add New File… Сохраняем файл в каталог, где лежит файл проекта, а дальше Max сам создаст там папку patchers, в которую на самом деле и сохраняется файл патча.

§ 4.3. Bang, Metro, Counter, Number


Начнем с чего-нибудь простого, например, счетчик с тактовым генератором. Счетчик будет прибавлять значение на единицу только тогда, когда на вход счетчика приходит bang-сообщение от тактового генератора (метроном).

Bang — это специальное сообщение, запускающее работу модуля/объекта. Завершение любой операции в модуле на выходе дает какое-то значение, при этом сам факт отправки данных из модуля на его выход сопровождается bang-сообщением. Bang используем когда нужно отправить какое-либо сообщение куда-либо. Он как бы «толкает» сообщение дальше по тракту от объекта к объекту.

Добавим в наш патч объекты и связи как на изображении справа.

Примечание. Max хорош еще и тем, что патчами можно спокойно обмениваться в текстовом формате. Происходит это следующим образом — вы выделяете все элементы и связи в патче нажатием клавиш CTRL+A, копируете CTRL+C, а затем открываете любой текстовый редактор или форму на сайте и вставляете текст из буфера. По сути, описание состояния программы (структуру, данные) представляется в виде JSON-текста, который вы только что скопировали. Чтение такой информации происходит не намного сложнее: в главном меню Max 7 Files → New From Clipboard… А вообще, не обязательно даже создавать новый файл, можно вставить скопированное прямо в уже открытый патч. Таким образом, Max считывает текст из буфера обмена и интерпретирует его в модули и связи между ними.

Попробуйте скопировать приведенный ниже код программы и вставить в Max.
Код модуля tut_lesson01
{
	"patcher" : 	{
		"fileversion" : 1,
		"appversion" : 		{
			"major" : 7,
			"minor" : 0,
			"revision" : 2,
			"architecture" : "x64",
			"modernui" : 1
		}
,
		"rect" : [ 458.0, 167.0, 574.0, 390.0 ],
		"bglocked" : 0,
		"openinpresentation" : 0,
		"default_fontsize" : 12.0,
		"default_fontface" : 0,
		"default_fontname" : "Arial",
		"gridonopen" : 1,
		"gridsize" : [ 15.0, 15.0 ],
		"gridsnaponopen" : 1,
		"objectsnaponopen" : 1,
		"statusbarvisible" : 2,
		"toolbarvisible" : 1,
		"lefttoolbarpinned" : 0,
		"toptoolbarpinned" : 0,
		"righttoolbarpinned" : 0,
		"bottomtoolbarpinned" : 0,
		"toolbars_unpinned_last_save" : 0,
		"tallnewobj" : 0,
		"boxanimatetime" : 200,
		"enablehscroll" : 1,
		"enablevscroll" : 1,
		"devicewidth" : 0.0,
		"description" : "",
		"digest" : "",
		"tags" : "",
		"style" : "",
		"subpatcher_template" : "",
		"boxes" : [ 			{
				"box" : 				{
					"id" : "obj-21",
					"maxclass" : "comment",
					"numinlets" : 1,
					"numoutlets" : 0,
					"patching_rect" : [ 265.0, 165.0, 30.0, 20.0 ],
					"style" : "",
					"text" : "в)"
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-20",
					"maxclass" : "comment",
					"numinlets" : 1,
					"numoutlets" : 0,
					"patching_rect" : [ 145.0, 165.0, 30.0, 20.0 ],
					"style" : "",
					"text" : "б)"
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-19",
					"maxclass" : "comment",
					"numinlets" : 1,
					"numoutlets" : 0,
					"patching_rect" : [ 25.0, 165.0, 30.0, 20.0 ],
					"style" : "",
					"text" : "a)"
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-13",
					"maxclass" : "number",
					"numinlets" : 1,
					"numoutlets" : 2,
					"outlettype" : [ "", "bang" ],
					"parameter_enable" : 0,
					"patching_rect" : [ 255.0, 135.0, 50.0, 22.0 ],
					"style" : ""
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-14",
					"maxclass" : "newobj",
					"numinlets" : 5,
					"numoutlets" : 4,
					"outlettype" : [ "int", "", "", "int" ],
					"patching_rect" : [ 255.0, 90.0, 81.0, 22.0 ],
					"style" : "",
					"text" : "counter 2 0 3"
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-15",
					"maxclass" : "number",
					"numinlets" : 1,
					"numoutlets" : 2,
					"outlettype" : [ "", "bang" ],
					"parameter_enable" : 0,
					"patching_rect" : [ 300.0, 15.0, 50.0, 22.0 ],
					"style" : ""
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-16",
					"maxclass" : "newobj",
					"numinlets" : 2,
					"numoutlets" : 1,
					"outlettype" : [ "bang" ],
					"patching_rect" : [ 255.0, 60.0, 65.0, 22.0 ],
					"style" : "",
					"text" : "metro 500"
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-17",
					"maxclass" : "toggle",
					"numinlets" : 1,
					"numoutlets" : 1,
					"outlettype" : [ "int" ],
					"parameter_enable" : 0,
					"patching_rect" : [ 255.0, 15.0, 24.0, 24.0 ],
					"style" : ""
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-8",
					"maxclass" : "number",
					"numinlets" : 1,
					"numoutlets" : 2,
					"outlettype" : [ "", "bang" ],
					"parameter_enable" : 0,
					"patching_rect" : [ 135.0, 135.0, 50.0, 22.0 ],
					"style" : ""
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-9",
					"maxclass" : "newobj",
					"numinlets" : 5,
					"numoutlets" : 4,
					"outlettype" : [ "int", "", "", "int" ],
					"patching_rect" : [ 135.0, 90.0, 81.0, 22.0 ],
					"style" : "",
					"text" : "counter 1 0 3"
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-10",
					"maxclass" : "number",
					"numinlets" : 1,
					"numoutlets" : 2,
					"outlettype" : [ "", "bang" ],
					"parameter_enable" : 0,
					"patching_rect" : [ 180.0, 15.0, 50.0, 22.0 ],
					"style" : ""
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-11",
					"maxclass" : "newobj",
					"numinlets" : 2,
					"numoutlets" : 1,
					"outlettype" : [ "bang" ],
					"patching_rect" : [ 135.0, 60.0, 65.0, 22.0 ],
					"style" : "",
					"text" : "metro 500"
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-12",
					"maxclass" : "toggle",
					"numinlets" : 1,
					"numoutlets" : 1,
					"outlettype" : [ "int" ],
					"parameter_enable" : 0,
					"patching_rect" : [ 135.0, 15.0, 24.0, 24.0 ],
					"style" : ""
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-7",
					"maxclass" : "number",
					"numinlets" : 1,
					"numoutlets" : 2,
					"outlettype" : [ "", "bang" ],
					"parameter_enable" : 0,
					"patching_rect" : [ 15.0, 135.0, 50.0, 22.0 ],
					"style" : ""
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-6",
					"maxclass" : "newobj",
					"numinlets" : 5,
					"numoutlets" : 4,
					"outlettype" : [ "int", "", "", "int" ],
					"patching_rect" : [ 15.0, 90.0, 71.0, 22.0 ],
					"style" : "",
					"text" : "counter 0 3"
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-5",
					"maxclass" : "number",
					"numinlets" : 1,
					"numoutlets" : 2,
					"outlettype" : [ "", "bang" ],
					"parameter_enable" : 0,
					"patching_rect" : [ 60.0, 15.0, 50.0, 22.0 ],
					"style" : ""
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-4",
					"maxclass" : "newobj",
					"numinlets" : 2,
					"numoutlets" : 1,
					"outlettype" : [ "bang" ],
					"patching_rect" : [ 15.0, 60.0, 65.0, 22.0 ],
					"style" : "",
					"text" : "metro 500"
				}

			}
, 			{
				"box" : 				{
					"id" : "obj-3",
					"maxclass" : "toggle",
					"numinlets" : 1,
					"numoutlets" : 1,
					"outlettype" : [ "int" ],
					"parameter_enable" : 0,
					"patching_rect" : [ 15.0, 15.0, 24.0, 24.0 ],
					"style" : ""
				}

			}
 ],
		"lines" : [ 			{
				"patchline" : 				{
					"destination" : [ "obj-11", 1 ],
					"disabled" : 0,
					"hidden" : 0,
					"midpoints" : [ 189.5, 58.0 ],
					"source" : [ "obj-10", 0 ]
				}

			}
, 			{
				"patchline" : 				{
					"destination" : [ "obj-9", 0 ],
					"disabled" : 0,
					"hidden" : 0,
					"source" : [ "obj-11", 0 ]
				}

			}
, 			{
				"patchline" : 				{
					"destination" : [ "obj-11", 0 ],
					"disabled" : 0,
					"hidden" : 0,
					"source" : [ "obj-12", 0 ]
				}

			}
, 			{
				"patchline" : 				{
					"destination" : [ "obj-13", 0 ],
					"disabled" : 0,
					"hidden" : 0,
					"midpoints" : [ 264.5, 134.0 ],
					"source" : [ "obj-14", 0 ]
				}

			}
, 			{
				"patchline" : 				{
					"destination" : [ "obj-16", 1 ],
					"disabled" : 0,
					"hidden" : 0,
					"midpoints" : [ 309.5, 58.0 ],
					"source" : [ "obj-15", 0 ]
				}

			}
, 			{
				"patchline" : 				{
					"destination" : [ "obj-14", 0 ],
					"disabled" : 0,
					"hidden" : 0,
					"source" : [ "obj-16", 0 ]
				}

			}
, 			{
				"patchline" : 				{
					"destination" : [ "obj-16", 0 ],
					"disabled" : 0,
					"hidden" : 0,
					"source" : [ "obj-17", 0 ]
				}

			}
, 			{
				"patchline" : 				{
					"destination" : [ "obj-4", 0 ],
					"disabled" : 0,
					"hidden" : 0,
					"source" : [ "obj-3", 0 ]
				}

			}
, 			{
				"patchline" : 				{
					"destination" : [ "obj-6", 0 ],
					"disabled" : 0,
					"hidden" : 0,
					"source" : [ "obj-4", 0 ]
				}

			}
, 			{
				"patchline" : 				{
					"destination" : [ "obj-4", 1 ],
					"disabled" : 0,
					"hidden" : 0,
					"midpoints" : [ 69.5, 58.0 ],
					"source" : [ "obj-5", 0 ]
				}

			}
, 			{
				"patchline" : 				{
					"destination" : [ "obj-7", 0 ],
					"disabled" : 0,
					"hidden" : 0,
					"midpoints" : [ 24.5, 134.0 ],
					"source" : [ "obj-6", 0 ]
				}

			}
, 			{
				"patchline" : 				{
					"destination" : [ "obj-8", 0 ],
					"disabled" : 0,
					"hidden" : 0,
					"midpoints" : [ 144.5, 134.0 ],
					"source" : [ "obj-9", 0 ]
				}

			}
 ],
		"dependency_cache" : [  ],
		"embedsnapshot" : 0
	}

}



Разберем всё по порядку. Основными объектами в данном патче являются:
3 тактовых генератора ([toggle] + [metro]) и 3 счетчика [counter].

[toggle]
Переключатель. Имеет два режима работы: кнопка (Button) и переключатель (Toggle). При нажатии на [toggle], объект посылает на выход значение своего состояния [0, 1]. При нажатии на «кнопку», он посылает на выход короткую единицу. Переключатель отличается тем, что запоминает свое предыдущее состояние. Нажал один раз, на выходе 0, еще раз — 1, еще раз — 0 и т.д.

[metro 500]
Данный объект представляет из себя метроном, отправляющий на свой выход каждые N-миллисекунд bang-сообщение. В данном случае bang будет генерироваться каждые 500 мс.

[counter направление мин.значение макс.значение]
Счетчик, прибавляющий свое значение на одну единицу при каждом поступающем на вход bang-сообщении. По направлению отсчета счетчики разделяются на восходящий (а), нисходящий (б) и туда-обратно (в).

Таким образом, название объекта [counter 1 0 3] говорит нам о нисходящем счетчике с границами от 0 до 3. При достижении максимального значения счетчик сбрасывается и отсчет начинается с мин. значения. У объекта есть два инлета, позволяющие сбросить счетчик. Один из них сбрасывает значение мгновенно, а другой — сбросить, начиная со следующего отсчета.

[number]
Объект ввода данных, позволяющих хранить введенную информацию. Используется только для целых чисел, для чисел с плавающей точкой есть объект [flonum].

§ 4.4. Избавляемся от лишнего


Немаловажным умением при создании программ является умение избавляться от лишних деталей. Любознательный читатель заметил бы, что в вышепреведенном патче мы используем 3 тактовых генератора и 3 выключателя, хотя можно использовать всего по одному экземпляру. Забегая вперед скажу, что чем больше объектов типа [metro] вы будете добавлять, тем медленнее может стать обработка остальной информации программой. Чтобы получить программу с хорошим быстродействием, следует задумываться об этом еще на начальной стадии.

Избавимся от лишнего, удалим избыточные вычисления из программы:

Заменяем три тактовых генератора одним, входы счетчиков соединяем с выходом объекта [metro 500]. Так-то лучше. Вы можете сказать, что так надо было поступать с самого начала, но на практике координаты блоков генератора и других объектов могут сильно отличатся, не задумываясь добавляешь еще один метроном, а потом еще и еще. В итоге связи объектов превращаются в запутанную паутину, в которой довольно сложно ориентироваться. При правильном подходе данных проблем можно избежать множественными инкапсуляциями объектов в модули, группируя их по назначению. Этого мы и будем добиваться на протяжении всего цикла статей.

§ 4.5. Другие объекты


[print]
Если по каким-то причинам вы хотите выводить информацию в консоли, то для этого используется объект [print имя_строки]. Название объекта [print b] говорит нам о том, что при поступлении сообщения на вход [print], в консоли отобразится сообщение вида b: текст.

§ 4.6. Логические операторы, регулярные выражения


Элементарные операции

[+ i/f] — сложение двух значений входных параметров объекта с возвратом результата в аутлет.
Прим.: [+ 1], [+ 1.06]. i -int — целые числа, f — float — числа с плавающей точкой.

[* i/f] — умножение
[/ i/f] — деление

[+~ 1.] — сложение двух сигналов
[*~ 1.] — умножение двух сигналов

[if условие then 1 else 0] — при выполнении условия послать на выход единицу, в ином случае — ноль.
[if условие then 1 else out2 0] — при выполнении условия послать на первый выход единицу, в ином случае — во второй выход послать ноль.

[regexp] — работа с регулярными выражениями
[expr $i1 + $i2*$i3] — выполнить выражение между значениями, поступающими на вход модуль.

Остальные операции доступны в документации, всё аналогично обычному программированию.

Сохраняем приведенный код как два разных файла с именами tobit.maxpat и frombit.maxpat в папке патчей проекта. В дальнейшем, для осуществления операций кодирования/декодирования чисел мы будем пользоваться именно этими модулями.

§ 4.7. Логические выражения


С помощью объекта [vexpr] можно задавать различные логические операции.

tut_bitlogic.maxpat — в данном примере рассматриваются побитовые логические операции многоразрядных сообщений.

§ 5. Полезные модули


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

[toBit]
Данный модуль переводит переводит числа от 0 до 255 в восьмиразрядный битовый код.

[fromBit]
Принимает на вход восьмиразрядный битовый код, а на выходе выдает числа от 0 до 255.

[tut_dynamicInlets N]
Пример организации входов и выходов с заданным количеством N.

Прилагаемые файлы


image tut_lesson01.maxpat
image tut_bitlogic.maxpat
image tut_encapsulation.maxpat
image tut_dynamicInlets.maxpat

image toBit.maxpat
image fromBit.maxpat

image Все сразу (.zip) + каталог tutorial_all.maxpat

Полезные ссылки


Обзорная статья на хабре про Max MSP

Cycling '74 — сайт производителя/страница Max 7.
Max Objects Database — хранилище разнообразных объектов. Зачем изобретать велосипед, когда он уже есть.
Cycling '74 — Projects — проекты других разработчиков.
Cycling '74 — Forums — форум, где можно найти решения для многих задач, достаточно лишь правильно спросить.
Pattr.ru — здесь можно найти полезные плюшки и статьи для Max MSP.
maxmsp vk — группа русскоязычных пользователей.

В следующем номере


Список может изменится, примерный вариант:
  • § Формы и способы ввода информации
  • § Графики, GUI
  • § Открытие HTML-страниц
  • § Создание внешних ссылок
  • § Пути. PATH=?
  • § Вызов внешнего модуля (окна) с помощью кнопки



Автор: Валерий Зимнев
Tags:
Hubs:
Total votes 19: ↑14 and ↓5 +9
Views 27K
Comments Comments 9