Как стать автором
Обновить
4
0.3

Пользователь

Отправить сообщение

Вполне себе годный вариант для текстового ввода простеньких мелодий. Но не уверен, что хорошо подойдёт для профессиональных. Просто сложные музыкальные произведения, вводимые с помощью классической нотной грамоты крайне сложны в наборе - это хорошо знают классические композиторы, например, вводящие ноты в Finale (насколько я знаю - вводить классическим путём ноты в других, более привычных современным композиторам, редактора ещё куда сложнее). Оттого и стал так популярен Piano roll - но если нужны именно классические ноты - то он не особо годится (всё равно будет много правок - тут тогда уж проще на MIDI клавиатуре наиграть и потом долго корпеть в Finale - исправляя огрехи и расставляя правильную музыкальную "пунктуацию").

Но классические ноты редко нужны современным композиторам - если надо - они сбагрят это работу музыкальным "неграм" - пусть тем в Finale корячатся... Современным "не классически " композиторам вполне хватает Piano roll (в разных вариациях + drum machine) и мультидороженный семплер + Kontakt для подключения современных программ инструментов + DSP плагины для эффектов и некоторый доп. софт для создания/обработки семплов (но этим скорее уже саунд продюсеры руководят, без них композиторы обычно берут готовые библиотеки и программы Kontakt и иногда специальные плагины для эмуляции старых синтезаторов).

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

Я правильно понял, что у Вас аккорды через { } объединение реализованы? Тогда как решаете такую игру - когда, скажем, зажимается одна клавиша (или несколько), и в это время играются другие? При этом ещё и зажатая клавиша так же может плавно варьироваться с другой клавишей! А ещё может быть начатый аккорд - переходящий в другой аккорд, и в процессе которого берутся оба аккорда с промежуточными легато, работой педалью и т.п. В современной музыке столько интересных и сложных техник... классикам и не снилось - хотя и они тоже порой сочиняли сложные произведения!

И это мы ещё сейчас мыслим скорее в терминах клавишных инструментов а-ля класс "фортепьяно". А у музыкальных инструментов других классов (видов) куча своих особенностей построения звукосочетаний.

Поэтому я и проектирую разные гибкие форматы ввода - чтобы подстроиться под технику разных инструментов. Я тут неспец по мультиинструменталке - но вот, хотя бы про гитары, или в общем случае - про класс "щипковые струнные" инструменты - там доступно столько хитрых техник исполнения (XX век был веком расцвета струнных инструментов и техник игры на них; впрочем клавишные в лице синтезаторов не шибко отставали по вариации звучания - но там техник не так много новых появилось), которые не доступны для исполнения на клавишных инструментах. И Piano roll тут вообще бессилен - а нам предлагают даже в Kontak писать мелодию для струнных через него... фу....

Так что проблема описания сложных аккордов и прочих безымянных техник гармонизации - это очень непростой вопрос! Он даже на нотном стане непростой...

Помимо аккордов продумывать и удобный ввод таких вещи как:

  • Музыкальные штрихи

  • Мелизмы

  • Сложные пассажи

  • И некоторые другие (о которых я не знаю)

Это техники для фортепиано - а у других инструментов свои хитры техники, которые тоже как-то надо вводить!

Обоснуете? Выше я тут уже приводил аргументы против графических ЯП! И привёл лишь капельку аргументов за! Некоторые из комментирующих так же привели капельку аргументов за и против. Но в целом - я тут пока не вижу значимых аргументов за графическое программирование, тем более, если говорить о далёком будущем - что там такого должно быть, чтобы визуальная разработка заметно перевесила иные способы (кстати, не обязательно текстовые - если уже говорите о далёком будущем, хотя тогда стоит хорошо подумать - какие ещё могут быть альтернативы)? А не просто визуальные системы станут лишь подспорьем для других способов

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

Для визуализации вариации piano roll - хорошая штука - а имею ввиду - вводить музыку с помощью него (тем боле как Вы показали в виде текстовой графики, или я Вас не правильно понял) - те же Black MIDI не создаются на piano roll - их создают сложные алгоритмы, генерирующие MIDI-события, обрабатывающие готовые музыкальные паттерны!

Вот так будет на "RANGE" в варианте ввода в проприетарном буквенно-цифровом коде (но, как уже сказал, кодированный формат ввода, в принципе, можно будет настроить любой, или использовать один из готовых вариантов):

//Первая часть партитуры
{octave:3 keys: D#600 C#600 -F#600 -A#600+-F#600 -A#600+-F#600}:repeat(2)
{octave:3 keys: D#600 C#600 -F#600 -A#600+-F#600 -D#600 -A#600+-F#600 B#600 B600+-F600 B600+-F600}
{octave:3 keys: D#600 C#600 -C#600 B600+-F600 B#600+-F600}:repeat(2)
{octave:3 keys: D#600 C#600 -C#600 B600+-F600 -D#600 B600+-F600 A#600 -A#600+-F#600 A#600+-F#600}

//Или компактнее
use (octave=3, script="keys", len=600):{
(D# C# -F# (-A#+-F#):r2):r2
D# C# -F# -A#+-F# -D# -A#+-F# B# ( B+-F):r2
(D# C# -C# ( B+-F):r2):r2
D# C# -C# B+-F -D# B+-F A# (-A#+-F#):r2}

//В более сложном примере с большим числом одинаковых партий могло бы быть ещё компактнее:
use (octave=3, script="keys", len=600):{
var n1 = {D# C# -F#}
var n2 = {D# C# -C#}
var n3 = {-A#+-F#}
var n4 = {B+-F}
(n1 n3:r2):r2
n1 n3 -D# n3 B# n3:r2
(n2 n4:r2):r2
n2 n4 -D# n4 A# n3:r2}

Надеюсь нигде не ошибся. Если съедет ровность отображение - я не виноват - изначально всё было аккуратно выровнено

P.S.

Вот серьёзно думаю заменить символ "+" для формирования аккордов на что-то другое - чтобы не путать со смещением октав, например на "*" - просто "+" уже привычен для клавиатурных аккордов "сочетаний горячих клавиш"

Не кажется Вам, что это слишком громоздко? Время Piano roll прошло...

MusicXML  - он не для ручного ввода - а для автоматикой (в т.ч. кроссплатформенной) интеграции - как раз для копи/паста мог сгодиться...

Так же MusicXML априори очень гибкий и расширяемый формат. Например, в "ORANGE" помимо общих форматов музыкальных потоков WAVE и MIDI возможны и потоки в других форматах (пока сугубо теоретические - этот вопрос ещё не проработан, но заложен изначально), среди которых может быть и MusicXML; а так же запланирован (но может откажусь и буду расширять MusicXML) проприетарный открытый формат (кстати, рассматривалась база XML, JSON, Protobuf) - для более расширенного управления компонентами (как в качестве внутреннего протокола, так и для взаимодействия со сторонними компонентами). Просто у меня запланировано куда более сложное командное взаимодействие, чем набор MIDI-событий, в т.ч. с целью управления параметрами и техниками звукоизвлечения комплексных компонент (а-ля какие использует Kontakt)

мой пример было не про опции, а про работу с null значениями - я специально старался его абстрактно написать, а "CustomOptions["Allow"] " просто привёл как понятный источник null значения, но я не указывал его физическую природу - это может быть и карта "ключ-значение" (фиг его знает откуда полученная) - или обращение какому-либо хранилищу - хоть локальному, хоть БД, или какой-либо ещё комплексный сервис - который пытает получить значение из данных, собираемых их различных источников. ИМХО - алгоритму основной логики это всё должно быть сугубо "фиолетово" - у него есть источник "CustomOptions" - вот там он будет искать значение. А если его там нет - у него есть некий процесс иного поучения этого значения, которые тоже не гарантирует успех - и только затем значение берётся из кода - для случая, когда без него дальше никак не обойтись, но по какой-то непонятной причине оно так и не было получено!

Ну а в финале - передаём (во втором случае пытаемся) значение в нужные объекты - чтобы так больше не "мучиться" и для того, что это значение ещё где-то важно должно быть - если это "где-то" существует! Не вдаваясь в подробности того - как эти все вспомогательные объекты устроены!

//A?.B?.C?.Checked ??= Enabled;

но можно написать вот так (тоже вполне коротко, красиво и читаемо):

if (A?.B?.C.Checked is not null) A.B.C.Checked = Enabled;

P.S.

Введение NULL - "Ошибка на миллиард долларов" не Дейкстры, а Хоара (впервые появился NULL в ЯП ALGOL W ) - всё время путаю

Вопрос скорее про интеграцию с платформой

Понятное дело, что вы будете топить за свой ЯП всеми правдами и неправдами.

Я не собираюсь топить за свой ЯП! Как и топить другие системы (ну кроме Native instruments Kontakt - уж больно она меня разочаровала (хотя шутка, бесспорно, полезная); как и разочаровало, например, и развитие Sony Acid - который теперь мультикомбайн Vega, Cakewalk - который теперь Sonar (и многие другие мультидорожечники) - но это для тех кто в курсе). И готов принять любую критику своих идей - главное чтобы было обоснование, даже если я его сочту спорным - обоснованная критика - всё равно полезная критика!. И я не пытаюсь необоснованно критиковать вашу разработку. Напротив - я всячески желаю Вам удачи с ней!

И сути это не меняет - нельзя ошибиться в названии переменной, если его нельзя напечатать, а можно только выбрать из списка. Нельзя ошибиться с пропущенной кавычкой, если кавычек тоже нету. Нельзя перепутать "=" или "==" в условии, если "=" тоже нету

Как я выше написал - всем есть своя цена - и всего есть плюсы и минусы. И где есть минусы - их стараются "пусть порой условно и костылями" эти минусы устранять! И таких наработок для текстовых процессоров уже уйма - так что если сравнивать кодинг лет пятьдесят назад и сейчас - это будет гигантский разрыв (даже в рамках одного текстового ЯП)! Даже за последние 10 лет IDE шагнули очень далеко вперёд. А сейчас, на волне, генеративных лингвистических алгоритмов - шагнут ещё сильнее!

(Кстати, у Вас есть имена модулей, и да - вы позволяете их выбирать из списка (как, впрочем, это позволяют и быстрые всплывающие подсказки ввода) - но решаете ли Вы проблему, когда - это имя потом меняется у модуля - везде где используется переназначаться? Для визуальных систем это, правда, плёвое дело - а текстовые процессоры пришли к решениям не так давно - рефакторинг изменения и подсчёт с отображением ссылок - но 100% надёжности это не даёт... впрочем наврядлли сейчас хоть где-то есть 100% надёжность при активном повторном использовании кода и библиотек)

А, вот, куда сейчас развиваются музыкальные редакторы (априори визуальные) - мне категорически не нравится - это навороченные визуальны монстры с красивой графической обёрткой - и скудным сложным содержимым (я не буду говорить про плагины - среди которых есть и не скудные но от того не менее простые приложения)! Вот тут действительно назрела революция! Когда-то такой был Трекерный редактор, Piano roll, драмм-машина, , затем технология VST-плагинов, затем виртуальных DSP-процессоров и мультидорожечных редакторов и наконец музыкальных приложений для платформы Kontakt (ну я не все знаковые технологии в музыко-строении перечислил). Пришла пора двигаться дальше...

Нельзя ошибиться с разыменованием NULL в рантайме, если NULL-ов тоже нету (а вместо них есть значения/объекты по умолчанию).

Вот за это всецелое УРА! Учли опыт величайшей ошибки Дейкстры! Я тоже против NULL но....

для обхода NULL придумали и целе семейство null-операторов (?. ?? ??=) и отделили nullable определения переменных/свойств от не-nullable - и это отличное подспорье - появились очень интересные и удобные техники их применения!

С NULL очень удобно и красиво решается - без NULL приводит к старом заскорузлому некрасивому (хоть и понятному) коду!

Bool? Enabled = CustomOptions["Allow"] ?? (Object as ICheckable)?.Checked;
Enabled ??= A?.B?.C?.Checked ?? true;
CustomOptions["Allow"] = Enabled;
//A?.B?.C?.Checked ??= Enabled; //Вот это, правда, в C# не прокатит

Вот попробует без поддержки NULL такое написать

Так оставляйте в стороне и вспомогательные средства IDE для быстрого ввода в виде автодополнения, подсветки синтаксиса и проверки орфографии, а то как-то нечестно получается

Если внимательно читали - то я при оценке времени так и сделал. И указал - что с данными средствами будет и ещё быстрее и надёжнее

Просто Ваш аргумент он не имеет значимой силы

Интересно - кто минус моему комментарию выше поставил - за что (если это вы просто в отместку - то я не минусовал ваш комментарий)

Тут всё зависит от подходов к разработке и среды. Чем жёстче подходы - тем меньше комфорта и универсальность - но выше контроль.

А подобные опечатки текстовые IDE в 99.98% случае сами находят ещё на стадии окончания ввода слова! А некоторые продвинутые IDE ещё и сразу могут исправлять! Не говоря уже о быстрых подсказках автоподстановки - которые в умелых руках (и умелом текстовом процессоре) в более чем 80% случае просто позволяют избегать таких ошибок!

(не ключевые слова, уже определённых идентификаторов или литералов - так же будут выделяться цветом; а при мало-мальски грамотном назначении имён идентификаторов - вероятность ошибиться и из-за опечатки ввести другое имя существующего идентификатора - практически равна нулю - и современные IDE могут сразу автоматически исправлять такие опечатки)!

У визуальных сред куча своих проблем - часть я в комментариях к этой статье уже описал - но это далеко не полный список!

То же зарезервированное слово для определения сущности "instrument" - в текстовом редакторе вводится за 1.5-2 секунды (кото-то и быстрее введёт, я уж не говорю о шаблонах и копипасте, и быстрых подсказках ввода) - ошибка в тестовых процессорах будет видна сразу (это же ключевое слово - оно не будет выделено соответствующим образом) - и на её осознание и исправление (требующееся очень редко) уйдёт ещё секунды 2-3.

А сколько времени уйдёт в визуальном редакторе размещение такого компонента на поле (так оставим в стороне вспомогательные средства быстрого ввода): надо где-то нажать кнопку с командой добавления компонента, затем выбрать его из списка, или воспользоваться текстовым поиском, кликнуть по кнопке добавления, перенести его в нужное место на плоскости (а то ещё и другие компоненты подёргать) - это десятки секунд.... а потом окажется что это не тот компонент, что нужен (например, промахнулись - не туда кликнули)...

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

P.S.

Вот опечатка с MIDI там где нужна WAVE именно в моём ЯП всплыла- бы только при компиляции - когда драйвер устройства WASAPI не смог бы по типам данных спрячься с типом данных, передаваемых из канала! Но это уже нюансы ЯП гибкой статической типизации - точные типы появляются только при компиляции!

Упущенный параметр "Input=InputChanel2" для "Track2" (без специально настроенных анализаторов) всплыл бы только при отладке - параметр не обязательный (как и то, что у трека может не быть входного канала данных - когда он сами их статически описывает или генерирует, или откуда-то загружает) в своём теле - внутри { }; или в трек могут напрямую отправляться инструкции из другого трека (трек сначала может динамически наполняться, а потом только воспроизводиться, или не обязательно воспроизводиться, а, скажем, выгружаться на диск в файл/БД, или передаваться в другую программу, в т.ч. по сети)!

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

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

Скажу так - в этом конкретном случае лишь три проблемы:

  1. Отсутствие правильно архитектурно подготовленных библиотек и документации к ним

  2. Отсутствие настроенных кодогенератор, отладчиков и прочего суппорт-софта для данной среды

  3. Закостенелость мышления технического руководства

Я же выше написал - что системное программирование ещё долго будет с нами - и там будет править классика. Но, объёмы такого программирования будут год от года снижаться. А вот объёмы кодогенерации, в т.ч. и в области системного программирования будут год от года расти. А визуальное и декларативное программирование будут как раз стоять на фундаменте низкоуровневой кодогенерации и некоторых системных готовых библиотеках!

Я ни разу не говорил, что Ваше решение - не рабочее и не может иметь практической ценности или быть популярным в определённых кругах. А так да - только практическое применение и отзывы могут показать эффективность того или иного подхода. У меня пока нет рабочего решения :-(

Про повторное использование кода, кодогенерацию и шаблоны, и разбиение по файлам/модулям - я уже написал выше. И уверен - даже незнакомые с построением DSP-плагинов люди, сходу поймут что да как тут происходит и настраивается! Не говоря уж про строки комментариев - и прочее самодокументированние!

Да и ЯП "Orange" - задуман как куда более мощная "штука", чем просто DSP-фильтр - так что тут есть "место" для боллеплейт-кода - но всё это можно вынести в повторноиспользуемый код -или применять шаблоны! Да и с некоторым "синтаксическим сахаром" это всё можно несколько было упростить - для простых случаев

P.S. Хотя компиляция проекта в DSP-фильтр или VST-плагин - тоже вполне возможна

Поспешил - ошибки допустил - что сам уже заметил:

  1. Была проращена открывающая кавычка:
    Driver = WASAPI("Динамики (Realtek High Definition Audio)"

  2. Опечатка "instrumnet"->"instrument"

  3. В обоих OutputChanel ошибочно указал формат MIDI - там, конечно же WAVE - но может быть и MIDI - но тогда VSTi семплер будет проигнорирован (если он не сможет выдавать MIDI поток)

  4. В "Track2" забыл указать параметр "Input=InputChanel2" для настройки канала, по которому в трек будут поступать MIDI события!

  5. При старте проекта хорошо было бы указать и стартуемые треки, ну или аннотировать их как автотстартуемые вместе с проектом (а вообще треки могу запускаться (и останавливаться) в произвольный момент времени - мануально, по расписанию, по событию и другими способами - тут полная гибкость):
    run MyProject with track(Auto) [MyLayer.Track1, MyLayer.Track2]

  6. У значений перечислений без указания полного пути идентификатора - по-хорошему надо бы поставить точку перед идентификатором значения - чтобы синтаксический разбор понимал, что надо проанализировать тип приёмника для идентификации полного имени значения - но, будем считать, что можно и без точки, когда нет пересечений идентификаторов в текущем контексте - опция настройки проекта)

Примечания:

  1. Маппинг каналов скорее лучше делать через отдельный компонент Mixer - но для простоты не стал его указывать - а вообще - в мультиканальном проекте с пространственным 3D0звучанием такой компонент может активно применяться!

  2. Вместо указания параметра инструмента "ProgramFIxed" (что скорее для инструментов, которые не поддерживают разные программы звучания) лучше настроить у InputChanel компонент фильтра - для отбрасывания MIDI инструкций смены инструмента:

Пример фильтрации в каналах

chanel InputChanel1
{

       Direct = Input
       Format = MIDI
Source = InputDevice1
Filter = MIDIBoolFilter
{

return MIDIEvent.Command != ProgramChange)

} //Задали произвольный алгоритм фильтра MIDI сообщений - пропускаются только "истинные" MIDI события

}

chanel InputChanel2
{

       Direct = Input
       Format = MIDI
Source = InputDevice2
Filter = MIDIEventFilter
{

return ? (MIDIEvent.Command == ProgramChange) MIDIEvent:new{Command=None}

} //Задали произвольный алгоритм фильтра MIDI сообщений - подменяющий сообщения по смене программы на пустую команду (в условии нет секции "иначе" - она генерируется автоматически - исходным значением событий); а, в принципе, такой фильтр может и другие преобразования делать (для WAVE-формата канала тоже свои фильтры могут быть - но там, их лучше подключать как DSP-процессоры - между каналами)

}

Filter = MIDIBoolFilter
{

return ? (MIDIEvent.Command==ProgramChange) MIDIEvent:{Command=None}

} //Задали произвольный алгоритм фильтра MIDI сообщений - подменяющий сообщения по смене программы на пустую команду (в условии нет секции "иначе" - она генерируется автоматически - исходным значением событий)

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

Главное преимущество визуального программирования - отсутствие необходимости именования переменных/объектов и ещё больше возможностей для инкапсуляции

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

Поэтому в своё примере выше - у меня все узлы именованы (кроме узлов проекций/фильтров - это порты, принадлежащие своим узлам, но - в принципе им, как и линиям тоже можно было бы вешать лейблы)! А так - как, в другом комментарии выше, я показывал - можно и анонимную лямбду создать - и передать её в другой блок!

И обратите внимание - графической связи между клавиатурами и синтезатором нет, она задаётся в свойствах

Да, при визуализации вполне допустимо - но, опять же, очень спорное решение - усложняет понимание схемы!

А насчёт примера.... ну я тут выше в комментарии уже приводил примеры своего ЯП для музыки "ORANGE" - он текстовый и на нём ваш пример (в котором, правда большая часть информации отсутствует в обоих вариантах представления) выглядел бы так:

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

project MyProject
{

device OutputDevice1
{

       Direct = Output //Не обязательно - т.к. это по умолчанию так
       Format = MIDI
      Driver = WASAPI(Динамики (Realtek High Definition Audio)"
       ChanelsMap = {Left->"L", Right->"R", BackLeft->"BL", BackRight->"BR"}

}

device OutputDevice2
{

       Direct = Output //Не обязательно - т.к. это по умолчанию так
       Format = MIDI
      Driver = WASAPIOut("LG ULTRAGEAR (Аудио Intel(R) для дисплеев)")
       ChanelsMap = {Left->"L", Right->"R"} //Не обязательно - т.к. это по умолчанию так (когда у устройства нет других каналов)

}

device InputDevice1
{
Direct = Input
Format = MIDI
            RAWFormat = Int
            RAWConverter = System.Converters.ToMIDI.KeyboardScanCodeToMIDI                          Driver = KeyboardInput //Если я правильно понял – что источников является букво-цифровая клавиатура
             RAWInternalConverter += @AnotherFunction //Если нужен какой-то свой обработчик конвертации потока кодов клавиатуры в MIDI инструкции
       ChanelsMap = {Mono->"1"}

}

device InputDevice2
      {

Direct = Input
           Format = MIDI
           Driver = MIDIInput("LoopBe Intenral") //Какой-то MIDI input - из примера не ясно как он настроен
       ChanelsMap = {Mono->"1"}

}

chanel OutputChanel1
{

Direct = Output //Не обязательно - т.к. это по умолчанию так
Format = MIDI
Space = STEREO //Не обязательно - т.к. это по умолчанию так
Destination = OutputDevice1
       ChanelsMap = {Left->Left, Right->Right} //Маппинг только в два канала устройства воспроизведения

}

chanel OutputChanel2
{
Format = MIDI
Destination = OutputDevice2
       //ChanelsMap = {Left->Left, Right->Right} //Не требуется, т.к. тут маппинг по умолчанию в два доступных у устройства канала

}

chanel InputChanel1
{

              Direct = Input
             Format = MIDI
             Source = InputDevice1

      }

      chanel InputChanel2
      {

            Direct = Input
           Format = MIDI
           Source = InputDevice2

      }

      sampler S_yxg50_Sampler
      {
          Format = VSTi
          Path = FilePath("c:\vst\yamaha\syxg50.dll":raw)
          Space = STEREO //Не обязательно - т.к. это по умолчанию так
       ChanelsMap = {Left->"01", Right->"02"}

}

      instrument S_yxg50
      {

          Destination = S_yxg50_Sampler
      Program = 8 //Вообще инструмент подразумевает фиксацию программы синтезатора здесь (т.к. именно инструмент определяет настройки звучания), но в примере она фиксируется только для одного Midi input (вероятно у другого - другая программа) - такое тоже возможно (здесь только значение по умолчанию)

      }

layer MainLayer
{

          track Track1

      {

           use instrumnet S_yxg50(ProgramFixed=true)
           use input InputChanel1
           use output [OutputChanel1,OutputChanel2] //В моей схеме не семплер подключается к каналам вывода, а музыкальный трек (здесь подключение сразу к двум каналам
           runtime input:loop //трек активен только в runtime режиме в бесконечном цикле воспроизведения

         }

         track Track2
         (
          Instrumnet=S_yxg50(Program=3, ProgramFixed=true) //Сменили программу (тут будет клон инструмента)
          Output = [OutputChanel1,OutputChanel2]

         ) @RuntimeInput(lnfinity) //аннотация режима исполнения трека

      }

      Layers=[MainLayer]

}

run MyProject

Надеюсь ничего не забыл, и правильно понял исходный пример. Да - может код несколько многословен - но тут много базового конфигурирования идёт. У Вас же, в визуальной части, настройки делаются в узлах - и не отображаются, но их всё-равно надо делать (текст тоже можно скрыть в сворачиваемых блоках, распихать по файлам и подключаемым модулям библиотек, в т.ч. для повторного использования), ну и текст легко комплексно просматривается, и легко рефакторится, и легко публикуется и передаётся куда-либо, да хоnть в Git

И да - всё-таки ЯП ORANGE хоть и спроектирован для реализации runtime MIDI-ввода - но, всё же, создан больше для кодирования воспроизведения в виде инструкций к семплерам (что можно делать и в runtime; или направлять MIDI инструкции из источника в генератор кода в инструкциях ЯП Orange)!

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

Ну - для этого возможны:

  1. Шаблоны быстрого ввода в текстовом процессоре IDE (в т.ч. привязанные к macros и static instument generators, которые могут читать конфигурацию из внешнего config-файла, а так же иметь доступ к AST-дереву выражений проекта - чтобы генерировать код максимально гибко и адаптивно; но я не говорю - что такое в принципе нельзя сделать при визуальной разработке - но инструментарий IDE должен быть очень продвинутым, в отличии от текстовых процессоров - где это либо уже реализовано, либо легко подключается плагинами, либо вообще решается на уровне компилятора и/или внешнего текстового препроцессора)

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

Есть одно пересечение от функции "Process" к "B" (в идеале там должно быть "мостик" - рисовал в ""Miro" - не поддерживает, видимо) - но, замечу, что как раз в этой схеме его можно избежать, нарисовав линию стрелки в другую сторону (обогнув функцию "Process2")! Кстати, IDE может иметь средство перераспределения схемы/части схемы - для минимизации пересечений.

В более сложных схемах могут применяться разные способы избежание пересечений или решения проблем их читаемости. Например, можно клонировать состояние системы в узле "А" (переменной/источнике/примёнике) - и нарисовать его ниже отдельно - так чтобы его связи не мешали другим. Или размещать их на разных слоях (в т.ч. с настроенной прозрачностью или цветами линий - чтобы даже в неотображаемом или полуотображаемом случае видеть намёки, что тут есть и другие связи). Можно и сами линии группировать через промежуточные узлы - и начинать из них движения тоже где-то ниже. Можно просто часть линий выносить в узел субпрограммы, который в основном режиме отображается как просто узел, а при детализации (как написал выше - это легко делать просто масштабированием схемы, ну или просто кликом по лупе в этом узле) - уже отображать отдельно его структуру. И так далее и тому подобное - вариантов как синтаксических так и средств IDE может быть много! Не думаю, что это такая уж проблема. Тем более, что я, ту не требую целостности графа, а в большинстве случаев такого большого числа переходов из одного узла вряд ли будет - на картинке уж очень специфическая ситуация - чаще всего инструкции достаточно линейны (ветвления условий и матчей - скорее всего не будут шибко обширными или хорошо сворачиваются, по указанным выше, или иным, методикам), а распараллеливания - вполне можно достаточно эффективно разнести друг от друга.

Кстати, IDE может даже представлять схему в разных вариантах компоновки - просто меняя способы её отображения (фактически не переставляя сами элементы) - что позволяет легко подстраивать её анализ под разные ситуации

У визуального программирования есть пара интересных архитектурных преимуществ - перед текстовым:

  1. Очень удобно управлять множественными потоками данных - в т.ч. ветвлениями или дублированием (см. пример ниже). От одного источника легко может исходить несколько переходов. И на эти переходы можно удобно накалывать разные условия или метки аннотаций - задающие логику работы. Более того, на источник и на приёмник можно вешать как бы специальные порты - проекции/фильтрации - так что все исходящие или, соответственно, входящие линии переходов, из/в эти порты, будут подвержены зависимы от действий, заданных в этих портах - и на один источник/приёмник можно повесить сразу несколько разных портов! Так же, множественные переходы могут удобно определять и параллельное выполнение этих операций (в т.ч. в режиме по умолчанию, когда компилятор сам решает как лучше выполнять эти действия - в отдельном потоке или последовательно - в зависимости от настроек контекста выполнения и специальных хинтов-аннотаций со стороны программиста)

  2. В отличии от представления инструкций/деклараций в текстов - которых по сути линейны - графические схемы размещаются на плоскости - а, в принципе, в 3D и даже в большем числе измерений - что позволяет более наглядно размещать связи между элементами и вложенные блоки. Тут же можно сказать и про уровень масштабирования - когда можно приближая масштаб легко переходить от общего узла некоторого блока - к его внутренней реализации, оставаясь в текущем контексте, что позволяет (при необходимости), например, вместо внутренней логики подпрограммы (читай функции) подставлять идентификаторы текущего контекста - чтобы лучше понимать как внешняя среда влияет на результат внутренней

В схеме выше много действий. Условно начало можно считать получение фильтра FilterList (хотел сначала сделать точку входа Request - но передумал - и так сложно вышло)

Ключевым тут является источник переменной "A" (тип который является перечислимым) - у неё есть ряд исходящих портов разного типа - какие-то передают все данные переменной "A" (но только если сущность переменной "A" удовлетворяет условиям); какие-то передают только часть её содержимого - поэлементно удовлетворяющие условию. Так же тут осуществляются операции фильтрации данных по типам и контрактам (забыл добавить и просто операции преобразования)

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

Короче - схема, безусловно очень абстрактная, но я просто хотел показать возможную глубину фишек визуального программирования на графических схемах

1
23 ...

Информация

В рейтинге
2 084-й
Откуда
Москва, Москва и Московская обл., Россия
Дата рождения
Зарегистрирован
Активность