Browse Source

fix: add air8000 音频功能

梁健 6 months ago
parent
commit
f5128cb045

+ 74 - 32
luat/demo/airtalk/audio_config.lua

@@ -1,37 +1,79 @@
 function audio_init()
     pm.ioVol(pm.IOVOL_ALL_GPIO, 3300)
-    local multimedia_id = 0
-
-    local i2s_id = 0
-    local i2s_mode = 0
-    local i2s_sample_rate = 16000
-    local i2s_bits_per_sample = 16
-    local i2s_channel_format = i2s.MONO_R
-    local i2s_communication_format = i2s.MODE_LSB
-    local i2s_channel_bits = 16
-    --air8000 core开发版+音频小板配置
-    local voice_vol = 60 --音频小板喇叭太容易失真了,不能太大
-    local i2c_id = 0
-    local pa_pin = 162           -- 喇叭pa功放脚
-    local pa_on_level = 1
-    local pa_delay = 200
-    local dac_power_pin = 164
-    local dac_power_on_level = 1
-    local dac_power_off_delay = 600
-    gpio.setup(24, 1)   --air8000的I2C0需要拉高gpio24才能用
-    gpio.setup(26, 0)
-    i2c.setup(0, i2c.FAST)
-    gpio.setup(24, 1, gpio.PULLUP)          -- i2c工作的电压域
-    sys.wait(100)
-    gpio.setup(dac_power_pin, 1, gpio.PULLUP)   -- 打开音频编解码供电
-    gpio.setup(pa_pin, 1, gpio.PULLUP)      -- 打开音频放大器
-    audio.on(0, audio_callback)
-
-    i2s.setup(i2s_id, i2s_mode, i2s_sample_rate, i2s_bits_per_sample, i2s_channel_format, i2s_communication_format,i2s_channel_bits)
-
-    audio.config(multimedia_id, pa_pin, pa_on_level, 0, pa_delay, dac_power_pin, dac_power_on_level, dac_power_off_delay)
-    audio.setBus(multimedia_id, audio.BUS_I2S,{chip = "es8311",i2cid = i2c_id , i2sid = i2s_id})	--通道0的硬件输出通道设置为I2S
+    -- local multimedia_id = 0
+
+    -- local i2s_id = 0
+    -- local i2s_mode = 0
+    -- local i2s_sample_rate = 16000
+    -- local i2s_bits_per_sample = 16
+    -- local i2s_channel_format = i2s.MONO_R
+    -- local i2s_communication_format = i2s.MODE_LSB
+    -- local i2s_channel_bits = 16
+    -- --air8000 core开发版+音频小板配置
+    -- local voice_vol = 60 --音频小板喇叭太容易失真了,不能太大
+    -- local i2c_id = 0
+    -- local pa_pin = 162           -- 喇叭pa功放脚
+    -- local pa_on_level = 1
+    -- local pa_delay = 200
+    -- local dac_power_pin = 164
+    -- local dac_power_on_level = 1
+    -- local dac_power_off_delay = 600
+    -- gpio.setup(24, 1)   --air8000的I2C0需要拉高gpio24才能用
+    -- gpio.setup(26, 0)
+    -- i2c.setup(0, i2c.FAST)
+    -- gpio.setup(24, 1, gpio.PULLUP)          -- i2c工作的电压域
+    -- sys.wait(100)
+    -- gpio.setup(dac_power_pin, 1, gpio.PULLUP)   -- 打开音频编解码供电
+    -- gpio.setup(pa_pin, 1, gpio.PULLUP)      -- 打开音频放大器
+    -- audio.on(0, audio_callback)
+
+    -- i2s.setup(i2s_id, i2s_mode, i2s_sample_rate, i2s_bits_per_sample, i2s_channel_format, i2s_communication_format,i2s_channel_bits)
+
+    -- audio.config(multimedia_id, pa_pin, pa_on_level, 0, pa_delay, dac_power_pin, dac_power_on_level, dac_power_off_delay)
+    -- audio.setBus(multimedia_id, audio.BUS_I2S,{chip = "es8311",i2cid = i2c_id , i2sid = i2s_id})	--通道0的硬件输出通道设置为I2S
+
+    -- audio.vol(multimedia_id, voice_vol)
+    -- audio.micVol(multimedia_id, 75)
+     local multimedia_id = 0
+ local i2c_id = 0 -- i2c_id 0
+
+    local pa_pin = gpio.AUDIOPA_EN -- 喇叭pa功放脚
+    local power_pin = 20 -- es8311电源脚
+
+    local i2s_id = 0 -- i2s_id 0
+    local i2s_mode = 0 -- i2s模式 0 主机 1 从机
+    local i2s_sample_rate = 16000 -- 采样率
+    local i2s_bits_per_sample = 16 -- 数据位数
+    local i2s_channel_format = i2s.MONO_R -- 声道, 0 左声道, 1 右声道, 2 立体声
+    local i2s_communication_format = i2s.MODE_LSB -- 格式, 可选MODE_I2S, MODE_LSB, MODE_MSB
+    local i2s_channel_bits = 16 -- 声道的BCLK数量
+
+    local multimedia_id = 0 -- 音频通道 0
+    local pa_on_level = 1 -- PA打开电平 1 高电平 0 低电平
+    local power_delay = 3 -- 在DAC启动前插入的冗余时间,单位100ms
+    local pa_delay = 100 -- 在DAC启动后,延迟多长时间打开PA,单位1ms
+    local power_on_level = 1 -- 电源控制IO的电平,默认拉高
+    local power_time_delay = 100 -- 音频播放完毕时,PA与DAC关闭的时间间隔,单位1ms
+
+    local voice_vol = 70 -- 喇叭音量
+    local mic_vol = 80 -- 麦克风音量
+    gpio.setup(power_pin, 1, gpio.PULLUP)
+    gpio.setup(pa_pin, 1, gpio.PULLUP)
+
+    sys.wait(200)
+
+    i2c.setup(i2c_id, i2c.FAST) -- 设置i2c
+    i2s.setup(i2s_id, i2s_mode, i2s_sample_rate, i2s_bits_per_sample, i2s_channel_format, i2s_communication_format,
+        i2s_channel_bits) -- 设置i2s
+
+    audio.config(multimedia_id, pa_pin, pa_on_level, power_delay, pa_delay, power_pin, power_on_level, power_time_delay)
+    audio.setBus(multimedia_id, audio.BUS_I2S, {
+        chip = "es8311",
+        i2cid = i2c_id,
+        i2sid = i2s_id,
+    }) -- 通道0的硬件输出通道设置为I2S
 
     audio.vol(multimedia_id, voice_vol)
-    audio.micVol(multimedia_id, 75)
+    audio.micVol(multimedia_id, mic_vol)
+
 end

+ 253 - 0
module/Air8000/demo/audio/exaudio.lua

@@ -0,0 +1,253 @@
+--[[
+@module exaudio
+@summary exaudio扩展库
+@version 1.0
+@date    2025.08.08
+@author  梁健
+@usage
+]]
+local exaudio = {}
+
+local i2s_id = 0            -- i2s_id 0
+local i2s_mode = 0          -- i2s模式 0 主机 1 从机
+local i2s_sample_rate = 16000   -- 采样率
+local i2s_channel_format = i2s.MONO_R   -- 声道, 0 左声道, 1 右声道, 2 立体声
+local i2s_communication_format = i2s.MODE_LSB   -- 格式, 可选MODE_I2S, MODE_LSB, MODE_MSB
+local i2s_channel_bits = 16     -- 声道的BCLK数量
+local multimedia_id = 0         -- 音频通道 0
+local voice_vol = 55
+local mic_vol = 80
+local power_on_level = 1
+
+local audio_setup_param ={
+    model= "es8311",          -- dac类型,可填入"es8311","es8211"
+    i2c_id = 0,          -- i2c_id,可填入0,1 并使用pins 工具配置对应的管脚
+    pa_ctrl = 0,         -- 音频放大器电源控制管脚
+    dac_ctrl = 0,        --  音频编解码芯片电源控制管脚
+    dac_delay = 3,        -- 在DAC启动前插入的冗余时间,单位100ms
+    pa_delay = 100,      -- 在DAC启动后,延迟多长时间打开PA,单位1ms
+    dac_time_delay = 600,    -- 音频播放完毕时,PA与DAC关闭的时间间隔,单位1ms
+    bits_per_sample = 16,  -- codec 采样位数
+    pa_on_level = 1,           -- PA打开电平 1 高电平 0 低电平        
+}
+
+local audio_play_param ={
+    type= 0,                -- 播放类型,有0,播放文件,1.播放tts 2. 流式播放
+                            -- 如果是播放文件,支持mp3,amr,wav格式
+                            -- 如果是tts,内容格式见:https://wiki.luatos.com/chips/air780e/tts.html?highlight=tts
+                            -- 流式播放,仅支持PCM 格式音频,如果是流式播放,则Sampling_Rate, Sampling_Depth,Signed_or_Unsigned 必填写
+    content = nil,          -- 如果播放类型为0时,则填入string 是播放单个音频文件,如果是表则是播放多段音频文件。
+                            -- 如果播放tts 则填入要播放的内容。
+                            -- 如果为2,流式播放,则填入音频回调函数
+    cbFnc = nil,            -- 播放完毕回调函数,返回值有如下的参数
+                            --  0-播放成功结束
+                            --  1-播放出错
+                            --  2-播放优先级不够,没有播放
+                            --  3-传入的参数出错,没有播放
+                            --  4-被新的播放请求中止
+                            --  5-调用audio.stop接口主动停止
+    priority = 0,           -- 音频优先级,数值越大,优先级越高
+                            -- 优先级高的播放请求会终止优先级低的播放
+                            -- 相同优先级的播放请求,播放策略参考:audio.setStrategy接口
+    sampling_Rate = 16000,  -- 采样率,仅为流式播放起作用
+    sampling_Depth =  16,   -- 采样位位深,仅流式播放的时候才有作用
+    signed_or_Unsigned = true  -- PCM 的数据是否有符号,仅为流式播放起作用
+}
+
+local audio_record_param ={
+    format= 0,              -- 录制格式,有AMR,AMR_WB,PCM_8000,PCM_16000,PCM_24000,PCM_32000
+    time = 5,               -- 录制时间,单位(秒)
+    path = nil,             -- 如果填入的是字符串,则表示是文件路径,录音会传输到这个路径里
+                            -- 如果填入的是函数,则表示是流式录音,录音的数据会传输到此函数内
+}
+
+local function audio_callback(id, event)
+    log.info("audio_callback,event:",event,audio.MORE_DATA,audio.DONE,audio.RECORD_DATA,audio.RECORD_DONE)
+    if event  == audio.MORE_DATA then
+        audio_play_param.content()
+    end
+end
+
+local function audio_setup()
+    local result,data
+    sys.wait(100)
+
+    i2c.setup(audio_setup_param.i2c_id,i2c.FAST)
+    
+    result,data= i2s.setup(i2s_id, i2s_mode, i2s_sample_rate, audio_setup_param.bits_per_sample, i2s_channel_format, i2s_communication_format,i2s_channel_bits)
+    if not result then     --  设置音频参数错误
+        return result
+    end
+
+    audio.config(multimedia_id, audio_setup_param.pa_ctrl, audio_setup_param.pa_on_level, audio_setup_param.dac_delay, audio_setup_param.pa_delay, audio_setup_param.dac_ctrl, power_on_level, audio_setup_param.dac_time_delay)
+    audio.setBus(multimedia_id, audio.BUS_I2S,{chip = audio_setup_param.model,i2cid = audio_setup_param.i2c_id , i2sid = i2s_id, voltage = audio.VOLTAGE_1800})	--通道0的硬件输出通道设置为I2S
+
+    audio.vol(multimedia_id, voice_vol)
+    audio.micVol(multimedia_id, mic_vol)
+    audio.pm(multimedia_id,audio.RESUME)
+    sys.wait(100)
+    audio.on(multimedia_id, audio_callback)
+    return result
+end
+
+
+
+
+function exaudio.setup(audioConfigs)
+    if audioConfigs.model == nil  and (audioConfigs.model ~= "es8311"  or audioConfigs.model ~= "es8211") then   -- codec 名称必现写
+        log.error("没有填写codec 名称,或者不是es8311,es8211")
+        return false      
+    else
+        audio_setup_param.model = audioConfigs.model
+    end
+
+    if audioConfigs.model  == "es8311"  then
+        if  ( audioConfigs.i2c_id == nil  or type(audioConfigs.i2c_id) ~= "number"  )then   
+             -- 如果是8311 ,则必须写出i2c 地址
+            log.error("当前使用8311 codec, 但没有填写i2c id")
+            return false
+        else
+            audio_setup_param.i2c_id = audioConfigs.i2c_id
+        end
+    end
+
+    if audioConfigs.pa_ctrl == nil then   -- pa_ctrl PA 的控制管脚必须填写
+        log.error("pa 控制为空")
+        return false
+    else
+        audio_setup_param.pa_ctrl = audioConfigs.pa_ctrl
+    end
+
+
+    if audioConfigs.dac_ctrl ~= nil  and type(audioConfigs.dac_ctrl) == "number" then   -- 编解码芯片控制管脚不需要必填
+        audio_setup_param.dac_ctrl = audioConfigs.dac_ctrl
+    end
+
+    if audioConfigs.dac_delay ~= nil  and type(audioConfigs.dac_delay) == "number" then   -- 在DAC启动前插入的冗余时间 ,非必填
+        audio_setup_param.dac_delay = audioConfigs.dac_delay
+    end
+
+    if audioConfigs.pa_delay ~= nil  and type(audioConfigs.pa_delay) == "number" then   -- 在DAC启动后,延迟多长时间打开PA ,非必填
+        audio_setup_param.pa_delay = audioConfigs.padelay
+    end
+
+
+    if audioConfigs.dac_time_delay ~= nil  and type(audioConfigs.dac_time_delay) == "number" then   
+        audio_setup_param.dac_time_delay = audioConfigs.dac_time_delay
+    end
+
+    if audioConfigs.bits_per_sample ~= nil  and type(audioConfigs.bits_per_sample) == "number" then   
+        audio_setup_param.bits_per_sample = audioConfigs.bits_per_sample
+    end
+    
+    if audioConfigs.pa_on_level ~= nil  and type(audioConfigs.pa_on_level) == "number" then  
+        audio_setup_param.pa_on_level = audioConfigs.pa_on_level
+    end
+
+    return audio_setup()    -- 返回初始化结果
+end
+
+function exaudio.write_datablock(data)
+    audio.write(multimedia_id,data)    
+end
+
+function exaudio.play_start(playConfigs)
+    if playConfigs.type == nil  and type(playConfigs.type)  ~= "number" then   
+        log.error("type 必须填写,也必须为数值,0:播放文件,1: 播放TTS,2:流式播放")
+        return false      
+    else
+        audio_play_param.type = playConfigs.type
+    end
+
+    if playConfigs.priority ~= nil and type(playConfigs.priority) == "number" then  -- 如果当前的播放优先级比历史优先级高,则停止之前的播放
+        if playConfigs.priority >= audio_play_param.priority then   
+            audio.stop(multimedia_id)
+            sys.wait(100)
+        end
+    end
+
+    if audio_play_param.type == 0 then    --  播放文件处理
+        if playConfigs.content == nil then
+            log.error("当type 为0 时,playConfigs.content 只能为string(播放单文件),或者table(多文件)")
+            return false      
+        end
+        
+        if(type(playConfigs.content) == "table") then      -- 当播放多文件时候
+            for _, path in ipairs(playConfigs.content) do  
+                if type(path) ~= "string" then             -- 检查多文件是否都是string
+                    log.error("当type 为0 时,playConfigs.content 为table 时,table 内元素必须为string 类型")
+                    return false     
+                end
+            end
+        elseif  (type(playConfigs.content) ~= "string") then
+            log.error("当type 为0 时,playConfigs.content 类型必须为table(播放多文件),或者string(播放单文件)")
+            return false    
+        end
+        audio_play_param.content = playConfigs.content
+        audio.play(multimedia_id,audio_play_param.content)
+    end
+
+    if audio_play_param.type == 1 then        -- 播放tts 处理
+        if playConfigs.content == nil or type(playConfigs.content) ~= "string"  then
+            log.error("当type 为1 时,则表示播放tts,playConfigs.content 必须为string 类型")
+            return false    
+        end
+        audio_play_param.content = playConfigs.content
+        audio.tts(multimedia_id,audio_play_param.content)
+    end
+    if audio_play_param.type == 2 then        -- 流式播放处理
+        if playConfigs.content == nil or type(playConfigs.content) ~= "function"  then
+            log.error("当type 为2 时,则表示流式播放,playConfigs.content 必须为function 类型")
+            return false    
+        end
+        if playConfigs.sampling_Rate == nil or type(playConfigs.sampling_Rate) ~= "number"  then
+            log.error("当type 为2 时,则表示流式播放,sampling_Rate(采样率)必须为int 类型")
+            return false    
+        end
+        if playConfigs.sampling_Depth == nil or type(playConfigs.sampling_Depth) ~= "number"  then
+            log.error("当type 为2 时,则表示流式播放,sampling_Depth(采样位深)必须为int 类型")
+            return false    
+        end
+        if playConfigs.signed_or_Unsigned == nil and type(playConfigs.signed_or_Unsigned) == "boolean"  then
+            audio_play_param.signed_or_Unsigned = playConfigs.signed_or_Unsigned
+        end
+        audio_play_param.content = playConfigs.content
+        audio.start(multimedia_id, audio.PCM, 1, playConfigs.sampling_Rate, playConfigs.sampling_Depth, audio_play_param.signed_or_Unsigned)
+        audio.write(0, string.rep("\0", 512))
+    end
+
+    if audio_play_param.cbFnc ~= nil and type(audio_play_param.cbFnc) == "function" then -- 如果填了回调函数,则保存回调韩函数,播放完毕调用回调函数
+        audio_play_param.cbFnc = playConfigs.cbFnc
+    end
+    
+end
+
+function exaudio.play_stop()
+    
+end
+
+function exaudio.isEnd()
+    
+end
+
+function exaudio.getError()
+    
+end
+
+function exaudio.record()
+    
+end
+
+function exaudio.record_stop()
+    
+end
+
+function exaudio.vol()
+    
+end
+
+function exaudio.micVol()
+    
+end
+
+return exaudio

+ 3 - 101
module/Air8000/demo/audio/main.lua

@@ -9,117 +9,19 @@ VERSION = "1.0.0"
 
 -- sys库是标配
 _G.sys = require("sys")
-_G.sysplus = require("sysplus")
 
-gpio.setup(24, 1, gpio.PULLUP)          -- i2c工作的电压域
 
+-- require "play_file"     --  播放文件
 
-local i2c_id = 0            -- i2c_id 0
+-- require "play_tts"      -- 播放tts
 
-local pa_pin = 162           -- 喇叭pa功放脚,需要根据自己的硬件配置
-local power_pin = 164         -- es8311电源脚,需要根据自己的硬件配置
-
-local i2s_id = 0            -- i2s_id 0
-local i2s_mode = 0          -- i2s模式 0 主机 1 从机
-local i2s_sample_rate = 16000   -- 采样率
-local i2s_bits_per_sample = 16  -- 数据位数
-local i2s_channel_format = i2s.MONO_R   -- 声道, 0 左声道, 1 右声道, 2 立体声
-local i2s_communication_format = i2s.MODE_LSB   -- 格式, 可选MODE_I2S, MODE_LSB, MODE_MSB
-local i2s_channel_bits = 16     -- 声道的BCLK数量
-
-local multimedia_id = 0         -- 音频通道 0
-local pa_on_level = 1           -- PA打开电平 1 高电平 0 低电平
-local power_delay = 3           -- 在DAC启动前插入的冗余时间,单位100ms
-local pa_delay = 100            -- 在DAC启动后,延迟多长时间打开PA,单位1ms
-local power_on_level = 1        -- 电源控制IO的电平,默认拉高
-local power_time_delay = 100    -- 音频播放完毕时,PA与DAC关闭的时间间隔,单位1ms
-
-local voice_vol = 70        -- 喇叭音量
-local mic_vol = 80          -- 麦克风音量
-
-gpio.setup(power_pin, 1, gpio.PULLUP)            -- 打开es8311 的电源脚
-gpio.setup(pa_pin, 1, gpio.PULLUP)               -- 打开pa 的电源脚
-
-function audio_setup()
-    sys.wait(100)
- 
-    i2c.setup(i2c_id,i2c.FAST)      --设置i2c
-    i2s.setup(i2s_id, i2s_mode, i2s_sample_rate, i2s_bits_per_sample, i2s_channel_format, i2s_communication_format,i2s_channel_bits)    --设置i2s
-
-    audio.config(multimedia_id, pa_pin, pa_on_level, power_delay, pa_delay, power_pin, power_on_level, power_time_delay)
-    audio.setBus(multimedia_id, audio.BUS_I2S,{chip = "es8311",i2cid = i2c_id , i2sid = i2s_id, voltage = audio.VOLTAGE_1800})	--通道0的硬件输出通道设置为I2S
-
-    audio.vol(multimedia_id, voice_vol)
-    audio.micVol(multimedia_id, mic_vol)
-    sys.publish("AUDIO_READY")
-end
-
--- 配置好audio外设
-sys.taskInit(audio_setup)
-
-local taskName = "task_audio"
-
-local MSG_MD = "moreData"   -- 播放缓存有空余
-local MSG_PD = "playDone"   -- 播放完成所有数据
-
-audio.on(0, function(id, event)
-    --使用play来播放文件时只有播放完成回调
-    local succ,stop,file_cnt = audio.getError(0)
-    if not succ then
-        if stop then
-            log.info("用户停止播放")
-        else
-            log.info("第", file_cnt, "个文件解码失败")
-        end
-    end
-    sysplus.sendMsg(taskName, MSG_PD)
-end)
-
-
-local function audio_task()
-    local result    
-    sys.waitUntil("AUDIO_READY")
-    while true do
-        log.info("开始播放")
-        result = audio.play(0,"/luadb/1.mp3")
-        if result then
-        --等待音频通道的回调消息,或者切换歌曲的消息
-            while true do
-                msg = sysplus.waitMsg(taskName, nil)
-                if type(msg) == 'table' then
-                    if msg[1] == MSG_PD then
-                        log.info("播放结束")
-                        break
-                    end
-                else
-                    log.error(type(msg), msg)
-                end
-            end
-        else
-            log.debug("解码失败!")
-            sys.wait(1000)
-        end
-        if not audio.isEnd(0) then
-            log.info("手动关闭")
-            audio.playStop(0)
-        end
-        if audio.pm then
-		    audio.pm(0,audio.STANDBY)       --PM模式 待机模式,PA断电,codec待机状态,系统不能进低功耗状态,如果PA不可控,codec进入静音模式
-        end
-		-- audio.pm(0,audio.SHUTDOWN)	--低功耗可以选择SHUTDOWN或者POWEROFF,如果codec无法断电用SHUTDOWN
-        log.info("mem", "sys", rtos.meminfo("sys"))
-        log.info("mem", "lua", rtos.meminfo("lua"))
-        sys.wait(1000)
-    end
-end
+require "play_steam"        -- 流式播放
 
 sys.timerLoopStart(function()
     log.info("mem.lua", rtos.meminfo())
     log.info("mem.sys", rtos.meminfo("sys"))
  end, 3000)
 
-sysplus.taskInitEx(audio_task, taskName)
-
 -- 用户代码已结束---------------------------------------------
 -- 结尾总是这一句
 sys.run()

+ 27 - 0
module/Air8000/demo/audio/play_file.lua

@@ -0,0 +1,27 @@
+exaudio = require("exaudio")
+
+local audio_setup_param ={
+    model= "es8311",          -- dac类型,可填入"es8311","es8211"
+    i2c_id = 0,          -- i2c_id,可填入0,1 并使用pins 工具配置对应的管脚
+    pa_ctrl = 162,         -- 音频放大器电源控制管脚
+    dac_ctrl = 164,        --  音频编解码芯片电源控制管脚
+    -- dac_delay = 3,        -- 在DAC启动前插入的冗余时间,单位100ms,控制pop 音
+    -- pa_delay = 100,      -- 在DAC启动后,延迟多长时间打开PA,单位1ms,控制pop 音
+    -- dac_time_delay = 600,    -- 音频播放完毕时,PA与DAC关闭的时间间隔,单位1ms,控制pop 音
+    -- pa_on_level = 1,           -- PA打开电平 1 高电平 0 低电平        
+}
+local audio_play_param ={
+    type= 0,                -- 播放类型,有0,播放文件,1.播放tts 2. 流式播放
+                            -- 如果是播放文件,支持mp3,amr,wav格式
+                            -- 如果是tts,内容格式见:https://wiki.luatos.com/chips/air780e/tts.html?highlight=tts
+                            -- 流式播放,仅支持PCM 格式音频,如果是流式播放,则Sampling_Rate, Sampling_Depth,Signed_or_Unsigned 必填写
+    content = "/luadb/1.mp3",          -- 如果播放类型为0时,则填入string 是播放单个音频文件,如果是表则是播放多段音频文件。
+}
+local taskName = "task_audio"
+local function audio_task()
+    log.info("开始播放音频文件")
+    exaudio.setup(audio_setup_param)
+    exaudio.play_start(audio_play_param)
+end
+
+sysplus.taskInitEx(audio_task, taskName)

+ 75 - 0
module/Air8000/demo/audio/play_steam.lua

@@ -0,0 +1,75 @@
+exaudio = require("exaudio")
+
+local audio_setup_param ={
+    model= "es8311",          -- dac类型,可填入"es8311","es8211"
+    i2c_id = 0,          -- i2c_id,可填入0,1 并使用pins 工具配置对应的管脚
+    pa_ctrl = 162,         -- 音频放大器电源控制管脚
+    dac_ctrl = 164,        --  音频编解码芯片电源控制管脚
+    -- dac_delay = 3,        -- 在DAC启动前插入的冗余时间,单位100ms
+    -- pa_delay = 100,      -- 在DAC启动后,延迟多长时间打开PA,单位1ms
+    -- dac_time_delay = 600,    -- 音频播放完毕时,PA与DAC关闭的时间间隔,单位1ms
+    -- bits_per_sample = 16,  -- codec 采样位数
+    -- pa_on_level = 1,           -- PA打开电平 1 高电平 0 低电平        
+}
+local  index = 1024         --  
+local f = io.open("/luadb/test.pcm", "rb")
+local function audio_need_more_data()
+    if f then 
+        local data = f:read(index)
+        -- print("-------------")
+        if  data  then
+            audio.write(0, data)            
+        end
+        -- sys.wait(100)
+    end
+end 
+
+local function cbFnc()
+    
+
+end 
+
+local audio_play_param ={
+    type= 2,                -- 播放类型,有0,播放文件,1.播放tts 2. 流式播放
+                            -- 如果是播放文件,支持mp3,amr,wav格式
+                            -- 如果是tts,内容格式见:https://wiki.luatos.com/chips/air780e/tts.html?highlight=tts
+                            -- 流式播放,仅支持PCM 格式音频,如果是流式播放,则Sampling_Rate, Sampling_Depth,Signed_or_Unsigned 必填写
+    content = audio_need_more_data,          -- 如果播放类型为0时,则填入string 是播放单个音频文件,如果是表则是播放多段音频文件。
+                            -- 如果播放tts 则填入要播放的内容。
+                            -- 如果为2,流式播放,则填入音频回调函数
+    cbFnc = cbFnc,            -- 播放完毕回调函数,返回值有如下的参数
+    --                         --  0-播放成功结束
+    --                         --  1-播放出错
+    --                         --  2-播放优先级不够,没有播放
+    --                         --  3-传入的参数出错,没有播放
+    --                         --  4-被新的播放请求中止
+    --                         --  5-调用audio.stop接口主动停止
+    -- priority = 0,           -- 音频优先级,数值越大,优先级越高
+    --                         -- 优先级高的播放请求会终止优先级低的播放
+    --                         -- 相同优先级的播放请求,播放策略参考:audio.setStrategy接口
+    sampling_Rate = 16000,  -- 采样率,仅为流式播放起作用
+    sampling_Depth =  16,   -- 采样位位深,仅流式播放的时候才有作用
+    signed_or_Unsigned = true  -- PCM 的数据是否有符号,仅为流式播放起作用
+}
+
+
+local taskName = "task_audio"
+local function audio_task()
+    log.info("开始播报")
+
+    exaudio.setup(audio_setup_param)
+    exaudio.play_start(audio_play_param)
+    
+end
+
+sysplus.taskInitEx(audio_task, taskName)
+
+sys.timerLoopStart(function()
+    log.info("mem.lua", rtos.meminfo())
+    log.info("mem.sys", rtos.meminfo("sys"))
+ end, 3000)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!

+ 27 - 0
module/Air8000/demo/audio/play_tts.lua

@@ -0,0 +1,27 @@
+exaudio = require("exaudio")
+
+local audio_setup_param ={
+    model= "es8311",          -- dac类型,可填入"es8311","es8211"
+    i2c_id = 0,          -- i2c_id,可填入0,1 并使用pins 工具配置对应的管脚
+    pa_ctrl = 162,         -- 音频放大器电源控制管脚
+    dac_ctrl = 164,        --  音频编解码芯片电源控制管脚 
+    -- dac_delay = 3,        -- 在DAC启动前插入的冗余时间,单位100ms
+    -- pa_delay = 100,      -- 在DAC启动后,延迟多长时间打开PA,单位1ms
+    -- dac_time_delay = 600,    -- 音频播放完毕时,PA与DAC关闭的时间间隔,单位1ms
+    -- pa_on_level = 1,           -- PA打开电平 1 高电平 0 低电平        
+}
+local audio_play_param ={
+    type= 1,                -- 播放类型,有0,播放文件,1.播放tts 2. 流式播放
+                            -- 如果是播放文件,支持mp3,amr,wav格式
+                            -- 如果是tts,内容格式见:https://wiki.luatos.com/chips/air780e/tts.html?highlight=tts
+                            -- 流式播放,仅支持PCM 格式音频,如果是流式播放,则Sampling_Rate, Sampling_Depth,Signed_or_Unsigned 必填写
+    content = "支付宝到账,12345元",          -- 如果播放类型为0时,则填入string 是播放单个音频文件,如果是表则是播放多段音频文件。
+}
+local taskName = "task_audio"
+local function audio_task()
+    log.info("开始播放音频文件")
+    exaudio.setup(audio_setup_param)
+    exaudio.play_start(audio_play_param)
+end
+
+sysplus.taskInitEx(audio_task, taskName)

BIN
module/Air8000/demo/audio/test.pcm


+ 7 - 9
script/libs/exaudio.lua

@@ -62,7 +62,7 @@ local audio_record_param ={
 }
 
 local function audio_callback(id, event)
-    log.info("audio_callback,event:",event)
+    log.info("audio_callback,event:",event,audio.MORE_DATA,audio.DONE,audio.RECORD_DATA,audio.RECORD_DONE)
     if event  == audio.MORE_DATA then
         audio_play_param.content()
     end
@@ -71,13 +71,6 @@ end
 local function audio_setup()
     local result,data
     sys.wait(100)
-    
-    if audio_setup_param.pa_ctrl >128 then
-        gpio.setup(audio_setup_param.pa_ctrl, 1, gpio.PULLUP)            -- 打开es8311 的电源脚
-    end
-    if audio_setup_param.dac_ctrl >128 then
-        gpio.setup(audio_setup_param.dac_ctrl, 1, gpio.PULLUP)
-    end
 
     i2c.setup(audio_setup_param.i2c_id,i2c.FAST)
     
@@ -91,7 +84,7 @@ local function audio_setup()
 
     audio.vol(multimedia_id, voice_vol)
     audio.micVol(multimedia_id, mic_vol)
-
+    audio.pm(multimedia_id,audio.RESUME)
     sys.wait(100)
     audio.on(multimedia_id, audio_callback)
     return result
@@ -154,6 +147,10 @@ function exaudio.setup(audioConfigs)
     return audio_setup()    -- 返回初始化结果
 end
 
+function exaudio.write_datablock(data)
+    audio.write(multimedia_id,data)    
+end
+
 function exaudio.play_start(playConfigs)
     if playConfigs.type == nil  and type(playConfigs.type)  ~= "number" then   
         log.error("type 必须填写,也必须为数值,0:播放文件,1: 播放TTS,2:流式播放")
@@ -216,6 +213,7 @@ function exaudio.play_start(playConfigs)
         end
         audio_play_param.content = playConfigs.content
         audio.start(multimedia_id, audio.PCM, 1, playConfigs.sampling_Rate, playConfigs.sampling_Depth, audio_play_param.signed_or_Unsigned)
+        audio.write(0, string.rep("\0", 512))
     end
 
     if audio_play_param.cbFnc ~= nil and type(audio_play_param.cbFnc) == "function" then -- 如果填了回调函数,则保存回调韩函数,播放完毕调用回调函数