100 lines
2.7 KiB
Lua
100 lines
2.7 KiB
Lua
local task = require "lib.utils.task"
|
||
local ease = require "lib.utils.easing"
|
||
|
||
local EFFECTS_SUPPORTED = love.audio.isEffectsSupported()
|
||
|
||
--- @alias SourceFilter { type: "bandpass"|"highpass"|"lowpass", volume: number, highgain: number, lowgain: number }
|
||
|
||
--- @class Audio
|
||
--- @field musicVolume number
|
||
--- @field soundVolume number
|
||
--- @field looped boolean
|
||
--- @field from love.Source?
|
||
--- @field to love.Source?
|
||
audio = {}
|
||
audio.__index = audio
|
||
|
||
--- здесь мы должны выгружать значения из файлика с сохранением настроек
|
||
local function new(musicVolume, soundVolume)
|
||
return setmetatable({
|
||
musicVolume = musicVolume,
|
||
soundVolume = soundVolume,
|
||
looped = true
|
||
}, audio)
|
||
end
|
||
|
||
function audio:update(dt)
|
||
if self.fader then
|
||
local t = self.fader.value
|
||
if self.from then self.from:setVolume(self.musicVolume * (1 - t)) end
|
||
if self.to then self.to:setVolume(self.musicVolume * t) end
|
||
end
|
||
end
|
||
|
||
--- if from is nil, than we have fade in to;
|
||
--- if to is nil, than we have fade out from
|
||
---
|
||
--- also we should guarantee, that from and to have the same volume
|
||
--- @param from love.Source
|
||
--- @param to love.Source
|
||
--- @param ms number? in milliseconds
|
||
function audio:crossfade(from, to, ms)
|
||
print("[Audio]: Triggered crossfade")
|
||
|
||
-- Stop previous 'from' if it's dangling to avoid leaks
|
||
if self.from and self.from ~= from and self.from ~= to then
|
||
self.from:stop()
|
||
end
|
||
|
||
self:play(to)
|
||
to:setVolume(0)
|
||
self.from = from
|
||
self.to = to
|
||
|
||
-- Reuse fader object to allow task cancellation
|
||
if not self.fader then self.fader = { value = 0 } end
|
||
self.fader.value = 0
|
||
|
||
task.tween(self.fader, { value = 1 }, ms or 1000, ease.easeOutCubic)(function()
|
||
if self.from then
|
||
self.from:setVolume(0)
|
||
self.from:stop()
|
||
end
|
||
if self.to then
|
||
self.to:setVolume(self.musicVolume)
|
||
end
|
||
self.fader = nil
|
||
print("[Audio]: Crossfade done")
|
||
end)
|
||
end
|
||
|
||
--- @param source love.Source
|
||
--- @param settings SourceFilter?
|
||
--- @param effectName string?
|
||
function audio:play(source, settings, effectName)
|
||
if source:getType() == "stream" then
|
||
source:setLooping(self.looped)
|
||
source:setVolume(self.musicVolume)
|
||
source:play()
|
||
else
|
||
source:setVolume(self.soundVolume)
|
||
source:play()
|
||
end
|
||
if settings and EFFECTS_SUPPORTED then
|
||
source.setFilter(source, settings)
|
||
end
|
||
if effectName and EFFECTS_SUPPORTED then
|
||
source:setEffect(effectName, true)
|
||
end
|
||
end
|
||
|
||
function audio:setMusicVolume(volume)
|
||
self.musicVolume = volume
|
||
end
|
||
|
||
function audio:setSoundVolume(volume)
|
||
self.soundVolume = volume
|
||
end
|
||
|
||
return { new = new }
|