WAV — звуковые эффекты и подключение звуковых банков
Источник: coreprime/kbot @ 0ab97bf · Редактировать на GitHub
Звуковые эффекты Total Annihilation (голоса юнитов, попадания оружия, щелчки интерфейса) — это обычные 8- и 16-битные файлы WAV в PCM, и в самом контейнере нет ничего особенного для TA. Интересно другое — подключение: как FBI юнитов, TDF оружия и глобальный интерфейс передают имена файлов на звуковую шину через три уровня косвенности.
Tip
Попробуйте сами.
# Play one directly
ls $(kbot ctx path)/sounds/ | head
afplay $(kbot ctx path)/sounds/cmdsel1.wav # macOS
aplay $(kbot ctx path)/sounds/cmdsel1.wav # Linux
# The web UI also previews WAV/MP3 inline
kbot mount $(kbot ctx path) --server
На диске это просто WAV
Файлы WAV лежат в sounds/. Они соответствуют стандартному формату
RIFF WAVE — всё, что воспроизводит WAV, воспроизводит и их. kbot не
разбирает их как особый формат: обозреватель передаёт их элементу
<audio> браузера.
Типичное кодирование в файлах из комплекта Cavedog:
| Свойство | Значение |
|---|---|
| Частота дискретизации | 22050 Гц (большинство), 11025 Гц (некоторые щелчки интерфейса) |
| Разрядность | 8-битный беззнаковый PCM |
| Каналы | Моно |
| Длительность | 0,1–3 секунды |
| Размер файла | 5 КБ – 200 КБ |
Моды иногда поставляют 16-битные стереосэмплы; движок их принимает, но они занимают больше памяти.
Три уровня подключения
Поиск ответа на вопрос «что звучит, когда выделен Командир ARM» идёт по такой цепочке:
FBI gamedata/sound.tdf sounds/
┌─────────────┐ ┌───────────────────────┐ ┌──────────────┐
│ units/ │ │ [ARM_COM] │ │ cmdsel1.wav │
│ armcom.fbi │ │ { │ │ │
│ │ ──▶ │ select1=cmdsel1; │ ──▶│ │
│ Sound │ │ ok1=cmdok1; │ │ │
│ Category= │ │ ... │ │ │
│ ARM_COM; │ │ } │ │ │
└─────────────┘ └───────────────────────┘ └──────────────┘
1. FBI picks 2. sound.tdf maps 3. WAV file
a category event → filename on disk
Уровень 1 — SoundCategory в FBI
FBI юнита называет категорию:
[UNITINFO]
{
UnitName=ARMCOM;
SoundCategory=ARM_COM; // ← points at [ARM_COM] in sound.tdf
...
}
Категории общие для нескольких юнитов: все варианты Командира ARM или все К-боты ARM указывают на одну и ту же категорию, чтобы голоса при выделении звучали одинаково в пределах стороны.
Уровень 2 — gamedata/sound.tdf
Этот TDF связывает события движка с именами файлов WAV внутри категории:
[ARM_COM]
{
select1=cmdsel1; // Selecting the unit
ok1=cmdok1; // Movement order acknowledged
arrived1=cmdarvd1; // Reached destination
cant1=cantdo4; // Order rejected ("I can't do that")
underattack=warning1; // Took damage
count5=count1; // Commander self-destruct countdown (5)
count0=count6; // …countdown (now)
canceldestruct=cancel2;
}
Обратите внимание на суффикс 1 у большинства имён событий. У
каждого события может быть целое семейство вариантов: ключ без номера
(select) и нумерованные ключи select1, select2, select3, …;
движок для разнообразия выбирает один из них случайно. Если определён
только select1, каждый раз звучит одна и та же реплика.
Для каждого события TA 3.1c читает ключ без номера, если он есть, затем
KEY1, KEY2, … до первого пропущенного номера: при
select1=kbarmsel; select3=kbarmse2; звучит только kbarmsel, потому что
отсутствующий select2 обрывает список. (Отсутствие ключа без номера
нумерованные ключи не останавливает.) Пустое значение — это вариант
«тишина». Ключи, которых нет среди перечисленных ниже событий, никогда не
воспроизводятся.
Уровень 3 — sounds/<name>.wav
Значение в TDF — это основа имени (без расширения .wav). Движок
ищет sounds/<stem>.wav в виртуальной файловой системе.
Important
Суффикс .wav подразумевается. Если написать в TDF
select1=cmdsel1.wav, движок будет искать sounds/cmdsel1.wav.wav и
молча ничего не воспроизведёт.
Стандартные ключи событий
TA 3.1c читает из звуковой категории юнита 23 события, каждое — как ключ
без номера плюс описанное выше нумерованное семейство (ok, ok1,
ok2, …):
| Событие | Когда срабатывает |
|---|---|
select |
Юнит выделен. |
underattack |
Юнит получает урон. |
activate / deactivate |
Включение/выключение (радар, глушитель, укрепления). |
ok |
Приказ принят. |
arrived |
Юнит завершил перемещение. |
cant |
Приказ отклонён (рельеф, очередь строительства и т. п.). |
unitcomplete |
Юнит достроен. |
build |
Строитель начинает строить. |
repair |
Строитель начинает ремонт. |
working |
Строитель утилизирует или воскрешает. |
load / unload |
Транспорт берёт / высаживает юнит. |
cloak / uncloak |
Юнит включает / снимает маскировку (Командиры). |
capture |
Командир или юнит, способный захватывать, начинает захват. |
count5 … count0 |
Тики отсчёта самоуничтожения. |
canceldestruct |
Самоуничтожение отменено. |
У каждого ключа может быть парная запись KEYtext (select1text) с
субтитром реплики. Остальные ключи категории игнорируются.
Просмотрщик юнитов и песочница KBot Studio следуют тем же правилам:
метаданные юнита (/api/studio/unit/{name}) содержат ровно те ключи,
которые игра воспроизводит для этих событий, и каждое событие
воспроизводит случайный из своих ключей.
Звуки интерфейса — allsound.tdf
События интерфейса (щелчки кнопок, переходы между меню, короткие звуки в
конце игры) задаются ключами так же, но живут в секциях вида
[GLOBAL_*] файла gamedata/allsound.tdf:
[BIGBUTTON] { sound=butmain1; }
[SMLBUTTON] { sound=button1; }
[SKIRMISH] { sound=butnskir; }
[BGM] { sound=drone2; } // Background music ID
На эти секции по имени ссылаются файлы меню .gui. Чтобы сменить звук
щелчка кнопки «Схватка», достаточно отредактировать этот TDF — править
.gui не нужно.
Звуки оружия
TDF оружия (TDF) содержат собственные звуковые ключи напрямую, без уровня косвенности:
[LIGHTLASER] {
...
soundstart=lasrmas1; // On fire
soundhit=lasrhit1; // On impact
soundwater=splshbig; // On water hit (overrides soundhit)
soundtrigger=1; // Play soundstart on each burst pulse, not just first
}
Поиск sounds/<stem>.wav работает так же. Звуки оружия настраиваются
под каждый выстрел — если вы меняете оружие юнита, уровни звука в TDF
оружия тоже придётся подстроить.
Разбор примера — новая реплика при выделении
Положите новый WAV в
sounds/(рекомендуется моно, 22050 Гц, 8 бит):mymod/sounds/cmdsel_grunt.wavДобавьте новое событие в
gamedata/sound.tdf:[ARM_COM] { select1=cmdsel1; // Existing select2=cmdsel_grunt; // Your new line, randomly selected }Менять FBI не нужно — существующей ссылки
SoundCategory=ARM_COMдостаточно.Упакуйте и проверьте:
kbot hpi pack ./mymod --target mymod.ufo
Теперь при выделении Командира движок будет чередовать cmdsel1.wav и
cmdsel_grunt.wav.
Типичные размеры
| Ресурс | Диапазон в ресурсах Cavedog |
|---|---|
| Голосовая реплика юнита | 5–60 КБ |
| Попадание оружия | 5–30 КБ |
| Взрыв | 30–120 КБ |
| Музыкальная петля | 100 КБ – 1 МБ |
gamedata/sound.tdf |
~20 КБ (300+ категорий) |
gamedata/allsound.tdf |
~6 КБ |
Подводные камни
Warning
Отсутствующий WAV — это тишина, а не ошибка. Опечатайтесь в
select1=cmsdel1 (переставлены буквы), и движок просто ничего не
воспроизведёт при выделении — ни сообщения в журнале, ни замены.
Изменённые звуки всегда проверяйте в игре.
- Расширение
.wavподразумевается — никогда не пишите его в значении TDF. - Частота дискретизации важна. Звуки с частотой, отличной от 8 кГц / 11,025 кГц / 22,05 кГц / 44,1 кГц, могут заикаться на аппаратных путях эпохи Windows 9x, которыми всё ещё пользуются некоторые оригинальные движки. 22050 Гц моно — надёжный вариант по умолчанию.
- Стерео-WAV движок сводит в моно. Не поставляйте стерео, если у вас нет особой причины, связанной с пространственным звуком.
- MP3 в
sounds/— здесь движок MP3 игнорирует. У музыкального проигрывателя отдельный путь в коде дляmusic/*.mp3. - Cavedog поставляет некоторые WAV в 16-битном PCM и со странными частотами дискретизации (например, 7000 Гц) — они всё равно работают, но если ваш инструмент рассчитывает на 22050/8/моно, вы на них споткнётесь.
См. также
- TDF — формат, в котором записаны
sound.tdf,allsound.tdfи звуковые поля оружия. - Интерфейс TA: Kingdoms — виджеты
.guiссылаются на звуковые события интерфейса. - Глоссарий — sound category (звуковая категория).