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

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

Послушать пример из заглавной картинки: [sarpnt][greggman]

Итак, сразу выкладываю технику. Тот кусок кода, с которым вы имеете дело, будет исполняться один раз каждый аудиофрейм (то есть, если частота дискретизации 8 килогерц, то код исполнится 8 тысяч раз). Результатом выполнения кода служит один семпл со значением от 0 до 255 (то есть, на выходе у нас восьмибитный звук). Если на выходе значение превышает 255, то происходит wraparound целочисленного значения (лишние биты отбрасываются). Если вы программировали на ассемблере, вам это должно быть знакомо. Все внутренние вычисления проходят в привычном 32-х битном формате.

А на входе у нас есть переменная t, которая хранит счетчик семплов, который растет от нуля до бесконечности.

Можно, недолго думая, вывести эту переменную. В результате к нам в наушники пойдет звук с частотой 31.25 герц. Вот такой код у нас получился:

t

Послушать: [sarpnt][greggman]

Дальше начинаются извращения. Во первых, все участники конкурса воспринимают эту задачу как 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)


  1. Gemefoll
    25.06.2023 04:50

    Классный язык, было бы прикольно послушать разные треки на нём и посмотреть их код.


    1. nikhotmsk Автор
      25.06.2023 04:50
      +8

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


  1. Gemefoll
    25.06.2023 04:50

    Классно, спасибо посмотрю.


  1. 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 и шейдеры



  1. Krasnoarmeec
    25.06.2023 04:50

    Прикольный язык. А что, там только 8-битную музыку можно делать, или режим 16 бит float тоже доступен?


    1. nikhotmsk Автор
      25.06.2023 04:50
      +1

      Всякие разные режимы есть. Но традиционный - 8 бит, 8 килогерц. Можно тактовую частоту поднять до 44100


  1. domix32
    25.06.2023 04:50
    +1

    Если кто-то хочет вырваться за пределы битового программирования есть ещё Sonic Pi.


  1. iShrimp
    25.06.2023 04:50
    +2

    Ну как же без ссылки на статью по теории ByteBeat?