dagon:audio
В новой версии Dagon будет встроенный звуковой движок на основе SoLoud — расширение dagon:audio. Поясню для тех, кто не знает: SoLoud — это библиотека-микшер с поддержкой 3D-звука и базовых потоковых форматов (WAV, MP3, OGG, FLAC), а также трекерных форматов через OpenMPT. Есть частотные фильтры и встроенные синтезаторы — в частности, текстово-речевой преобразователь, SFXR, эмулятор VIC-20 и генератор разных видов шума. SoLoud поддерживает множество бэкендов, и по дефолту работает на основе SDL2, как и сам Dagon (пользователь, однако, может выбрать конкретный бэкенд через опцию audio.backend в settings.conf). Короче говоря, это своего рода «FMOD от мира OpenSource». Особо отмечу удобный API и, более того, прямо из коробки — обертка для D, позволяющая писать в объектно-ориентированном стиле.
SoLoud можно было и раньше использовать в приложениях Dagon с использованием BindBC-SoLoud, но dagon:audio упрощает работу со звуком в играх еще больше, предоставляя удобный механизм привязки 3D-слушателя и пространственных звуков SoLoud к объектам движка. Для этого я ввел менеджер AudioManager и компонент SoundComponent:
class MyGame: Game
{
AudioManager audioManager;
this(uint windowWidth, uint windowHeight, bool fullscreen,
string title, string[] args)
{
super(windowWidth, windowHeight, fullscreen, title, args);
audioManager = New!AudioManager(this);
currentScene = New!TestScene(this);
}
}
class TestScene: Scene
{
AudioManager audio;
SoundComponent cubeSpeaker;
WavStream music;
this(MyGame game)
{
super(game);
this.audio = game.audioManager;
}
override void afterLoad()
{
Camera camera = addCamera();
camera.position = Vector3f(0.0f, 1.8f, 5.0f);
game.renderer.activeCamera = camera;
audio.listener = camera;
auto eCube = addEntity();
eCube.position = Vector3f(0, 1, 0);
cubeSpeaker = audio.addSoundTo(eCube);
music = audio.loadMusic("data/music/song.mp3");
cubeSpeaker.play(music);
}
override void onUpdate(Time t)
{
audio.update(t);
}
}
Позиция и ориентация слушателя и позиция источника звука обновляются автоматически в update.
Есть также класс PlaylistPlayer для управления плейлистами. Он упрощает загрузку множества аудиофайлов из папки и переключение между ними — полезно для автоматического воспроизведения фоновых мелодий одну за другой.
PlaylistPlayer pl = audio.addPlaylistPlayer();
pl.addTracksFromDirectory("data/music");
pl.play(0);
SoundComponent и PlaylistPlayer совместимы между собой:
cubeSpeaker.playlistPlayer = pl;
cubeSpeaker.play(0);