03 августа 2018

                            Новости
                        by Alone Coder

На работе у нас пертурбации, дома веселье, ещё я утонул в
ремонте, поэтому я не попал ни на одно пати, а этот номер газеты
задержался. Думаю, следующий задержится тоже, потому что дела
ещё далеко не закончились. Зато в этом году, спустя уже не знаю
сколько, удалось несколько раз выбраться на карьер, даже с
Louis'ой и детишками - поочерёдно. Пешком. С коляской. 

Видел Алексея Бугрова (который мне помогал с компьютером на
презентации Font Editor'а в1996 году). Сейчас у него своя фирма
по разработке железяк, по этому поводу и встречались. Выглядит
очень усталым. Показывал ему демы, его заинтересовали
мультиколоры и бордерный KOT :).

Звонил T(c)S'у. Он живёт всё там же, где мы тусовались в
2000-2002 годах, и работает в своей фирме по ремонту сотовых
телефонов. Очень занят. Хотел переманить его к нам на завод в
качестве программиста микроконтроллеров, но не смог убедить. В
Рязани очень трудно найти таких специалистов.

CyberDaemon периодически пишет, присылает новости из игрового 
мира (например, что STEP делают новую игру во вселенной
Звёздного Наследия, но не для Speccy...). 

Arwald всё ещё ведёт занятия по 2D анимации на киностудии, но я 
ни разу не смог его застать.

Wanderer написал (спустя22 года!) новую игру - CELL 3326: 
https://zxwanderer.github.io/cellЗЗ26/ Это квест на новом движке
типа Laser Squad. Хоть я и не игрок, но я его прошёл полностью и
подкорректировал пару переводов. Wanderer'а я тоже пытался
переманить, но из меня плохой head hunter :)

Hippiman выпустил игру Dizzy and the Mystical Letter на 
универсальном DizzyAGE -подобном движке, который он написал на
языке NedoLang. На настоящий момент игра существует на русском,
английском и португальском языках. Неужели спектрумовские игры
проDizzy не выходили так давно? Какие мы старые... Сейчас
Hippiman вносит последние штрихи в движок и собирается релизить 
его отдельно. Уровни редактируются прямо в редакторе DizzyAGE.
Теперь каждый сможет сделать свою сериюDizzy :)

Karbo опять исчез, поэтому его трек не попал в игру. Насколько 
мне известно, он сейчас в деревне, а дел там летом много.

John Silver занимается написанием партитур для оркестра и 
пропадает в командировках. Последний раз уехал на целый месяц.

Зато один композитор изШотландии написал, что решил освоить Pro
Tracker 3, обещал поделиться результатами, когда получится :) 

DimkaM написал инструкцию, как работать с расширенной памятью в 
компиляторе IAR (нажмите кнопку"2" ). Пока таких возможностей
нет в NedoLang ( Hippiman в своём движке Dizzy размещал
процедуры и данные по памяти вручную). Может, со временем
получится придумать круче? :)

В эмуляторе Unreal Speccy Portable появилась поддержка
расширенных экранов ATM2 ( Fyrex хотел с удобством читать ACNews
и добился этого :)). Но память пока работает только в верхнем
окне, причём, кажется, порты#7ffd и #fff7 устанавливают один и
тот же регистр.

Utz/irrlicht project организует конкурс графики под64 цвета на 
точку (как в Eye Ache 2 ) на International Symposium on Bits and
Beverages. 
Картинки надо рисовать в тулзе StellarPaint:
http://irrlichtproject.de/stellarpaint/
Или просто сделатьPNG картинку64x48 с этой палитрой:
http://
irrlichtproject.de/stellarpaint/stellarmode_gimp_tools.zip
И прислать по адресу1bitforum@posteo.net до18 сентября 2018
года. Не больше двух работ от автора, никаких конверсий или
ограничений на свободное распространение!

Ещё Utz написал по поводу своего языка программирования для
музыки (разговор завязался благодаря проекту языкаListh,
опубликованному в прошлом номере):

Utz> 
Сейчас я переделываю MDAL(https://utz82.github.io/MDAL/). 
На сайте сейчас не совсем понятно, но в общем там 3 вещи:
- MDMOD- абстрактный универсальный язык разметки; 
- MDCONF- стандарт передачи данных, основанный на XML, который 
описывает, как из универсального MDMODна входе получить 
специфический для данного звукового устройства ассемблерный
результат;
- libmdal- библиотека, реализующая MDMOD и MDCONF для 
использования (в будущем) в качестве бэк-энда для PC-шных
трекеров.
Ещё имеется bintracker(https://utz82.github.io/bintracker/) - 
собственно, тестовая реализация.

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

Alone> 
У меня была идея по поводу рекурсивного музыкального языка (и
трекерного интерфейса), с которым можно реализовать ранее
недостижимые музыкальные фишки.

Допустим, у нас AY музон, состоящий из паттернов, а те состоят
из треков на каждый канал. Каждый трек может содержать множество
инструментов (звуковых эффектов), которые играют одновременно, а
слышно только самый громкий на текущий момент. Нота в треке с
номером инструментаN может означать одно из двух:
-перезапуск звукового эффекта N в этом канале (стаккато);
-изменение частоты тона в звуковом эффекте N в этом канале
(легато).
По умолчанию используетсястаккато, а легато надо чем-то
помечать в нотном тексте. Или наоборот.
Или, как вариант,легато будет использоваться, если не указан
номер инструмента - будет использоваться предыдущий указанный
номер.

В AY музыке инструменты состоят из "сэмпла" (список точных
смещений тона, смещений громкости и масок тона-шума-огибающей на
каждый фрейм времени) и "орнамента" (список смещений тона в
полутонах на каждый фрейм времени).
Если в "орнамент" добавить громкости, он будет выглядеть как
трек в паттерне, с легато на всех нотах. Это первое
использование рекурсии.
Следующее использование - можно писать короткие музыкальные
фразы (риффы) и использовать их как ноты.
(Музыкальный модуль вызывает треки, треки вызывают риффы, риффы
вызывают орнаменты - всё единым механизмом.
Высота ноты уровнем выше задаёт транспозицию для используемого
риффа.)
Рифф содержит колонку"времени" для каждой ноты - сколько
фреймов её играть. Можно указатьвремя=0, чтобы запустить две
ноты одновременно: так можно, например, использовать рифф
перкуссии одновременно с риффом фонового арпеджио.
К сожалению, "сэмплы" уже играются другим механизмом, как
звуковой эффект.
Звуковые эффекты создаются нотами с флагом"стаккато" и
удаляются, когда закончатся, или по ноте"R".

Utz> 
Я тоже думал над таким рекурсивным подходом. Звуковой движок
PhaseSqueek 
https://github.com/utz82/ZX-Spectrum-1-Bit-Routines/tree/master/
phasesqueek
частично использует эту идею. Формат данных"fx table"там почти 
такой же, как формат данных"pattern".Правда, там не совсем 
рекурсия, потому что вfx tableесть команда"position jump",
которой нет в паттернах, но вfx tableтот же элемент данных, 
что и там. Если они будут обрабатываться одинаковой логикой, то
получится настоящая рекурсия. Ордер тоже можно сделать так же.

Вот пример MDMOD(старой версии) для движка PhaseSqueek: 
https://github.com/utz82/MDAL/blob/master/examples/
phasesqueek-demo.mdal

Это текстовый формат, как и в VTили 1tracker, но он хранит 
только текущие изменения, перед которыми пишетсяCOMMAND=(кроме 
ордера, где команда по умолчанию). Там есть одна фича, которой в
новом стандарте не будет, потому что мне её сложно поддерживать:
в MDALv1тип блока определяется автоматически, например, из 
такого текста в MDMOD:

:SEQUENCE
 intro
 ...
:intro
 FX=arp
 ...
:arp
 CMD=...

компилятор mdalможет определить, чтоintro- это паттерн, аarp
- этоfx table.
В новой версии формата MDMODпользователь сам будет указывать 
тип блока и его уникальный номер. В новом формате ещё будут
использоваться квадратные скобки для обрамления блоков.

:BLOCKTYPE:$01[:name] {
       COMMAND=value, CMD2=othervalue...
}

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

Делать формат MDMODпростым - не главная задача. Главное, чтобы 
его можно было редактировать вручную (но не в том смысле, чтобы
печатать директивыdb) и при этом нормально обрабатывать 
трекером или другим GUI.

Что могу сразу сказать, новый стандарт MDCONFуже будет 
полностью поддерживать вышеописанную рекурсивность.
Имеется 4 базовых типа данных:command, ifield, iblockиigroup,
гдеcommandопределяет один входной параметр (такой как "note", 
"volume", "name"...). Типifieldрасширяет типcommand,тип 
iblockсодержит плавающее число полейifield,а типigroup 
содержит элементы типаifield, iblockили опять-такиigroup.
Им соответствуют выходные типы данных, которые могут
соответствовать или не соответствовать входной рекурсивной
структуре.

На самом деле входная структура в новом стандарте MDAL
совершенно виртуальная, то есть не имеет отношения к выходной
структуре. Это позволяет мудрить с входным форматом вплоть до
поддержки совершенно разных видов ордера:
- "таблица", как в Beep Tracker;
- "список", как в Beepolaили в текущей версии bintracker; 
- "автоматический", то есть без ордера, как в 1tracker.
Причём независимо от звукового движка. С таким подходом
низкоуровневую реализацию будет легко оптимизировать.

Что я пока не продумал - как избежать выделения ордера в
отдельный тип данных, а вывести его из обычных типов(i/o)block.
Теоретически это должно работать, ведь мы можем определить
структуру ордера по тем же правилам, как и паттерны или любые
списки. Проблема в том, что это не будет работать, если выходной
формат использует список элементов (например, список сэмплов,
используемых в модуле, чтобы адресовать их по табличке или ещё
как). Для этого есть отдельный тип выходных данных(otype)под 
названиемolist.Мне кажется, если я включу osequence внутрь 
oblock,то смогу избавиться отolist.Также есть специальный
двоичный тип выходных данных -obitfield.Может быть, и 
получится вывести все выходные типы данных изobitfield,но это 
пока в голове не вырисовывается.

Alone> 
А как ты отлаживаешь музыку в текстовом формате? Когда я писал
трек для игры "Sewerage" на ассемблере, мне приходилось слушать
его сначала после каждого изменения...

Utz> 
Так же получается и с текущей libmdal(разве что можно поставить 
блочные комментарии, чтобы пропускать куски ордера и т.п.).
Новая версия libmdal,скорее всего, будет работать в реальном 
времени, так что любое изменение в MDMODможет автоматически 
обновлять выходную структуру (а она может выдавать бинарник и
ассемблер для всевозможных случаев - играть паттерн/текущую
позицию/сонг сначала и т.д.). Кроме того, новая libmdalдолжна 
включать своеобразный скриптовый язык, для взаимодействия и
реконфигурации на лету. Пока это не прорабатывал, но поглядываю
на языкScheme.

Alone> 
Я ещё раз подумал и придумал, как сделать рекурсивный формат без
сэмплов :) Ну, кроме нескольких стандартных звуков в поле номера
риффа (пример далее для AY).
Это всё возможно потому, что конкретный орнамент обычно
используется с одним конкретным инструментом.
Иерархия такая:ордер -> треки (можно несколько в одном канале,
с независимыми громкостями) ->риффы -> инструменты(орнаменты)
->сэмплы -> стандартные звуки. Всё это будем называть риффами.

- нота с риффом"T" включает тон и устанавливает частоту тона
(относительно частоты текущего риффа) - в текущем подканале
- нота с риффом"t" включает тон и устанавливает частоту тона
(абсолютную) - в текущем подканале
- нота с риффом"N" включает шум и устанавливает частоту шума -
в текущем подканале
- нота с риффом"n" устанавливает глобальное смещение шума
- нота с риффом"E","C","1" перезапускает огибающую указанного
типа - в текущем подканале
- нота с пользовательским риффом (мне понравилась твоя идея с
именованными треками) создаёт и запускает подканал с заданным
риффом (удаляется, когда заканчивается).
- нота с громкостью выключает огибающую и устанавливает
громкость (относительно громкости текущего риффа) в текущем
подканале.

По умолчанию в текущем фрейме текущего подканала (связанного с
текущим риффом) звук выключен, только громкость/огибающая
остаётся с прошлого фрейма (в первом фрейме риффа - нулевая).
Так мы можем накладыватьT+N+E в любой комбинации, используя
нулевую скорость.

Подканалы рендерятся плейером в один канал в соответствии с их
громкостями (слышно самый громкий на данный момент).

Utz> 
С точки зрения формата данных самый важный выбор - использовать
абстрактный базовый формат (соответствующий формату данных
плейера, как в PC-шных трекерах) или же подход "прямо в памяти",
как в большинстве нативных трекеров. Думаю, абстрактный для
этого подойдёт больше, потому что он может решить тут многие
проблемы. Так что надо исследовать этот вариант, если мы хотим
нативный трекер. С другой стороны, с подходом "прямо в памяти"
можно организовать очень интересные экспериментальные
интерфейсы. Я к тому, что концепции трекера уже 30 лет, но за
это время в трекерах появилось не так уж много новых идей. Было
бы интересно порвать с традиционными концепциями и построить всё
с новой точки зрения, без стереотипов. Как я понимаю,
defMONнаC64до какой-то степени пошёл по этому пути, но пока 
точно оценить не могу. Стоит посмотреть.

Например, можно поспорить с идеей, чтоTNEдолжны бать привязаны 
к ноте. Почему бы их не разделить? Конечно, это несколько дико в
контексте AY, потому что делители разные. Но все делители шума и
огибающей приемлемы (а иногда и юзабельны) в качестве делителей
тона, так что можно и дать пользователю шанс прострелить себе
ногу. Полагаю, nqможет с этим развлечься :D 
Или можно поставить три колонки делителей - тон, огибающая, шум,
а плейер будет брать те, которые ему надо. С абстрактным базовым
форматом этот выбор можно сделать во время компиляции, плейер
будет не очень перегружен. То же можно сказать про
многоканальные риффы и зацикленные сэмплы. Абстрактный базовый
формат с агрессивной оптимизацией в компиляторе может решить
многие такие проблемы. Вопрос только, юзабельный ли будет
результат - в смысле объёма скомпилированных данных. Здравый
смысл подсказывает, что объём получится большой даже с сильными
оптимизациями, но это надо исследовать и попробовать, прежде чем
отбросить :)

Alone> 
Как описывать многоканальные риффы/сэмплы? Мы не можем иметь
много стандартных звуков!

Utz> 
По идее лучше вообще без стандартных звуков. Их можно
реализовать в виде "патчей" или "макросов", загружаемых с диска.

Многоканальные риффы в абстрактном базовом формате можно
реализовать как "виртуальные" ордеры, которые разгребает
компилятор.

Alone> 
А как зацикливать сэмплы (особенно без шанса на бесконечное
размножение их, если забудем их заглушить)?

Utz> 
В общем-то, зацикленные сэмплы должны обрабатываться как циклы в
ордере. В MDAL v2было сделано две команды: команда типа 
"label",для указания именованных локаций внутри элемента
(ордер/паттерн/сэмпл/что-то ещё) и команда типа"reference",
которая ссылается наlabel(или другой элемент). Ордеры 
реализованы как обычные блоки, состоящие из таких команд ;)

Alone> 
А как отображать и редактировать такую древовидную структуру?

Utz> 
Главное, что MDAL(и в соответствии с ним bintracker ) будет 
поддерживать такую структуру. Если он не сможет, то мне придётся
повозиться, но сделать это. Чего мне пока не хватает - эмуляции
AY в bintracker.Эмуляторы в bintracker имеют специфические 
требования, а именно:1)они должны быть действительно 
свободными (то есть никакихGPL) и2)они должны поддерживать 
набор коллбэков в определённых точках, так что эмуляторы типа
Game Music Emuне подходят. Пока я не прорабатывал программный 
интерфейс, так что это потом.

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

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

С практической точки зрения на PC нет проблем, потому что экран
достаточно большой, чтобы показать дерево прямо в виде вложенных
элементов. Для нативного трекера можно использовать трюк,
который уже есть в bintracker'е:нажатиеEnterна поле, которое 
указывает на какой-то элемент, переходит к этому элементу. Можно
ещё отдельно вывести список текущих экземпляров этого элемента,
но это не обязательно - в частности, обращение к несуществующему
экземпляру может создать новый, пустой, а неиспользуемые
экземпляры могут быть выброшены оптимизатором.

Можно ещё подумать насчёт гибридного приложения, т.е. нативного
трекера, использующего мощную периферию. Но здесь практическая
проблема: на Западе такие устройства обычно базируются на
ESXDOS,а на Востоке, как я понимаю, - на TR-DOS. В ESXDOS есть 
какая-то эмуляция TR-DOS,но неполная. Например, я могу 
запустить Beep Tracker,но не могу ALASM. 

Я выпустил предварительные спецификации MDAL v2:

https://github.com/utz82/MDAL/wiki/
MDCONF-Standard-Version-2-Specification-Draft

https://github.com/utz82/MDAL/wiki/
MDMOD-Standard-Version-2-Specification-Draft

Полагаю, спецификация MDMODуже достаточно проработана, а MDCONF 
будет ещё корректироваться.

...

Свежие новости по libmdal:дело идёт медленнее, чем 
планировалось. Явно недооценил сложность.
Но библиотека уже умеет парсить текст MDMODво внутреннее 
представление модуля (в соответствии со спецификацией MDCONF) и 
выдавать правильный результат в формате MDMODобратно. Далее 
надо будет сгенерировать ассемблерный текст. Пока не полностью
вижу решение, но по идее нужен некий внутренний промежуточный
формат, из которого можно быстро сгенерировать этот ассемблер и
бинарник. Посмотрим, как получится.

                             * * *

По результатам этой беседы я решил довести язык Listh до
запускаемого состояния (нажмите кнопку"4" ). Может быть, со
временем что-то из него и вырастет :)



Other articles:


Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Similar articles:
News - Alone Coder'a impression on CC'2004.
BBS - list of stations BBS ZXNet.
destroyer - an overview of fresh media: Psychoz 9-12, HeresY 8-10, Buzz 20, Target 10, Ebelka, ZX-Guide # 4.5, RIP 15, Promised Land 2.

В этот день...   21 November