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