Оптимизация размера трекерной музыки
Shiru (A.Semenov) mailto:shiru at mail dot ru



Как можно понять из заголовка, речь в данной статье пойдёт о приёмах уменьшения объёма так называемых "трекерных модулей" - музыки в форматах MOD, S3M, XM, IT, и им подобных. Для начала отвечу на закономерный вопрос - какое отношение данная тема имеет к разработке игр? На текущий момент трекерная музыка продолжает успешно использоваться для создания музыкального сопровождения в играх на различных маломощных платформах (карманные приставки, КПК), и на PC, в небольших shareware-играх. Это обусловлено тем, что трекерные форматы обеспечивают оптимальное соотношение размера файла и качества звучания. Но встречаются ситуации, когда размер модулей выходит за определённые рамки - например, музыка слишком сильно увеличивает размер дистрибутива; игра не помещается в оперативную память; игра не укладывается в ограниченное время, отведённое для загрузки данных. В этих условиях приходится искать способы уменьшить размер модуля, сохранив приемлемое качество его звучания. Если это ваш случай - данная статья, возможно, будет вам полезна. Для понимания материала желательно разбираться в принципах создания трекерной музыки.

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



Простейшая оптимизация

Самое первое средство, которое надо всегда, в обязательном порядке, применять для всех ваших модулей - это авточистка модуля в ModPlug Tracker (один из самых популярных редакторов-трекеров). Загрузите модуль, и выберите Edit->Cleanup->Cleanup Song (не забудьте сохранить трек). Это простейшее действие сразу сделает множество очень полезных вещей. Оно уберёт неиспользуемые (не присутствующие в order list) паттерны; неиспользуемые в композиции инструменты; неиспользуемые в инструментах сэмплы (для многослойных инструментов); отрежет куски сэмплов, находящиеся после маркера конца петли (т.е. никогда не звучащие). Удивительно, но очень часто авторы модулей пренебрегают этим элементарным действием, увеличивая размер модулей вдвое, втрое. Всегда выполняйте это действие после окончания работы над треком (после написания, перед и после оптимизации).

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

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



Основная оптимизация

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

Для начала надо определиться, насколько вы можете пожертвовать качеством звука. Здесь всё зависит от того, на каком устройстве вы будете воспроизводить оптимизируемые модули. Одно дело - качественная компьютерная акустика на PC, и совсем другое - монофонический динамик телевизора (с полосой воспроизводимых частот до 8-12 килогерц) или маленький плёночный динамик портативной игровой приставки (вариант - плохие наушники). Для каждого из этих вариантов допустим свой уровень снижения качества звука - заметное на PC ухудшение звучания может быть совершенно незаметным на приставке. Для PC тоже допустимы разные уровни снижения качества - возможно, вас устроит звучание на уровне MP3 с битрейтом 56 kb/s.

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

Если удалить из сэмпла уже нечего - надо попробовать второй способ: снизить качество его оцифровки, за счёт чего сэмпл потеряет в размере. Снижение качества звучания означает выборочную конверсию сэмплов 16bit>8bit, снижение их частоты дискретизации. На слух это выражается в появлении шумов и потере высокочастотных составляющих звука. Появление небольших шумов в сэмпле (при снижении разрядности) может быть абсолютно незаметно в общей композиции. При снижении частоты дискретизации надо помнить, что согласно теореме Котельникова, для оцифровки звука с частотой f требуется частота дискретизации 2f и выше. Это означает, что многие низкочастотные звуки без выраженных высокочастотных составляющих в спектре (например, бас-гитара, бочка) будут приемлемо звучать на очень низких частотах дискретизации их сэмплов.

Далее я опишу общий порядок оптимизации одного инструмента.

Если инструмент многослойный (но не набор ударных/эффектов) - проверить, действительно-ли необходимо использовать все его слои, и, если звучание с уменьшенным их количеством (вплоть до одного) приемлемо - удалить лишние.

Прослушать композицию в трекере, который показывает позицию указателя в сэмпле при проигрывании (такая возможность есть в Fast Tracker II, Sk@le, но её нет в ModPlug Tracker`е). Проследить, до какой позиции максимально доходит указатель. Нередко бывает, что длина сэмпла очень избыточна, и можно смело отрезать большой его кусок в конце - он просто никогда не звучит в реальном треке.

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

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

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

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

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

После всего вышеописанного, если сэмпл по-прежнему слишком велик, нужно приступать к прямому снижению его качества (разрядности и частоты дискретизации). Проще всего это делать в ModPlug Tracker`е. Необходимые для этого функции находятся на вкладке Samples. Кнопка Downsample при каждом нажатии понижает частоту дискретизации выбранного сэмпла вдвое. Для снижения разрядности нужно нажать правую кнопку мыши на области редактирования сэмпла, и выбрать во всплывающем меню пункт Convert to 8bit (присутствует только у 16bit сэмплов). Перед использованием этих функций не забывайте сохранять трек, т.к. на них не действует Undo. Общий алгоритм действий таков: нажмите Downsample один раз, проверьте звучание сэмпла. Если оно не изменилось - сохраните модуль, нажмите ещё раз. И так до тех пор, пока звучание сэмпла не ухудшится до неприемлемого уровня. Таким образом, определитесь, насколько можно понизить качество этого сэмпла. При необходимости снизьте разрядность (это можно сделать как до снижения частоты дискретизации, так и после). Прослушайте трек, чтобы узнать, как изменение качества сэмпла отразилось на общем звучании.

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



Оптимизация по мелочам

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

Оптимизация по числу каналов. Нередко встречаются модули, использующие 32 и более канала. Конечно, сложно что-то сказать против авторской реализации (может, идея этого требует), но практически, настолько большая полифония в модуле - это излишество, ведущее лишь к повышению нагрузки на процессор и лишнему расходу памяти. На заре трекинга писали отличные модули всего в 4-х каналах. Сейчас вполне разумным числом каналов является 8-16. Так как специфика игровой музыки обычно требует, чтобы музыка создавала атмосферу, но не отвлекала всё внимание на себя, такое исскуственное ограничение полифонии не является проблемой для музыканта. Если для композиции потребовалось 16 и более каналов - стоит задуматься, возможно, лучше заменить часть каналов уже сведенными в один канал сэмплами. Например, это можно сделать для широких аккордов на струнных, для сложного бита (который иногда выгоднее заменить на сведённый в один канал луп).

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

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



Дополнительные возможности оптимизации

На достаточно мощных платформах (PC, мощные КПК) становится возможным применение упаковки сэмплов в модулях алгоритмами MP3/OGG (реализовано в форматах MO3, OXM). Это позволяет существенно снизить размер файла с модулем (например, с 4 мегабайт до 700 килобайт) без каких-либо заметных на слух изменений, но в оперативной памяти модуль будет занимать столько места, сколько занимает в несжатом виде, т.к. сэмплы распаковываются в момент загрузки (другие варианты просто неприемлемы). Для использования этой возможности ваш загрузчик/плеер модулей должен поддерживать используемый формат сжатия. В коммерческих звуковых библиотеках для воспроизведения трекерной музыки такая поддержка встречается (BASS - MO3, FMOD - OXM), но не является обязательной возможностью.

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

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

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

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



В заключение

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

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

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

И напоследок хочу заметить, что всё, описанное в этой статье, не является плодом голых теоретических измышлений на тему, но является практическим опытом, позволившим сохранить музыку в нескольких играх при портировании их на платформу с очень жёсткими ограничениями по памяти и скорости загрузки данных. Одиночные модули объёмом 80-800 килобайт успешно сокращались по размеру до 20-100 килобайт, при этом сохранялось приемлемое качество звучания.



Ссылки по теме

Сайт ModPlug Tracker
Сайт Sk@le Tracker
Статья о формате MO3 (на русском)
Страничка MO3-конвертера