- PVSM.RU - https://www.pvsm.ru -
При решении задач визуализации информации, очевидно, возникает вопрос о практической реализации задуманного. Данный цикл статей посвящен процессу проектирования приложений с помощью визуального программирования в Max 7 от компании Cycling '74. Начнем изучение вопроса, от простого к сложному. Пройдем путь от любительской заготовки до полноценного «однофайлового» приложения (standalone .exe).
Уровень: легкий
♞
[1]Наверняка кто-нибудь использует какую-либо программу и не догадывается, что она сделана с помощью Max. Такой программой, например, является DAW [2] 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] [3]
Данный способ программирования позволит читателю отойти от написания строк кода на языках типа C/C++, всё представляется в виде модулей и связями между ними. Процесс разработки становится более наглядным и быстрым, при этом программа выполняется в реальном времени, пока вы ее делаете, т.е. для любых изменений в структуре результат отображается сразу же, без компиляции. По сути, вы строите логическую блок-схему работы программы.
Для решения задач визуализации будем использовать визуальный язык программирования — Max (MSP). В основном, Max предназначен для создания интерактивных объектов искусства, но так же может быть применим при решении огромного пласта задач. Во многих областях можно найти что-то, что можно визуализировать красиво. Вспомните эти шпионские фильмы, в которых на компьютерах героев изображены различные красивые интерфейсы неведомых программ. Да и в реальности — например, визуализация информации, поступающей с датчиков. К тому же он позволяет вести разработку как на машинах с ОС Windows, так и на компьютерах с Mac OS.
Для описания процесса осуществления задуманного, введем следующие понятия:
В терминах телекоммуникаций модуль выступает в роли коммутатора, который в свою очередь выполняет заданные функции и отправляет результат в выходные порты.
Примечание. В данной статье я постараюсь не углубляться в очевидные вещи. Очень много дополнительной информации о работе объектов и модулей доступно в справке — правой кнопкой мыши по объетку, затем «Open имя_объекта help». Поэтому при описании элементов программы предпочтение будет отдаваться в основном их предназначению, а не синтаксису или структуре.
В основном мы будем пользоваться режимами: конструктора и презентации, а так же заглядывать в окна консоли (Max console), инспектора объектов (Inspector, CTRL+I) и инспектора патча (Inspector Window, CTRL+SHIFT+I).
Процесс создания программ сводится к построению блок-схемы из модулей и связей между ними. Можно использовать встроенные в Max модули, но интересней всего писать их самому. Это очень удобно как при вызове их изнутри программы, так и при использовании в процессе программирования в целом. В обычном программировании данная модель представлена в виде ООП, ну или можно представить один модуль как одну функцию, параметры которой — входы [inlets] модуля, а return — выход, причем выходов может быть много [outlets].
Примечание: Для добавления объекта в патч кликните 2 раза мышкой по пустому месту, либо нажмите клавишу N, вводите название, нажимаете Enter и дальше можно уже соединять его с другими.
Есть несколько способов добавления самописных модулей:
— инкапсуляция [p patchname],
— самостоятельный патч,
— [bpatcher].
Данное понятие аналогично понятию инкапсуляции в обычных языках программирования. В данном случае всё элементарно — выделяем объекты, которые хотим объединить в группу/модуль/файл и нажимаем CTRL+E (Edit — Encapsulation). При завершении инкапсуляции таким образом на выходе получаем модуль — [p patchname], где patchname — любая фраза на английском. Так же доступны и цифровые символы.
Объединяемые объекты после завершения данного процесса исчезают из окна патча Max. На самом деле Max внутри оригинально патча создает субпатч, куда и переносит все выделенные объекты и их связи. В зависимости от наличия внешних связей, инкапсулятор может автоматически вставить объекты входы [inlet] и выходы [outlet], а так же соединить их с внешними объектами. Это очень удобно, когда разрабатываешь программу не задумываясь о нагромождении объектов, ведь при достижении определенного количества, структура программы перестанет быть читаемой и вы сами в ней запутаетесь. Для решения проблем организации структуры программы и предназначена инкапсуляция в Max.
Особенности: это инструмент группировки/разграничения объектов по различным признакам. Данный способ создания модулей предполагает уникальность каждого модуля. Т.е. если вы создадите один модуль таким образом и продублируете его — это будут уже два разных модуля. Внесение изменений в один из них не повлечет за собой изменение остальных дубликатов.
Применение: уникальные группы объектов, простые или сложные вычисления, которые используются в программе только в одном месте.
Для создания модулей можно воспользоваться и другим способом. Достаточно создать новый файл, добавить и соединить нужные блоки, расположить объекты, отвечающие за принятие входа [inlet], и за отправку на выход — [outlet] и сохранить файл в любой папке (например создать отдельную папку «tools» и кидать туда патчи со своим префиксом). Далее уже в рабочем патче добавляем объект с именем [название_файла] (без разрешения файла .maxpat) и всё готово.
Данный способ можно использовать в комбинации с инкапсуляцией, описанной выше. Это даже еще удобнее. Можно инкапсулировать нужные объекты, открыть получившийся модуль (в заблокированном режиме два раза левой кнопкой мыши по блоку) и сохранить его как самостоятельный патч.
Особенности: удобная вещь для создания модулей по типу «черный ящик» — один раз написав модуль, мы уже не возвращаемся без надобности к его структуре и т.д. Мы видим только 3 вида информации: входы, название модуля и выходы. Важно, что при дублировании таких модулей, их содержание не становится уникальными, т.е. изменения в одном из дубликатов повлечет за собой изменения во всех них. Если точнее, то в таком случае редактируется не дубликаты модулей, а сам оригинальный файл модуля.
Применение: удобно применять этот способ при создании модулей для каких либо отдельных вычислений. Особенности позволяют многократно дублировать модули.
Наглядный пример — модуль перевода сообщения из десятичной системы исчисления в двоичную. Простой копипаст объектов абстракции переводчика внутри главного патча в этом случае будет признаком плохого тона, т.к. может оказаться, что модуль требует изменений. Легче изменить 1 файл, чем весь этот копипаст перебирать.
Если в предыдущих способах мы создавали «черные ящики», то бывают случаи, когда нужно отобразить какую-либо часть модуля в открытом виде без редактирования структуры. Это могут быть различные числовые визуализации, отображения служебных сообщений и т.д. Еще более интересным является процесс добавления презентационной части модуля.
Данный способ расширяет границы применения самостоятельных патчей. Для того, чтобы добавить модуль в рабочий патч, просто создаем объект [bpatcher], а в инспекторе его свойств указываем путь к файлу модуля.
Особенности: можем видеть структуру и связи модуля, а так же презентационную часть.
Применение: подходит для организации верхнего уровня структуры программы, т.е. по сути отображаем сгруппированные модули одним объектом, что очень удобно — избавляемся от лишних нагромождений проводов и вспомогательных объектов. Видим только те части, которые нужны.
Весь процесс написания программы будет сводится к многочисленным инкапсуляциям и добавлением субпатчей в рабочий патч. Это довольно логично и удобно, особенно при проектировании сложных программ, где может быть много модулей различных применений. По сути, мы просто закапываем «рабочие лошадки» программы по группам все глубже и глубже, а на выходе будем иметь элементарную структуру всего из нескольких объектов. Если потребуется внести изменения в какой-то из модулей, то мы просто откроем его файл и без проблем это сделаем.
Лично для меня данный способ проектирования программ является более наглядным. К тому же не нужно дублировать кучу символьного кода, а в некоторых случаях это очень утомляет.
Наглядные примеры модулей, созданных перечисленными способами, представлены в файле tut01_subpatches.maxpat
[5]Для создания сложных программ с большим количеством библиотек в Max 7 предусмотрена возможность создания проектов. Данная функция представлена в виде списка патчей и других файлов, использующихся в проекте. Справа в миниатюре показано содержание уже готового крупного проекта по визуализации цифровой обработки сигналов. Как можно наблюдать, в списке видим не только сами файлы патчей .maxpat, но и файлы других типов.
В дальнейшем можно будет использовать такой список «для себя», просто чтобы знать где что лежит и какие модули использованы в данном проекте. Хотя, компилировать программу можно хоть из главного патча, хоть из меню с проектом. Отличие в том, что при открытии проекта можно задать открываемый патч по-умолчанию — открываешь проект и вместе со списком файлов открывается и назначенный патч.
Начнем наш тернистый путь познания о программировании в среде Max 7 созданием нового проекта. File → New Project. Рекомендуется сохранять все проекты в отдельную папку, например — C:Max Projects… Расположение папки с проектами в корне диска крайне удобно, особенно когда меняешь версию программы или ОС.
После сохранения проекта откроется окно со списком патчей проекта, но пока он пуст. Добавим новый файл в проект:
+ → Add New File… Сохраняем файл в каталог, где лежит файл проекта, а дальше Max сам создаст там папку patchers, в которую на самом деле и сохраняется файл патча.
Начнем с чего-нибудь простого, например, счетчик с тактовым генератором. Счетчик будет прибавлять значение на единицу только тогда, когда на вход счетчика приходит bang-сообщение от тактового генератора (метроном).
Bang — это специальное сообщение, запускающее работу модуля/объекта. Завершение любой операции в модуле на выходе дает какое-то значение, при этом сам факт отправки данных из модуля на его выход сопровождается bang-сообщением. Bang используем когда нужно отправить какое-либо сообщение куда-либо. Он как бы «толкает» сообщение дальше по тракту от объекта к объекту.
Добавим в наш патч объекты и связи как на изображении справа.
Примечание. Max хорош еще и тем, что патчами можно спокойно обмениваться в текстовом формате. Происходит это следующим образом — вы выделяете все элементы и связи в патче нажатием клавиш CTRL+A, копируете CTRL+C, а затем открываете любой текстовый редактор или форму на сайте и вставляете текст из буфера. По сути, описание состояния программы (структуру, данные) представляется в виде JSON-текста, который вы только что скопировали. Чтение такой информации происходит не намного сложнее: в главном меню Max 7 Files → New From Clipboard… А вообще, не обязательно даже создавать новый файл, можно вставить скопированное прямо в уже открытый патч. Таким образом, Max считывает текст из буфера обмена и интерпретирует его в модули и связи между ними.
Попробуйте скопировать приведенный ниже код программы и вставить в Max.
{
"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].
Немаловажным умением при создании программ является умение избавляться от лишних деталей. Любознательный читатель заметил бы, что в вышепреведенном патче мы используем 3 тактовых генератора и 3 выключателя, хотя можно использовать всего по одному экземпляру. Забегая вперед скажу, что чем больше объектов типа [metro] вы будете добавлять, тем медленнее может стать обработка остальной информации программой. Чтобы получить программу с хорошим быстродействием, следует задумываться об этом еще на начальной стадии.
Избавимся от лишнего, удалим избыточные вычисления из программы:
Заменяем три тактовых генератора одним, входы счетчиков соединяем с выходом объекта [metro 500]. Так-то лучше. Вы можете сказать, что так надо было поступать с самого начала, но на практике координаты блоков генератора и других объектов могут сильно отличатся, не задумываясь добавляешь еще один метроном, а потом еще и еще. В итоге связи объектов превращаются в запутанную паутину, в которой довольно сложно ориентироваться. При правильном подходе данных проблем можно избежать множественными инкапсуляциями объектов в модули, группируя их по назначению. Этого мы и будем добиваться на протяжении всего цикла статей.
[print]
Если по каким-то причинам вы хотите выводить информацию в консоли, то для этого используется объект [print имя_строки]. Название объекта [print b] говорит нам о том, что при поступлении сообщения на вход [print], в консоли отобразится сообщение вида b: текст.
Элементарные операции
[+ 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 в папке патчей проекта. В дальнейшем, для осуществления операций кодирования/декодирования чисел мы будем пользоваться именно этими модулями.
С помощью объекта [vexpr] можно задавать различные логические операции.
tut_bitlogic.maxpat — в данном примере рассматриваются побитовые логические операции многоразрядных сообщений.
Здесь я перечислю модули, которые используются мной чаще всего. Некоторые писал сам с нуля, некоторые нашел на форуме тех.поддержки. Там можно найти решение почти любого вопроса, редко когда я чего-то не находил.
[toBit]
Данный модуль переводит переводит числа от 0 до 255 в восьмиразрядный битовый код.
[fromBit]
Принимает на вход восьмиразрядный битовый код, а на выходе выдает числа от 0 до 255.
[tut_dynamicInlets N]
Пример организации входов и выходов с заданным количеством N.
tut_lesson01.maxpat [6]
tut_bitlogic.maxpat [7]
tut_encapsulation.maxpat [8]
tut_dynamicInlets.maxpat [9]
toBit.maxpat [10]
fromBit.maxpat [11]
Все сразу (.zip) + каталог tutorial_all.maxpat [12]
Обзорная статья на хабре про Max MSP [13]
Cycling '74 [14] — сайт производителя/страница Max 7.
Max Objects Database [15] — хранилище разнообразных объектов. Зачем изобретать велосипед, когда он уже есть.
Cycling '74 — Projects [16] — проекты других разработчиков.
Cycling '74 — Forums [17] — форум, где можно найти решения для многих задач, достаточно лишь правильно спросить.
Pattr.ru [18] — здесь можно найти полезные плюшки и статьи для Max MSP.
maxmsp vk [19] — группа русскоязычных пользователей.
Список может изменится, примерный вариант:
♞
Автор: Валерий Зимнев
Автор: Javelines
Источник [20]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/87214
Ссылки в тексте:
[1] Image: http://createdigitalmusic.com/files/2012/10/Session-Automation-Recording-Curves.png
[2] DAW: http://ru.wikipedia.org/wiki/DAW
[3] [1]: https://ru.wikipedia.org/wiki/%D0%92%D0%B8%D0%B7%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5
[4] Image: https://habrastorage.org/files/55d/388/67f/55d38867f64d413a9b385b34cd055eb1.gif
[5] Image: http://habrastorage.org/files/cca/913/cf8/cca913cf873a426abaf0bcc9f986d16c.png
[6] tut_lesson01.maxpat: https://drive.google.com/file/d/0BxYCcOv1ZLchdDVzY2wtNmhRelk/view?usp=sharing
[7] tut_bitlogic.maxpat: https://drive.google.com/file/d/0BxYCcOv1ZLchWk8xMTZhUTUzT2M/view?usp=sharing
[8] tut_encapsulation.maxpat: https://drive.google.com/file/d/0BxYCcOv1ZLchVHExQXhSTmlScVk/view?usp=sharing
[9] tut_dynamicInlets.maxpat: https://drive.google.com/file/d/0BxYCcOv1ZLchcHQwLVJaVXhVTG8/view?usp=sharing
[10] toBit.maxpat: https://drive.google.com/file/d/0BxYCcOv1ZLchS3dxaG53dFVMajA/view?usp=sharing
[11] fromBit.maxpat: https://drive.google.com/file/d/0BxYCcOv1ZLchR21xejZLemFWaHc/view?usp=sharing
[12] Все сразу (.zip) + каталог tutorial_all.maxpat: https://drive.google.com/file/d/0BxYCcOv1ZLchNV9kV1pJMW5raDA/view?usp=sharing
[13] Обзорная статья на хабре про Max MSP: http://habrahabr.ru/post/127972/
[14] Cycling '74: http://cycling74.com/
[15] Max Objects Database: http://www.maxobjects.com/
[16] Cycling '74 — Projects: https://cycling74.com/community/?q=project
[17] Cycling '74 — Forums: https://cycling74.com/forums/
[18] Pattr.ru: http://pattr.ru/
[19] maxmsp vk: https://vk.com/maxmsp
[20] Источник: http://habrahabr.ru/post/253745/
Нажмите здесь для печати.