From bf1895ebc5a6b2fdc23e163171a4711b9d15eed1 Mon Sep 17 00:00:00 2001 From: HenryDu8133 <813367384@qq.com> Date: Mon, 3 Aug 2026 09:49:01 +0800 Subject: [PATCH] =?UTF-8?q?perf(audio):=20=E4=BC=98=E5=8C=96=E9=9F=B3?= =?UTF-8?q?=E9=A2=91=E6=92=AD=E6=94=BE=E5=B8=A7=E5=A4=84=E7=90=86=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E5=8D=87=E7=BA=A7=E7=89=88=E6=9C=AC=E8=87=B3?= =?UTF-8?q?v1.0.50?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为test.lua添加标准文件头部注释 - 将station_broadcast.lua版本从v1.0.49更新至v1.0.50 - 新增NATIVE_AUDIO_FRAME_SAMPLES常量,将音频处理拆分为128样本每帧 - 修复空音频样本输入的边界异常问题 - 优化原生扬声器播放的循环逻辑,提升兼容性与执行效率 --- station_broadcast.lua | 94 ++++++++++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 33 deletions(-) diff --git a/station_broadcast.lua b/station_broadcast.lua index 90753b4..5d0495b 100644 --- a/station_broadcast.lua +++ b/station_broadcast.lua @@ -1,6 +1,6 @@ -- 1. Configuration & Constants -local APP_VERSION_TEXT = "v1.0.49" +local APP_VERSION_TEXT = "v1.0.50" local CONFIG = { CLOUD_URL = "ws://stabadmin.fse-media.group", @@ -32,6 +32,8 @@ local COLORS = { SUCCESS = colors.green } +local NATIVE_AUDIO_FRAME_SAMPLES = 128 + -- 2. State Management @@ -1170,46 +1172,70 @@ end local function playChunkOnSpeakers(samples, volume, playSeq, waitForDrain) if not Peripherals.speakers or #Peripherals.speakers == 0 then return false end if waitForDrain == nil then waitForDrain = true end - local pending = {} + local totalSamples = #samples + if totalSamples == 0 then return true end + + local speakerMap = {} + local nativeSpeakerCount = 0 for _, sp in ipairs(Peripherals.speakers) do local name = peripheral.getName(sp) - if name then pending[name] = sp end - end - - local usedNativePath = false - while next(pending) do - if shouldStop(playSeq) then return false end - for name, sp in pairs(pending) do - local ok = false - pcall(function() - if type(sp.playAudio) == "function" then - ok = sp.playAudio(samples, volume) - end - end) - if ok then - usedNativePath = true - pending[name] = nil + if name then + speakerMap[name] = sp + if type(sp.playAudio) == "function" then + nativeSpeakerCount = nativeSpeakerCount + 1 end end - if next(pending) then - local ev = { os.pullEvent() } - if ev[1] == "audio_interrupt" and tonumber(ev[2]) and tonumber(ev[2]) >= playSeq then + end + + local controller = Peripherals.speakers[1] + local usedNativePath = false + + for frameStart = 1, totalSamples, NATIVE_AUDIO_FRAME_SAMPLES do + local frameEnd = math.min(frameStart + NATIVE_AUDIO_FRAME_SAMPLES - 1, totalSamples) + local frame = {} + for i = frameStart, frameEnd do + frame[#frame + 1] = samples[i] + end + + if nativeSpeakerCount > 0 then + local pending = {} + for name, sp in pairs(speakerMap) do + if type(sp.playAudio) == "function" then + pending[name] = sp + end + end + + while next(pending) do + if shouldStop(playSeq) then return false end + for name, sp in pairs(pending) do + local ok = false + pcall(function() + ok = sp.playAudio(frame, volume) + end) + if ok then + usedNativePath = true + pending[name] = nil + end + end + if next(pending) then + local ev = { os.pullEvent() } + if ev[1] == "audio_interrupt" and tonumber(ev[2]) and tonumber(ev[2]) >= playSeq then + return false + end + end + end + else + if not controller or type(controller.playAudioAll) ~= "function" then return false end - end - end - - if usedNativePath then - Utils.log("INFO", string.format("Audio samples queued via native speaker.playAudio: samples=%d", #samples)) - else - local controller = Peripherals.speakers[1] - if controller and type(controller.playAudioAll) == "function" then - Utils.log("WARN", "Falling back to controller.playAudioAll for decoded samples") + if frameStart == 1 then + Utils.log("WARN", "Falling back to controller.playAudioAll for decoded samples") + end while true do if shouldStop(playSeq) then return false end local ok = false pcall(function() - ok = controller.playAudioAll(samples, volume) + ok = controller.playAudioAll(frame, volume) end) if ok then break end local ev = { os.pullEvent() } @@ -1217,11 +1243,13 @@ local function playChunkOnSpeakers(samples, volume, playSeq, waitForDrain) return false end end - else - return false end end + if usedNativePath then + Utils.log("INFO", string.format("Audio samples queued via native speaker.playAudio: samples=%d frame=%d", totalSamples, NATIVE_AUDIO_FRAME_SAMPLES)) + end + if not waitForDrain then return true end return waitForNativeSpeakersEmpty(Peripherals.speakers, playSeq) end