diff --git a/Аудио.md b/Аудио.md new file mode 100644 index 0000000..2b5865e --- /dev/null +++ b/Аудио.md @@ -0,0 +1,179 @@ +# Основные понятия + +## Бекенд (Backend) + +Вариант внутренней реализации звуковой подсистемы, управляющий выводом звука. +На данный момент в движке существует два: +- NoAudio - заглушка, используемая при невозможности инициализации OpenAL, либо, при отключенной через файл настроек, аудиосистеме: `audio=false`. Данный бекенд загружает PCM данные только по требованию, не создает спикеров при попытке воспроизведения аудио. +- ALAudio - основной вариант. Вывод звука через OpenAL. + +## Спикер (Speaker) + +Одноразовый контроллер проигрываемого аудио: звука или потока. Спикер уничтожается после остановки через вызов метода **stop** или при окончании аудио (поток также не удерживает спикер от уничтожения). +Контроллер продолжает жить при паузе. + +> [!NOTE] +Доступ к спикерам производится по целочисленным id, которые не повторяются за время работы движка, следует избегать хранения прямых указателей на объекты класса. + +Нумерация ID спикеров начинается с 1. ID 0 означает невозможность воспроизведения, по какой-либо причине. +## Звук (Sound) + +Звуковые данные загруженные в память для возможности одновременного воспроизведения из нескольких источников. Может предоставлять доступ к PCM данным. + +## Источник PCM (PCMStream) + +Поток, используемый потоком как источник PCM-данных. Реализация зависит не от бекенда звуковой системы, а от формата файла. Реализация потокового аудио из сетевого соединения делается через реализацию данного интерфейса. + +## Поток (Stream) + +Потоковое аудио. Не может воспроизводиться через несколько спикеров одновременно. + +# Поддержка форматов + +На данный момент реализована поддержка двух форматов. +- 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( + -- название загруженного звука + 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( + -- название загруженного звука + 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 +``` +