Дорогой Хабр, через два месяца мне предстоит организовать и провести фестиваль компьютерного искусства, поэтому я уже сейчас собираю информацию про необычные проявления демосцены, на которые обычно никто не обращает внимания. Язык программирования для генеративной музыки ByteBeat — это как раз то, что я ищу.
Как вы догадались, глядя на заглавную картинку, сейчас будет нечто, очень похожее на язык программирования Lisp. Все примеры рабочие, их можно запустить прямо в браузере.
Послушать пример из заглавной картинки: [sarpnt][greggman]
Итак, сразу выкладываю технику. Тот кусок кода, с которым вы имеете дело, будет исполняться один раз каждый аудиофрейм (то есть, если частота дискретизации 8 килогерц, то код исполнится 8 тысяч раз). Результатом выполнения кода служит один семпл со значением от 0 до 255 (то есть, на выходе у нас восьмибитный звук). Если на выходе значение превышает 255, то происходит wraparound целочисленного значения (лишние биты отбрасываются). Если вы программировали на ассемблере, вам это должно быть знакомо. Все внутренние вычисления проходят в привычном 32-х битном формате.
А на входе у нас есть переменная t
, которая хранит счетчик семплов, который растет от нуля до бесконечности.
Можно, недолго думая, вывести эту переменную. В результате к нам в наушники пойдет звук с частотой 31.25 герц. Вот такой код у нас получился:
t
Дальше начинаются извращения. Во первых, все участники конкурса воспринимают эту задачу как Size-coding, то есть, хотят сделать исходный код как можно меньше. Читаемость кода идет лесом. Чтобы понять, как устроена программа, приходится очень долго вникать.
Потом, список команд искусственно ограничивается. Это сделано для того, чтобы программисты не увлекались и не тратили бесконечно много ресурсов. Процедура, генерирующая звук, должна отрабатывать быстро, и успевать вовремя, пока буфер аудиокарты не опустошился, иначе начнутся лаги.
Список ограничений
Код должен состоять из одного единственного выражения. Без переменных (кроме t
— она есть изначально).
Арифметические: + - * / % ( )
Побитовая логика: & | ^ << >>
Операторы сравнения: < > <= >= == !=
Стараться не вызывать функции, которые потребляют много ресурсов. Лучше всего обойтись вообще без них.
В рамках этих ограничений многие люди делают вполне приличные конкурсные работы. Регулярно устраиваются соревнования, например, в Нидерландах недавно прошла демопати Lovebyte, на которой ByteBeat был одной из номинаций. Также можно устраивать ByteJam — соревнование в реальном времени.
Вернемся к коду. Вот еще один пример:
((t%100) < 50)*100
Попробую перевести его на человеческий язык. Берем переменную t
, вычисляем значение по модулю 100 (или берем остаток от деления на число 100, то же самое). В результате получается значение, которое бегает от нуля до 99 по кругу.
Потом оператор сравнения сравнивает полученное значение с цифрой 50 и выдает на выход либо 1 либо 0 в зависимости от результата сравнения.
Умножение на 100 нужно для того, чтобы сделать сигнал чуть громче. Теперь наша функция выдает несколько семплов со значением 100, за которым следует несколько семплов со значением 0. В наушники идет квадратная звуковая волна.
Если хотите послушать, откройте предыдущий пример и скопируйте новый код туда вручную. Разумеется, вы можете менять цифры и сразу же наблюдать изменения в звуке. Код, который вы набрали, сохраняется в URL страницы, вы можете им делиться с друзьями.
Сигналы можно смешивать с помощью оператора сложения либо оператора побитового OR. Умножая сигналы на 0 либо на 1 можно сделать так, чтобы они включались и выключались в определенный момент.
Побитовые операторы AND, OR, XOR и побитовые сдвиги работают также, как и в других языках программирования, они взяты напрямую из языка ассемблер.
Если вы дочитали до этого места, то вы невероятно терпеливы. Я думаю, вы почувствовали, что чтобы добиться чего-то стоящего в ByteBeat, придется полностью перестраивать мозг для работы с функциональным программированием. Неизбежные трюки и костыли будут преследовать вас всюду. Впрочем, если вы имеете опыт с языками наподобие Lisp, то вам все это, скорее всего, понравится.
В рамках подготовки к фестивалю самодельной электроники и компьютерного искусства "Undefined" я буду время от времени публиковать технические статьи. Надеюсь на поддержку от сообщества. Если вы хотите волонтерить на фестивале, заходите в наш чат. Хочу поблагодарить администрацию Хабрахабра за доверие и за предоставленный хаб. Буду постепенно наполнять его статьями.
Комментарии (9)
forthuse
25.06.2023 04:50+3Интересно, что в проигрывателе есть возможность проигрывать код и в представлении RPN и представлено несколько примеров (под классификацией PostFix)
Здесь некоторое описание доступных RPN словb PUT stack put c DROP discards the top of the stack d * multiply e / divide f + plus g - minus h % modulo i ? (NOT USED) j << less than k >> shift right l & and m | or n ^ xor o ~ invert p DUP duplicate stack q PICK stack pick r SWAP swap stack s < less than t > greater than u = equals v N/A w N/A x N/A y N/A z N/A
Проект ByteBot с поддержкой и генерации RPN кода.
P.S. т.е. такой вариант языка создания Бит музыки близок идейно Forth Haiku Salon сделанного уже для создания графических эффектов.
Forth и шейдеры
Krasnoarmeec
25.06.2023 04:50Прикольный язык. А что, там только 8-битную музыку можно делать, или режим 16 бит float тоже доступен?
nikhotmsk Автор
25.06.2023 04:50+1Всякие разные режимы есть. Но традиционный - 8 бит, 8 килогерц. Можно тактовую частоту поднять до 44100
domix32
25.06.2023 04:50+1Если кто-то хочет вырваться за пределы битового программирования есть ещё Sonic Pi.
Gemefoll
Классный язык, было бы прикольно послушать разные треки на нём и посмотреть их код.
nikhotmsk Автор
Открой вот этот проигрыватель. Если запустится, нажми кнопку Beats в правом верхнем углу, там коллекция треков. Еще где-то в текстовом виде должно быть.