206 lines
11 KiB
Markdown
206 lines
11 KiB
Markdown
# Аудио
|
||
|
||
## Основные понятия
|
||
|
||
### Бекенд (Backend)
|
||
|
||
Вариант внутренней реализации звуковой подсистемы, управляющий выводом звука.
|
||
На данный момент в движке существует два:
|
||
- NoAudio - заглушка, используемая при невозможности инициализации OpenAL, либо, при отключенной через файл настроек, аудиосистеме: `[audio] enabled=false`. Данный бекенд загружает PCM данные только по требованию, не создает спикеров при попытке воспроизведения аудио.
|
||
- ALAudio - основной вариант. Вывод звука через OpenAL.
|
||
|
||
### Канал (Channel)
|
||
|
||
Определяет категорию источников аудио для регулирования громкости, наложения эффектов, паузы.
|
||
На данный момент существует следующий набор каналов:
|
||
- master - управляет громкостью остальных каналов. Не следует указывать как целевой канал при воспроизведении аудио.
|
||
- ui - звуки интерфейса
|
||
- regular - звуки игрового мира, ставятся на паузу вместе с игрой.
|
||
- ambient - то же, что и regular, но предназначается для фоновых звуков: погода и иной эмбиент.
|
||
- music - канал для воспроизведения музыки. Как правило, потокового аудио.
|
||
|
||
Каналы управляются самим движком.
|
||
### Спикер (Speaker)
|
||
|
||
Одноразовый контроллер проигрываемого аудио: звука или потока. Спикер уничтожается после остановки через вызов метода **stop** или при окончании аудио (поток также не удерживает спикер от уничтожения).
|
||
Контроллер продолжает жить при паузе.
|
||
|
||
> [!NOTE]
|
||
Доступ к спикерам производится по целочисленным id, которые не повторяются за время работы движка, следует избегать хранения прямых указателей на объекты класса.
|
||
|
||
Нумерация ID спикеров начинается с 1. ID 0 означает невозможность воспроизведения, по какой-либо причине.
|
||
### Звук (Sound)
|
||
|
||
Звуковые данные загруженные в память для возможности одновременного воспроизведения из нескольких источников. Может предоставлять доступ к PCM данным.
|
||
|
||
### Источник PCM (PCMStream)
|
||
|
||
Поток, используемый потоком как источник PCM-данных. Реализация зависит не от бекенда звуковой системы, а от формата файла. Реализация потокового аудио из сетевого соединения делается через реализацию данного интерфейса.
|
||
|
||
### Поток (Stream)
|
||
|
||
Потоковое аудио. Не загружается полностью в память, поэтому не требует предзагрузки через `preload.json`. Не может воспроизводиться через несколько спикеров одновременно.
|
||
|
||
## Поддержка форматов
|
||
|
||
На данный момент реализована поддержка двух форматов.
|
||
- WAV: поддерживаются 8 и 16 bit (24 bit не поддерживается OpenAL)
|
||
- OGG: реализовано через библиотеку libvorbis
|
||
|
||
|
||
## Дополнительно
|
||
|
||
> [!WARNING]
|
||
> При воспроизведении через OpenAL стерео звуки не будут учитывать расположение источников относительно игрока. Звуки, которые должны учитывать расположение, должны быть в моно.
|
||
|
||
## API аудио в скриптинге
|
||
|
||
### Воспроизведение аудио
|
||
|
||
Работа с аудио производится с библиотекой `audio`.
|
||
|
||
```lua
|
||
audio.play_stream(
|
||
-- путь к аудио-файлу (без точки входа, но с указанием расширения)
|
||
name: string,
|
||
-- позиция источника аудио в мире
|
||
x: number, y: number, z: number,
|
||
-- громкость аудио (от 0.0 до 1.0)
|
||
volume: number
|
||
-- скорость воспроизведения (положительное число)
|
||
pitch: number,
|
||
-- [опционально] имя канала: regular/ambient/music/ui (по-умолчанию - regular)
|
||
channel: string,
|
||
-- [опционально] зацикливание потока (по-умолчанию - false)
|
||
loop: bool
|
||
) -> int
|
||
```
|
||
|
||
Воспроизводит потоковое аудио из указанного файла, на указанной позиции в мире. Возвращает id спикера.
|
||
|
||
```lua
|
||
audio.play_stream_2d(
|
||
-- путь к аудио-файлу (без точки входа, но с указанием расширения)
|
||
name: string,
|
||
-- громкость аудио (от 0.0 до 1.0)
|
||
volume: number
|
||
-- скорость воспроизведения (положительное число)
|
||
pitch: number,
|
||
-- [опционально] имя канала: regular/ambient/music/ui (по-умолчанию - regular)
|
||
channel: string,
|
||
-- [опционально] зацикливание потока (по-умолчанию - false)
|
||
loop: bool
|
||
) -> int
|
||
```
|
||
|
||
Воспроизводит потоковое аудио из указанного файла. Возвращает id спикера.
|
||
|
||
|
||
```lua
|
||
audio.play_sound(
|
||
-- название загруженного звука без префикса пака, "sounds/", номера варианта и расширения
|
||
-- пример "steps/stone" для проигрывания звука, загруженного из "sounds/steps/stone.ogg" или любого из его вариантов
|
||
-- вариант звука выбирается случайно
|
||
name: string,
|
||
-- позиция источника аудио в мире
|
||
x: number, y: number, z: number,
|
||
-- громкость аудио (от 0.0 до 1.0)
|
||
volume: number
|
||
-- скорость воспроизведения (положительное число)
|
||
pitch: number,
|
||
-- [опционально] имя канала: regular/ambient/music/ui (по-умолчанию - regular)
|
||
channel: string,
|
||
-- [опционально] зацикливание потока (по-умолчанию - false)
|
||
loop: bool
|
||
) -> int
|
||
```
|
||
|
||
Воспроизводит звук на указанной позиции в мире. Возвращает id спикера.
|
||
|
||
```lua
|
||
audio.play_sound_2d(
|
||
-- название загруженного звука без префикса пака, "sounds/", номера варианта и расширения
|
||
-- пример "steps/stone" для проигрывания звука, загруженного из "sounds/steps/stone.ogg" или любого из его вариантов
|
||
-- вариант звука выбирается случайно
|
||
name: string,
|
||
-- громкость аудио (от 0.0 до 1.0)
|
||
volume: number
|
||
-- скорость воспроизведения (положительное число)
|
||
pitch: number,
|
||
-- [опционально] имя канала: regular/ambient/music/ui (по-умолчанию - regular)
|
||
channel: string,
|
||
-- [опционально] зацикливание потока (по-умолчанию - false)
|
||
loop: bool
|
||
) -> int
|
||
```
|
||
|
||
Воспроизводит звук. Возвращает id спикера.
|
||
|
||
### Взаимодействие со спикером.
|
||
|
||
При обращении к несуществующим спикером ничего происходить не будет.
|
||
|
||
```lua
|
||
-- остановить воспроизведение спикера
|
||
audio.stop(speakerid: integer)
|
||
|
||
-- поставить спикер на паузу
|
||
audio.pause(speakerid: integer)
|
||
|
||
-- снять спикер с паузы
|
||
audio.resume(speakerid: integer)
|
||
|
||
-- установить зацикливание аудио
|
||
audio.set_loop(speakerid: integer, state: bool)
|
||
|
||
-- проверить, зациклено ли аудио (false если не существует)
|
||
audio.is_loop(speakerid: integer) -> bool
|
||
|
||
-- получить громкость спикера (0.0 если не существует)
|
||
audio.get_volume(speakerid: integer) -> number
|
||
|
||
-- установить громкость спикера
|
||
audio.set_volume(speakerid: integer, volume: number)
|
||
|
||
-- получить скорость воспроизведения (1.0 если не существует)
|
||
audio.get_pitch(speakerid: integer) -> number
|
||
|
||
-- установить скорость воспроизведения
|
||
audio.set_pitch(speakerid: integer, pitch: number)
|
||
|
||
-- получить временную позицию аудио в секундах (0.0 если не существует)
|
||
audio.get_time(speakerid: integer) -> number
|
||
|
||
-- установить временную позицию аудио в секундах
|
||
audio.set_time(speakerid: integer, time: number)
|
||
|
||
-- получить позицию источника звука в мире (nil если не существует)
|
||
audio.get_position(speakerid: integer) -> number, number, number
|
||
|
||
-- установить позицию источника звука в мире
|
||
audio.set_position(speakerid: integer, x: number, y: number, z: number)
|
||
|
||
-- получить скорость движения источника звука в мире (nil если не существует)
|
||
-- (используется OpenAL для имитации эффекта Доплера)
|
||
audio.get_velocity(speakerid: integer) -> number, number, number
|
||
|
||
-- установить скорость движения источника звука в мире
|
||
-- (используется OpenAL для имитации эффекта Доплера)
|
||
audio.set_velocity(speakerid: integer, x: number, y: number, z: number)
|
||
|
||
-- получить длительность аудио в секуднах, проигрываемого источником
|
||
-- возвращает 0, если не спикер не существует
|
||
-- так же возвращает 0, если длительность неизвестна (пример: радио)
|
||
audio.get_duration(speakerid: integer) -> number
|
||
```
|
||
|
||
### Другие функции
|
||
|
||
```lua
|
||
-- получить текущее число живых спикеров
|
||
audio.count_speakers() -> integer
|
||
|
||
-- получить текущее число проигрываемых аудио-потоков
|
||
audio.count_streams() -> integer
|
||
```
|