mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-19 12:15:31 +02:00
+47
-7
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user