FOnline Engine
Current master GitHub
Документация Docs/ru/how-to/content/audio.md

Аудиоресурсы и воспроизведение

Документация, принадлежащая движку. Это руководство описывает переиспользуемое запекание аудио, runtime-декодирование, воспроизведение, позиционирование, микширование и проверку в cvet/fonline. Игра отвечает за каталог звуков, сопоставление понятий с путями, автомат состояний музыки, пространственную политику, мастеринг, лицензии и слышимую приёмку.

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

Карта исходников

  • Source/Tools/AudioBaker.* принимает авторские WAV и Ogg, проверяет вход и выдаёт payload Ogg Vorbis, сохраняя авторский путь ресурса.
  • Source/Client/AudioManager.* индексирует пути и отвечает за декодирование, streaming, handles, позиционирование, повтор, остановку и текущее состояние громкости.
  • Source/Scripting/ClientGlobalScriptMethods.cpp экспортирует Game.PlaySound, Game.UpdateSound и Game.PlayMusic.
  • Source/Frontend/Application.* отвечает за SDL-аудиоустройство, преобразование, микширование и синхронизацию callback; ApplicationHeadless.cpp задаёт headless-границу без аудио.
  • Source/Common/Settings.inc владеет неизменяемыми начальными настройками.
  • Source/Tests/Test_AudioBaker.cpp и Test_AudioManager.cpp исполняют сфокусированный нативный контракт.
  • BuildTools/AudioInterface.json является проверяемым контрактом документации.

Поддерживаемые ресурсы

Граница авторинга принимает две формы исходников:

Авторский суффикс Допустимый вход Результат baker Runtime-декодер
.wav RIFF/WAVE PCM с разрядностью 8, 16, 24 или 32 бита; IEEE float с разрядностью 32 бита Нормализация в interleaved signed 16-bit и кодирование в Ogg Vorbis libvorbisfile
.ogg Битовый поток Ogg с аудио Vorbis Проверка и копирование без ещё одного прохода с потерями libvorbisfile

Runtime-пути ACM больше нет. MP3, FLAC, Opus, AAC, произвольные форматы SDL и контейнеры Ogg с кодеком, отличным от Vorbis, не поддерживаются.

Авторский суффикс обозначает путь исходника, а не байты после запекания. Ресурс Sfx/Door.wav сохраняет этот путь, но его payload становится Vorbis. Поэтому runtime использует один декодер и для сохранённых путей .wav, и для нативных путей .ogg; кодек не выбирается по суффиксу.

Доставка аудио

Включайте baker Audio в каждый ресурсный пакет с клиентским аудио:

[ResourcePack]
Name = Sound
InputDirs = Resources/Sound
IncludePatterns = **
ClientOnly = True
Bakers = Audio

Аудио больше не относится к семейству RawCopy. WAV преобразуется с качеством Baking.AudioVorbisQuality, а авторский Ogg проверяется перед passthrough. Оба маршрута подтверждают, что результат открывается как Vorbis. Baker сообщает число кодированных и скопированных ресурсов и суммарные входные/выходные байты.

AudioManager.IndexFiles() записывает пути с суффиксами из Audio.SoundFileExtensions (обычно wav ogg). Каталог нужен для инспекции; само воспроизведение получает точный путь выбранного ресурса.

Воспроизведение эффектов

Game.PlaySound(path) возвращает непереиспользуемый uint32 handle времени жизни:

uint sound = Game.PlaySound("Sfx/DoorOpen.wav");
if (sound == 0) {
    // No live sound was started.
}

Передавайте точный путь запечённого ресурса с авторским расширением и регистром. Fallback расширения, нормализации основы в нижний регистр и автоматического поиска по понятию нет.

Нумерованные варианты

Движок не обнаруживает и не выбирает случайно нумерованные варианты. Если игра содержит Footstep_1.wav — Footstep_4.wav, проектный код сам выбирает вариант и передаёт точный путь. Так политика каталога и рандомизации остаётся за пределами переиспользуемого mixer.

Позиционированное воспроизведение

Если у звука есть текущее положение, используйте overload с attenuation и pan:

uint sound = Game.PlaySound("Sfx/Generator.wav", attenuation, pan);
  • attenuation не больше нуля возвращает нулевой handle до файлового ввода;
  • pan ограничивается диапазоном -1..1: отрицательное значение ослабляет правый канал, положительное — левый;
  • ближний канал остаётся с единичным усилением, поэтому панорамирование не усиливает сигнал до clipping.

При движении источника или listener обновляйте существующий экземпляр:

bool alive = Game.UpdateSound(sound, attenuation, pan);

false означает нулевой handle, неактивное аудио или завершившееся воспроизведение. Handles никогда не переиспользуются, поэтому устаревший handle не попадёт в более поздний звук. Кривые расстояния, выбор listener, occlusion и фильтрация получателей остаются политикой проекта.

Воспроизведение музыки

Game.PlayMusic(path, repeatTime) принимает точный путь. Пустой путь останавливает текущую музыку и возвращает успех. Новая композиция останавливает существующую до загрузки замены; ошибка замены не восстанавливает старую.

Активна только одна музыкальная группа. Музыка не использует поиск по понятию или fallback суффикса.

Интервал повтора

Нулевой repeatTime означает однократное воспроизведение. Ненулевое значение сохраняет объект и перезапускает его после завершения:

  • значения больше одной миллисекунды добавляют указанную задержку;
  • значения не больше одной миллисекунды повторяют немедленно;
  • сохранённые потоки Vorbis перед повтором перематываются к нулевой позиции.

Интервал начинается после окончания воспроизведения: это пауза, а не период, включающий продолжительность композиции.

Детали форматов

Авторинг WAV

AudioBaker обходит RIFF-чанки в любом порядке, пропускает неизвестные, проверяет границы и учитывает выравнивание нечётного размера. Требуются один пригодный чанк fmt и непустой data. Поддерживаются PCM (1) с разрядностью 8/16/24/32 бита и IEEE float (3) с разрядностью 32 бита. Число каналов и частота должны быть положительными, выравнивание блока — соответствовать форме кадра, а обрезанный кадр приводит к ошибке запекания.

Каждый принятый sample нормализуется в signed 16-bit PCM до кодирования Vorbis. Проверяйте точный экспортированный исходник: неверные метаданные остаются ошибкой авторинга, даже если редактор способен воспроизвести файл.

Runtime Ogg Vorbis

Авторский Ogg и сгенерированный результат открываются через libvorbisfile во время запекания. В runtime AudioManager открывает каждый аудиоресурс как Vorbis и декодирует начальную порцию 64 KiB на native либо 128 KiB на Web. Короткие файлы становятся резидентными; длинные сохраняют OggStream и продолжают декодирование из audio callback.

Преобразование устройства и микширование

AppAudio::ConvertAudio преобразует декодированные каналы, частоту и формат в формат активного устройства SDL. Callback начинает с тишины, запрашивает у AudioManager активные данные, применяет per-instance attenuation и pan, затем микширует их с текущей громкостью звуков или музыки.

Audio.SoundVolume и Audio.MusicVolume — неизменяемые начальные значения. Для изменений в runtime используйте Game.SetSoundVolume и Game.SetMusicVolume; frontend ограничивает каждое микширование диапазоном 0..100.

Операции play, stop и обновления позиции синхронизируются lock аудиоустройства. Нативные расширения не должны изменять хранилище mixer из callback.

Отключённое аудио и headless

Audio.DisableAudio = true, недоступное устройство SDL и headless/stub frontend оставляют аудио неактивным. Тогда PlayMusic является успешной no-op операцией, а PlaySound возвращает нулевой handle.

Эти результаты не являются проверкой существования ресурса. Запекание подтверждает путь и payload, а видимый клиент с активным устройством — преобразование, планирование callback, микширование и слышимый вывод.

Рекомендуемая проектная практика

  1. Помещайте авторские WAV/Ogg в клиентский пакет с baker Audio.
  2. Храните точные пути в проектных каталогах; разрешайте понятия и варианты до вызова движка.
  3. Используйте WAV как редактируемый/master-вход, а нативный Ogg — когда важно избежать ещё одного кодирования с потерями.
  4. Централизуйте кривые расстояния, выбор listener, ambient, cooldown и музыкальные переходы в проектном коде.
  5. Отделяйте сервер-авторитетные игровые решения от локального воспроизведения.
  6. Храните masters, licenses, attribution и разрешение на распространение вне запечённого вывода.
  7. Проверяйте репрезентативные ресурсы и движение позиционированного звука на каждой поддерживаемой платформе.

Диагностика

Считайте все исключения AudioBaker ошибками контента. Обычные причины: отсутствующий или обрезанный RIFF-чанк, неподдерживаемая кодировка/разрядность WAV, несогласованное выравнивание, пустой Ogg или поток Ogg без Vorbis.

В runtime ошибки открытия/декодирования Ogg и преобразования устройства пишутся в лог и входят в debugger. Нулевой handle говорит только об отсутствии живого эффекта и не заменяет гейт baker.

Процесс проверки

Запустите документационные и сфокусированные нативные проверки:

python BuildTools\docs_audio.py --check
python -m pytest BuildTools\tests\test_docs_audio.py
cmake --build <build-dir> --config RelWithDebInfo --target RunUnitTests

Test_AudioBaker покрывает преобразование PCM/float WAV, passthrough нативного Ogg и ошибочные входы. Test_AudioManager покрывает вывод decoder/mixer, pan, позиционированный запуск, текущие обновления, истечение handles и поведение, важное для синхронизации.

Затем запеките реальный пакет встраиваемого проекта. Проверьте сохранённые пути, счётчики baker и открытие каждого результата как Vorbis. В видимом клиенте воспроизведите ресурс с WAV-путём и нативным Ogg-путём, переместите звук, замените музыку, проверьте немедленный/отложенный повтор и крайние значения громкости на каждой заявленной платформе.

Граница проекта

Встраиваемый проект владеет каталогами, понятиями, вариантами, маршрутизацией server/client, политикой расстояния и occlusion, ambient и состоянием музыки, бюджетами одновременности, loudness/accessibility, masters, licenses, attribution и слышимой приёмкой. Движок предоставляет запекание, единый путь декодера, клиентский mixer, handles и параметры позиционирования.

Сопровождение

Изменения допустимых входов, преобразования baker, сохранённых путей, streaming Vorbis, handles, позиционирования, повтора, script-сигнатур, текущей громкости, преобразования устройства, доставки package или headless-поведения требуют обновления документации. Обновите BuildTools/AudioInterface.json и это руководство, перегенерируйте справочник, запустите сфокусированные тесты и сводный contract diff, а для публичных изменений добавьте инструкции миграции.

Введите запрос.