111 lines
3.6 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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")
self:play(to)
to:setVolume(0)
self.from = from
self.to = to
-- Using a dummy object to tween a value from 0 to 1
local fade = { value = 0 }
task.tween(fade, { value = 1 }, ms or 1000, ease.easeOutCubic)(function()
self.from:setVolume(0)
self.to:setVolume(self.musicVolume)
self.from:stop()
print("[Audio]: Crossfade done")
end)
-- We need a custom update loop for the volume during the tween
-- Since task.tween updates properties, we can use a "monitor" task or just rely on `update` if we expose the task?
-- Actually, task.tween updates `fade.value` every frame.
-- We need to apply this value to the audio sources every frame.
-- BUT task.tween doesn't provide an "onUpdate" callback easily.
-- Workaround: create a task that runs every frame? Or modify task.tween?
-- Let's check task.lua... it updates properties on the target object.
-- So `fade.value` will change. We need to apply it.
-- We can hook into `update` or use a metatable on `fade`?
-- Let's use a "reactive" table with metatable setters? Overkill.
-- Simplest way: Add `onUpdate` to task.tween or just use `audio:update` to poll `fade.value`?
-- But `fade` is local.
-- Better approach: Tween `self` properties? No, volume is on Source userdate.
-- Let's add a `fader` object to `self` that we tween, and in `update` we apply it.
self.fader = { value = 0 }
task.tween(self.fader, { value = 1 }, ms or 1000, ease.easeOutCubic)(function()
self.fader = nil
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 }