fix(audio): 修复导致完全没有声音的回归错误,添加超时防止挂起,修复等待缓冲区清空的逻辑
This commit is contained in:
@@ -61,6 +61,7 @@ local function playDfpwmFile(path, volume)
|
|||||||
for _, sp in ipairs(speakers) do
|
for _, sp in ipairs(speakers) do
|
||||||
pending[peripheral.getName(sp)] = sp
|
pending[peripheral.getName(sp)] = sp
|
||||||
end
|
end
|
||||||
|
local maxAttempts = 20
|
||||||
while next(pending) do
|
while next(pending) do
|
||||||
for name, sp in pairs(pending) do
|
for name, sp in pairs(pending) do
|
||||||
if sp.playAudio(samples, volume) then
|
if sp.playAudio(samples, volume) then
|
||||||
@@ -68,6 +69,10 @@ local function playDfpwmFile(path, volume)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if next(pending) then
|
if next(pending) then
|
||||||
|
maxAttempts = maxAttempts - 1
|
||||||
|
if maxAttempts <= 0 then
|
||||||
|
break
|
||||||
|
end
|
||||||
local timerId = os.startTimer(0.05)
|
local timerId = os.startTimer(0.05)
|
||||||
while true do
|
while true do
|
||||||
local ev = { os.pullEvent() }
|
local ev = { os.pullEvent() }
|
||||||
|
|||||||
+21
-4
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
-- 1. Configuration & Constants
|
-- 1. Configuration & Constants
|
||||||
local APP_VERSION_TEXT = "v1.0.66"
|
local APP_VERSION_TEXT = "v1.0.67"
|
||||||
|
|
||||||
local CONFIG = {
|
local CONFIG = {
|
||||||
CLOUD_URL = "ws://stabadmin.fse-media.group",
|
CLOUD_URL = "ws://stabadmin.fse-media.group",
|
||||||
@@ -1216,12 +1216,17 @@ local function waitForNativeSpeakersEmpty(speakers, playSeq)
|
|||||||
if name then waiting[name] = true end
|
if name then waiting[name] = true end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local timerId = os.startTimer(2.0) -- Maximum 2 seconds wait for empty
|
||||||
while next(waiting) do
|
while next(waiting) do
|
||||||
if shouldStop(playSeq) then return false end
|
if shouldStop(playSeq) then return false end
|
||||||
local ev = { os.pullEvent() }
|
local ev = { os.pullEvent() }
|
||||||
if ev[1] == "audio_interrupt" and tonumber(ev[2]) and tonumber(ev[2]) >= playSeq then
|
if ev[1] == "audio_interrupt" and tonumber(ev[2]) and tonumber(ev[2]) >= playSeq then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
if ev[1] == "timer" and ev[2] == timerId then
|
||||||
|
Utils.log("WARN", "Timeout waiting for native speakers to empty")
|
||||||
|
break
|
||||||
|
end
|
||||||
if ev[1] == "speaker_audio_empty" and ev[2] and waiting[ev[2]] then
|
if ev[1] == "speaker_audio_empty" and ev[2] and waiting[ev[2]] then
|
||||||
waiting[ev[2]] = nil
|
waiting[ev[2]] = nil
|
||||||
end
|
end
|
||||||
@@ -1284,6 +1289,7 @@ local function playChunkOnSpeakers(samples, volume, playSeq, waitForDrain)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local usedNativePath = false
|
local usedNativePath = false
|
||||||
|
local maxAttempts = 20
|
||||||
while next(pending) do
|
while next(pending) do
|
||||||
if shouldStop(playSeq) then return false end
|
if shouldStop(playSeq) then return false end
|
||||||
for name, sp in pairs(pending) do
|
for name, sp in pairs(pending) do
|
||||||
@@ -1299,6 +1305,11 @@ local function playChunkOnSpeakers(samples, volume, playSeq, waitForDrain)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if next(pending) then
|
if next(pending) then
|
||||||
|
maxAttempts = maxAttempts - 1
|
||||||
|
if maxAttempts <= 0 then
|
||||||
|
Utils.log("WARN", "Speaker buffer full or failed, skipping chunk")
|
||||||
|
break
|
||||||
|
end
|
||||||
local timerId = os.startTimer(0.05)
|
local timerId = os.startTimer(0.05)
|
||||||
while true do
|
while true do
|
||||||
local ev = { os.pullEvent() }
|
local ev = { os.pullEvent() }
|
||||||
@@ -1319,6 +1330,7 @@ local function playChunkOnSpeakers(samples, volume, playSeq, waitForDrain)
|
|||||||
local controller = Peripherals.speakers[1]
|
local controller = Peripherals.speakers[1]
|
||||||
if controller and type(controller.playAudioAll) == "function" then
|
if controller and type(controller.playAudioAll) == "function" then
|
||||||
Utils.log("WARN", "Falling back to controller.playAudioAll for decoded samples")
|
Utils.log("WARN", "Falling back to controller.playAudioAll for decoded samples")
|
||||||
|
local maxAttempts = 20
|
||||||
while true do
|
while true do
|
||||||
if shouldStop(playSeq) then return false end
|
if shouldStop(playSeq) then return false end
|
||||||
local ok = false
|
local ok = false
|
||||||
@@ -1326,6 +1338,11 @@ local function playChunkOnSpeakers(samples, volume, playSeq, waitForDrain)
|
|||||||
ok = controller.playAudioAll(samples, volume)
|
ok = controller.playAudioAll(samples, volume)
|
||||||
end)
|
end)
|
||||||
if ok then break end
|
if ok then break end
|
||||||
|
maxAttempts = maxAttempts - 1
|
||||||
|
if maxAttempts <= 0 then
|
||||||
|
Utils.log("WARN", "Controller buffer full or failed, skipping chunk")
|
||||||
|
break
|
||||||
|
end
|
||||||
local timerId = os.startTimer(0.05)
|
local timerId = os.startTimer(0.05)
|
||||||
while true do
|
while true do
|
||||||
local ev = { os.pullEvent() }
|
local ev = { os.pullEvent() }
|
||||||
@@ -1765,7 +1782,7 @@ function Audio.playDfpwmItem(item)
|
|||||||
if chunk == nil then break end
|
if chunk == nil then break end
|
||||||
if type(chunk) == "string" and #chunk > 0 then
|
if type(chunk) == "string" and #chunk > 0 then
|
||||||
local samples = decoder(chunk)
|
local samples = decoder(chunk)
|
||||||
if samples and not playChunkOnSpeakers(samples, CONFIG.AUDIO_VOLUME, playSeq) then
|
if samples and not playChunkOnSpeakers(samples, CONFIG.AUDIO_VOLUME, playSeq, false) then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1826,7 +1843,7 @@ function Audio.playPcmItem(item)
|
|||||||
if chunk == nil then break end
|
if chunk == nil then break end
|
||||||
if type(chunk) == "string" and #chunk > 0 then
|
if type(chunk) == "string" and #chunk > 0 then
|
||||||
local samples = decodePcmS8Chunk(chunk)
|
local samples = decodePcmS8Chunk(chunk)
|
||||||
if samples and not playChunkOnSpeakers(samples, CONFIG.AUDIO_VOLUME, playSeq) then
|
if samples and not playChunkOnSpeakers(samples, CONFIG.AUDIO_VOLUME, playSeq, false) then
|
||||||
Audio.stop("current")
|
Audio.stop("current")
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@@ -1888,7 +1905,7 @@ function Audio.playPcmS16LEItem(item)
|
|||||||
if chunk == nil then break end
|
if chunk == nil then break end
|
||||||
if type(chunk) == "string" and #chunk > 0 then
|
if type(chunk) == "string" and #chunk > 0 then
|
||||||
local samples = decodePcmS16LEChunk(chunk)
|
local samples = decodePcmS16LEChunk(chunk)
|
||||||
if samples and not playChunkOnSpeakers(samples, CONFIG.AUDIO_VOLUME, playSeq) then
|
if samples and not playChunkOnSpeakers(samples, CONFIG.AUDIO_VOLUME, playSeq, false) then
|
||||||
Audio.stop("current")
|
Audio.stop("current")
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user