Аннотация


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



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


Введение


Процедурная генерация на основе музыки в видеоиграх — это та тема, которая, лично для меня, всегда была окутана неким налетом мистицизма. Есть что-то невероятное в том, как звуковые формы мало того, что визуализируются, так еще и напрямую влияют на геймплей. Выглядит все это своеобразно, но чертовски весело. Именно поэтому у подобных игр есть своя небольшая, но стабильная аудитория. В Steam для подобных игр добавили отдельные теги «Генерация на основе музыки» и «Ритм-игра». В данный момент по этим тегам можно найти около 200 проектов, хотя игр, которые используют данную механику, намного больше.


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


Примеры хороших проектов


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


Строго говоря, чистая генерация используется только в Audiosurf. Остальные игры использую те или иные её элементы. Какие-то игры больше заточены на отслеживания бита, какие-то — на громкость трека и т.п.


Подобные проекты очень сложно оценить по скриншоту или описанию, поэтому, если у вас нет времени поиграть, просто посмотрите видео на YouTube.


Audiosurf



Для многих игроков Audiosurf был первой игрой, в которой была использована генерация контента на основе музыки. Проект был создан независимым разработчиком Invisible Handlebar — компанией Дилана Фитерера. Когда Audiosurf появился в Steam, этот рынок только начинал развиваться, и до нынешних монструозных темпов роста было ещё далеко. Audiosurf выглядел очень свежо и не обычно, кроме того, это была первая игра в Steam (кроме игр Valve), которая содержала в себе достижения!


Слоган Audiosurf — "Ride your music" — очень точно отражает игровой процесс: на основе вашего музыкального трека создается трасса, которую вам нужно проехать. Игра учитывает скорость трека, динамические изменения (увеличение и снижение громкости) и бит. В ней можно использовать разные жанры музыки и сочетать их с различными режимами игры. Кроме того, для каждого трека существует своя таблица рекордов, и ты с удивлением можешь узнать, что твой любимый "Undeground death metal" слушает еще десять человек.



К сожалению, в статике Audiosurf не воспринимается. Нужно играть.


Если говорить о геймплее, то Audiosurf великолепен. Например, если трек начинается с тихого вступления, ваш кораблик медленно ползет в горку, но когда музыкальная фактура становится более насыщенной и полнозвучной, скорость движения увеличивается, и вы на всех порах мчитесь вниз. Особенно хорошо чувствуется так называемый Drop, во время которого звук "обрывается" посреди развития, а потом возвращается в момент кульминации. Разнообразная партия ударных может превратить ваш трек в холмистую дорогу, а также повлиять на спец. эффекты. Кроме того, блоки, которые вы должны собирать, проходя сгенерированную трассу, тоже расставляются под бит.


С момента выхода игры прошло уже 10 лет, но она до сих пор очень популярна у игроков. В данный момент вышло две части игры, а разработчик Dylan Fitterer продолжил развивать свои идеи и создал Audioshield, где вы отбиваетесь от летящих в вас под бит блоков в виртуальной реальности.


Советуем поиграть на таких треках, как:


  • System of a Down — Chop Suey!
  • Martin Garrix — Animals
  • Skrillex — Bangarang

Делитесь своими любимыми треками для Audiosurf в комментариях!


Игру можно купить в Steam.


Beat Hazard


В этом проекте создатели взяли стандартную механику Shoot'em up и добавили туда анализ ваших музыкальных треков. Получилось очень круто. Музыка влияет на все: мощность вашего корабля, количество противников, общую скорость игры. Лучше всего игру можно прочувствовать с музыкой, где есть резкие переходы от тишины к мощному звучанию, тогда ваш экран просто взрывается от эффектов, а корабль начинает стрелять огромными лучами.


В игре есть достаточно богатая механика, несколько режимов и огромные боссы. В общем, все, что нужно для веселья!



Советуем поиграть на таких треках, как:


  • The Prodigy — Invaders Must Die!
  • Infected Mushroom — The Legend of the Black Shawarma
  • Daft Punk — Contact

Пишите в комментариях, под какие треки вам больше всего нравится уничтожать вражеские корабли!


Игру можно купить в Steam.


Soundodger+


Игра представляет собой некую смесь Beat Hazzard и популярной Super Hexagon. Суть игрового процесса заключается в том, что вам нужно уворачиваться от объектов, активность которых зависит от вашего музыкального трека. Процесс очень сложный и оттого — супер-увлекательный.



Игру можно купить в Steam.


Crypt of the NecroDancer


Игра, которая безумно точно передает ритм и заставляет вас танцевать с геймпадом. Crypt of the NecroDancer — это Roguelike-проект, в котором и вы, и монстры должны двигаться строго под музыку. Если вы не попадаете в ритм, при движении игра вас штрафует. Вся локация при этом пульсирует в такт, что создает нереальную атмосферу. Саундтрек написал знаменитый Danny Baranowsky (Super Meat Boy, The Binding of Isaac). Между прочим, игра поддерживает танцевальные коврики!



Игру можно купить в Steam.


Geometry Dash


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



Как и практически все игры этого жанра, Geometry Dash выглядит очень ярко


Игру можно купить в Steam.


Beatbuddy: Tale of the Guardians


Великолепный музыкальный платформер, действие в котором происходит в подводном мире, живущем под яркий electro swing бит. Каждое существо в этой игре генерирует свой звук. Крабик выстукивает быстрый бит, актинии отвечают за бочку… При этом, главный герой может воздействовать на жителей мира и менять музыку и сам геймплей. Для игры использовались треки таких музыкантов, как Parov Stelar, Остин Уинтори, Sabrepulse и La Rochelle Band.



Игру можно купить в Steam.


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


Основные параметры звука


Параметры аналогового звука


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


К базовым параметрам звука мы будем относить следующее:


  • Частота звуковой волны или высота звука, Гц
  • Амплитуда звуковой волны или громкость звука, дБ
  • Коэффициент затухания — скорость убывания амплитуды с течением времени.
  • Форма волны — общий вид звуковой волны. С помощью этого параметра можно разделять звуки на группы (резкие, плавные, шумы и т.п.)

Для наглядности я привел основные характеристики звуковой волны на следующих графиках (единицы измерения не проставлены, прошу прощения):



Громкий звук с большой амплитудой



Тихий звук, у которого амплитуда меньше



Высокий звук, с большой частотой



Низкий звук, с меньшей частотой



Громкий и высокий звук (берегите уши!)


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


Параметры цифрового звука


При написании игр и других программ, мы будем работать именно с цифровым видом звука. Цифровой звук получается путем дискретизации (разбиении на небольшие моменты времени), квантования (округления до определенного уровня) и кодирования (собственно, превращения звука в нули и единицы). Много информации на эту тему вы можете найти в статье Теория звука. Что нужно знать о звуке, чтобы с ним работать. Опыт Яндекс.Музыки, которая мне очень понравилась. Там же вы найдете информацию про измерение громкости и описание фильтров, которые будут мной упоминаться.


Главное, что нам нужно знать о цифровом сигнале, это:


  1. Частота дискретизации (sample rate) — характеризует то, насколько точно ваш звук будет оцифрован. Например, когда мы говорим, что частота дискретизации 44,1 кГц, это значит, что сигнал измеряется 44 100 раз в течение одной секунды. Сегодня самыми распространенными частотами дискретизации являются 44,1 кГц и 48 кГц.


  2. Разрядность цифрового сигнала (Bit depth) — характеризует, насколько широкий динамический диапазон "влезет" в ваш цифровой. Измеряется в битах и обычно бывает 16, 24 и 32 битным. Динамический диапазон — это разница между самым громким и самым тихим звуком, выраженная в децибелах. Например, для 8-битного сигнала это 48 дБ, для 16-битного – 96 дБ, для 24-битного 144 дБ, а для 32-битного – 192 дБ.


  3. Битрейт (bitrate) — то, на что смотрели все пользователи интернета в 2002 году, когда качали музыку. Битрейт — это количество бит, используемых для передачи или обработки данных в единицу времени. В форматах потокового видео и аудио (например, MPEG и MP3), использующих сжатие c потерей качества, параметр «битрейт» выражает степень сжатия потока.



Метаданные в музыкальных файлах


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


Теги проще всего считывать с помощью уже готовой библиотеки, например с помощью TagLib.


Формат mp3 содержит в своей структуре ID3 метаданные, в которых мы можем хранить много информации. Есть несколько вариантов ID3 формата, но мы будем говорить о ID3 v2.3, в котором можно хранить больше всего данных. Из полезной информации нужно обратить внимание на: название, год записи, жанр, BPM (число ударов в минуту), длительность трека. Чем нам могут помочь эти поля при генерации контента? Если с BPM все понятно, он используется при генерации постоянно и о нем мы поговорим отдельно, то зачем нам нужны другие поля? Тут нужно проявить фантазию.


Например, мы считываем жанр и год. Для начала, нам нужно немного обработать данную информацию. Для упрощения будем рассматривать только английский язык. Mp3 теги (и другие теги) часто заполняют вручную, отсюда следуют разные написания жанров, разная пунктуация и т.п. Полученный тег лучше привести к единому формату, чтобы его проще было сопоставлять с другими. Желательно убрать все знаки пунктуации, пробелы и преобразовать строку в нижний регистр. Это можно сделать с помощью регулярных выражений.


После таких манипуляций вам будет намного проще сравнивать жанры песен. Дальше вам нужно будет создать базу жанров, на основе какого-то источника, и пройтись по ней для составления своей базы тегов. Вот пример списка всех жанров: musicgenreslist.com. Естественно, нужно выбрать только самые основные.


Я так и не ответил, зачем такие сложности? Приведу примеры (очень упрощенные).
На основе жанра мы можем:


  • Менять локацию (рок — мрачный лес, электронная музыка — космос, кантри — пустыня, поп — город и т.п.)
  • Менять персонажа
  • Менять врагов и т.п. ?


Пример персонажа на основе тегов rock, electro, pop.


А дальше можете придумывать все что угодно! Год выпуска альбома: 1960-1970? Переоденьте персонажа в одежду данного периода. Длительность трека 10 минут? Пусть у вашей «музыкально генерируемой змейки» будет длинный хвост. Возможностей очень много, и всегда есть шанс удивить игрока.


Представление аудиофайлов в Unity



Тут вроде все просто...


В Unity есть несколько главных компонентов для работы со звуком:


  • Audio Listener (слушатель) ведёт себя, как микрофон. Он получает входящие данные с любого источника звука (Audio Source) в сцене и проигрывает звуки через динамики. Для большинства приложений имеет смысл добавлять слушатель к главной камере — объекту Main Camera.
  • Audio Source (источник) воспроизводит Audio Clip в сцене. Если Audio Clip является 3D клипом, источник проигрывается в заданном положении в пространстве и будет приглушаться в зависимости от расстояния.
  • Audio Clips (клипы) содержат данные аудио, используемые в источниках аудио. Unity поддерживает моно, стерео и мультиканальные звуковые ассеты. Unity может импортировать следующие типы файлов: .aif, .wav, .mp3, и .ogg.


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


Музыкальные параметры трека


Итак, мы считали некоторые стартовые данные из нашего трека и у нас появились первые зачатки генерации. Теперь можно перейти к более сложной части. Нам нужно понять, какие динамические параметры трека мы можем определить и как их можно использовать в геймплее. Часть материала основано на блоге студии Parallelcube. Ребята делают ассеты и туториалы для Unreal Engine, за что им большое спасибо.


Можно выделить следующие задачи:


  • Определение бочки, как триггера для спецэффектов
  • Определение тихих и громких моментов в треке
  • Использование этих данных для построения уровня
  • Использование этих данные для создания эффектов

Определение бочки в треке и использование этого звука, как триггера.


Для того, чтобы начать работу по определению параметров трека, нужно выбрать музыку. Чтобы работать было проще, нужен трек, в котором есть явная бочка и, желательно, резкие переходы по громкости. Я выбрал трек Perturbator — Future Club, который вы могли слышать в игре Hotline Miami 2: Wrong Number.


Вот небольшой анализ вступления данного трека (аудиодорожка была специально сокращена)



  1. Так называемый fade in, или вступление. В этот момент трек нарастает по громкости.
  2. Появляется главная ударная сила — бочка. Моменты появления бочки очень легко читаются на визуальном представлении аудиодорожки. Кроме того, тут звучит фоновый синтезатор, и его шум виден на дорожке. Если бы трек не был скомпрессирован, то это было бы еще нагляднее. (подробности о компрессии тут)
  3. Появляется дополнительный синтезатор, который немного размывает четкость визуального представления бочки
  4. Пауза, появляющаяся перед ярким моментом трека (drop).
  5. Главная партия, где, кроме бочки, появляется басовый синтезатор, который сильно искажает визуальное представление сигнала, но бочку все еще можно различить.

Итак, наша основная задача — определять, в какой момент у нас звучит бочка. Это достаточно непростая задача, для которой обычно используют специальные аудиобиблиотеки. Помните, если есть уже готовые варианты, и у вас есть цель сделать эффект, а не изучать мат. часть, берите готовые варианты. Если у вашей игры есть бюджет и лишние 25$, то вы можете купить специальный ассет от разработчика 3y3net, который так и называется, Beat Detection. Кроме того, можно рассмотреть отличный вариант от разработчика Allan Pichardo. Если же вы хотите понять, как работают подобные алгоритмы, то, конечно же, пишите его с нуля, сами.


Как мы видели по аудиотреку, бит всегда четко выделяется по уровню звука. В этом его суть. Музыканты специально обрабатывают и компрессируют дорожку так, чтобы бит не забивался другими звуками и имел свое место в частотном диапазоне трека. Бит всегда громче, чем средний уровень громкости (Average). Если звук громче определенного порога (Threshold), то мы, просто посмотрев на графическое отображение звуковой волны, можем с уверенностью сказать "Да, это бит!".



Более подробное техническое описание и конкретные алгоритмы определения бита я бы хотел вынести в отдельную статью (она будет размещена через некоторое время), так как данная тема сильно выходит за рамки этого материала. Если коротко, в подобных алгоритмах звук сначала проходит через фильтры, чтобы его было проще обрабатывать, после чего анализируется динамика звуковой энергии. Вот пример подобного алгоритма (внимание, матлаб!).


Полное математическое описание данного алгоритма можно прочитать в этой статье (англ.): Design and implementation of a Beat Detector algorithm.


Поэтому, давайте представим, что мы смогли написать скрипт, который в риалтайме определяет, в какой момент у нас бьет бочка. Кроме того, с помощью алгоритма мы сможем также определять общий BPM и поймем, где у нас "бьет" основной ритм. Что мы можем сделать с полученной информацией?


Можно взять в пример Beathazard и сделать так, чтобы на каждый удар основного ритма наш корабль стрелял обычным обычным лазером, а когда идет удар бочки, то мы стреляем супер-лазером. Будет выглядеть как-то так:



Кроме того, мы сможем добавить больше спец. эффектов. И сделать так, чтобы уровень пульсировал вместе с битом:



Этот же алгоритм, который в реалтайме определяет бит, мы можем использовать для подсчета BPM (beats per minute или количество ударов в минуту). Информацию о BPM можно использовать, например, для генерации уровней сложности и расчета количества бонусных очков. Если трек быстрый (150 — 180 BMP), то игрок получает бонус X5 и т.п.


Определение тихих и громких моментов в треке


Одним из способов определения громких и тихих моментов является обработка трека фильтром нижних частот и получение скользящего среднего для уровня громкости. После чего мы можем сохранить данный уровень громкости в удобный нам формат, например — в массив float.


Если у вас получится определять тихие и громкие места в музыке динамически, вы сможете очень грамотно управлять напряжением и атмосферой в вашей игре. Например, перед битвой с боссом играет тревожная мелодия, а когда появляется босс, становится громче. Можно использовать алгоритм определения уровня громкости и усиливать все огни, которые есть на сцене. Так игрок будет понимать, что скоро наступит кульминационный момент.



Создание уровня на основе аудиоданных.


Если вы видели, как выглядят аудиодорожки, вы могли заместить, что они немного напоминают некий террейн с холмами, равнинами и ямами (особенно если трек не подвергался компрессии). Почему бы не сделать такой уровень, например, для гоночной 2D-аркады? Для этого можно использовать определение скользящего среднего по уровню громкости. Ниже я привел пример скользящего среднего для случайного набора данных:



Полученный массив данных вы можете использовать для генерации уровня как в 3D, так и в 2D пространстве. По факту, в Audiosurf использовался в основе этот алгоритм, но ребята его очень сильно усложнили и обвешали дополнительными фичами.



Сделать ваш вариант Elastomania, только с генерацией карты под музыку? Почему бы и нет!?


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


Заключение


Как видите, музыка может быть не только фоновым сопровождением вашей игры, но и активным генератором контента. Если вы захотите создать игру, в которой контент генерируется с помощью музыки, вам нужно будет обладать большим количеством знаний о звуке, чем в обычном проекте, так как нужно будет изучать характеристики звука и работу с звуком напрямую. Но, если вы это изучите, то сможете создавать очень крутые музыкальные игры, которые будут ограничены только вашей фантазией. Как я уже говорил, дальше я собираюсь написать ряд статей, в которых раскрою технические аспекты каждого геймдизайнерского решения из этого материала. В них мы больше погрузимся в технические аспекты работы с звуком и напишем конкретные примеры в Unity. Следите за новостями!



Полезные ссылки


Комментарии (6)


  1. Yermack
    16.11.2018 13:57

    Audiosurf весело игрался под что-нибудь от John5, а под композиции Франка Клепаки Ownage и Haunt, получались нереальные спуски в бездну! Ну вот, теперь знаю, как провести пятничный вечер…


  1. barbanel
    16.11.2018 15:21
    +2

    Имхо, еще одна интересная задумка — Beat Saber для VR.

    If You Want to ESCAPE with Me


    1. rPman
      17.11.2018 15:25

      разве там на основе музыки контент генерируется? я думал вручную расставляется.


  1. dolbnya
    16.11.2018 15:40

    Возможно, после очевидных вариантов сопоставлений в стиле «рок — мрачный лес, электронная музыка — космос, кантри — пустыня, поп — город», будет интересно попробовать поэкспериментировать. Пострелять в космосе под Баха, покататься по ночному городу под электронику, послушать кантри в лесу у костра.


  1. george3
    16.11.2018 23:34

    Обрадовался названию — подумал типо Milkdrop в 3D, увы нет.


  1. Space__Elf
    17.11.2018 09:03

    Melody Escape — не сюда?