Potentially CLOSES #1310, CLOSES #1005, CLOSES #1291

This commit is contained in:
bryanthaboi
2026-08-18 15:49:47 -04:00
parent 7583ba8729
commit 99806ead25
1216 changed files with 264324 additions and 147175 deletions
+47 -7
View File
@@ -66,6 +66,8 @@ local pendingBuf -- a current-gen buffer popped from the worker but not yet
-- the jingle ends.
local musicHeld = false
local suspended = false
-- ---------------------------------------------------------------------------
-- worker management
-- ---------------------------------------------------------------------------
@@ -150,12 +152,15 @@ local MUSIC_FILL_INITIAL = 4
local MUSIC_FILL_PER_CALL = 3
local function fillSync(limit)
if suspended then return end
local music = currentMusic
if not music or not music.engine or music.engine:finished() then return end
limit = limit or MUSIC_FILL_PER_CALL
local free = music.source:getFreeBufferCount()
local ok, free = pcall(music.source.getFreeBufferCount, music.source)
if not ok or type(free) ~= "number" then return end
while free > 0 and limit > 0 and not music.engine:finished() do
music.source:queue(ChipSynth.soundData(music.engine, MUSIC_BUFFER_SAMPLES, 2))
local sd = ChipSynth.soundData(music.engine, MUSIC_BUFFER_SAMPLES, 2)
if not pcall(music.source.queue, music.source, sd) then return end
free = free - 1
limit = limit - 1
end
@@ -235,7 +240,8 @@ local function updateThreaded()
return
end
while true do
local free = m.source:getFreeBufferCount()
local okFree, free = pcall(m.source.getFreeBufferCount, m.source)
if not okFree or type(free) ~= "number" then return end
local buf = pendingBuf
if buf then pendingBuf = nil else buf = outCh:pop() end
if not buf then break end
@@ -251,7 +257,7 @@ local function updateThreaded()
m.finished = true
elseif buf.sd then
if free > 0 then
m.source:queue(buf.sd)
if not pcall(m.source.queue, m.source, buf.sd) then return end
else
pendingBuf = buf -- Source full; hold this one for next frame
break
@@ -259,7 +265,9 @@ local function updateThreaded()
end
end
if not m.started and not musicHeld then
if (MUSIC_BUFFER_COUNT - m.source:getFreeBufferCount()) > 0 then
local okFree, free = pcall(m.source.getFreeBufferCount, m.source)
if okFree and type(free) == "number"
and (MUSIC_BUFFER_COUNT - free) > 0 then
pcall(function() m.source:play() end)
m.started = true
end
@@ -267,6 +275,7 @@ local function updateThreaded()
end
function ChipAudio.update()
if suspended then return end
local m = currentMusic
if not m then return end
if m.threaded then
@@ -280,13 +289,16 @@ end
-- Music has handled intentional fanfare pauses, so it never fights the normal
-- pause/resume behavior.
function ChipAudio.ensureMusicPlaying()
if suspended then return end
local m = currentMusic
if not m or m.finished or musicHeld then return end
if m.threaded then
if not m.started then return end
local ok, playing = pcall(function() return m.source:isPlaying() end)
if ok and not playing
and (MUSIC_BUFFER_COUNT - m.source:getFreeBufferCount()) > 0 then
if not ok or playing then return end
local okFree, free = pcall(m.source.getFreeBufferCount, m.source)
if okFree and type(free) == "number"
and (MUSIC_BUFFER_COUNT - free) > 0 then
pcall(function() m.source:play() end)
end
else
@@ -366,6 +378,34 @@ function ChipAudio.currentSource()
return currentMusic and currentMusic.source
end
function ChipAudio.setSuspended(flag)
suspended = not not flag
end
function ChipAudio.isSuspended()
return suspended
end
function ChipAudio.rebuildPlayback()
local m = currentMusic
if not m then return true end
if not (love.audio and love.audio.newQueueableSource) then return false end
local ok, source = pcall(
love.audio.newQueueableSource, SAMPLE_RATE, 16, 2, MUSIC_BUFFER_COUNT)
if not ok or not source then return false end
pendingBuf = nil
local old = m.source
m.source = source
m.started = false
if old then pcall(old.stop, old) end
if not m.threaded then
fillSync(MUSIC_FILL_INITIAL)
if not musicHeld then pcall(source.play, source) end
m.started = true
end
return true
end
function ChipAudio.setStereo(enabled)
enabled = not not enabled
if ChipSynth.getStereo() == enabled then return end
+23
View File
@@ -65,6 +65,8 @@ state = {
fade = nil, -- active volume-ramp fade-out (see Music.fadeOut)
tempo = nil, -- alternate-tempo override in force for `current`
start = nil,
data = nil,
loop = nil,
failed = {}, -- labels whose def could not be started; logged once
}
@@ -319,6 +321,8 @@ function Music.play(data, song, loop, ctx)
state.current = song
state.tempo = tempo
state.start = start
state.data = data
state.loop = loop
if Runtime.wants("music.started") then
Runtime.emit("music.started", {
song = song, previous = previous, chip = isChip,
@@ -334,6 +338,7 @@ function Music.stop()
require("src.core.ChipAudio").stopMusic()
state.current, state.source, state.loopSource, state.fade = nil, nil, nil, nil
state.tempo, state.start = nil, nil
state.data, state.loop = nil, nil
state.chip = false
state.pendingRestore = nil
if previous and Runtime.wants("music.stopped") then
@@ -521,6 +526,24 @@ function Music.applyOptions(opts)
end
end
function Music.onDeviceReset()
if not love.audio then return end
if state.chip then
local src = require("src.core.ChipAudio").currentSource()
if not src then return end
state.source = src
applyVolume(src)
applyFilter(src)
return
end
local data, song = state.data, state.current
if not (data and song) then return end
local loop, tempo, start = state.loop, state.tempo, state.start
state.current = nil
Music.play(data, song, loop, { reason = "devicereset", selected = true,
tempo = tempo, start = start })
end
local function sourceStopped(src)
if not src then return false end
local ok, playing = pcall(src.isPlaying, src)
+6 -2
View File
@@ -169,8 +169,8 @@ local function playPath(data, key, def, pitch, tempo, plain)
cache[key] = s
src = s
end
src:stop()
src:play()
pcall(src.stop, src)
pcall(src.play, src)
return src
end
@@ -817,6 +817,10 @@ end
-- def is re-resolved on the next play (20 §2 cache contract, audio row)
Assets.register(Sound.invalidate)
function Sound.onDeviceReset()
Sound.invalidate()
end
-- re-apply persisted audio options (Game calls this on boot and after
-- loading a save)
function Sound.applyOptions(opts)