main.lua 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. -- LuaTools需要PROJECT和VERSION这两个信息
  2. PROJECT = "audiotest"
  3. VERSION = "2.0.1"
  4. -- sys库是标配
  5. _G.sys = require("sys")
  6. _G.sysplus = require("sysplus")
  7. -- Air780E的AT固件默认会为开机键防抖, 导致部分用户刷机很麻烦
  8. if rtos.bsp() == "EC618" and pm and pm.PWK_MODE then
  9. pm.power(pm.PWK_MODE, false)
  10. end
  11. log.style(1)
  12. local taskName = "task_audio"
  13. local MSG_MD = "moreData" -- 播放缓存有空余
  14. local MSG_PD = "playDone" -- 播放完成所有数据
  15. -- amr数据存放buffer,尽可能地给大一些
  16. amr_buff = zbuff.create(20 * 1024)
  17. --创建一个amr的encoder
  18. encoder = nil
  19. pcm_buff0 = zbuff.create(16000)
  20. pcm_buff1 = zbuff.create(16000)
  21. audio.on(0, function(id, event, point)
  22. --使用play来播放文件时只有播放完成回调
  23. if event == audio.RECORD_DATA then -- 录音数据
  24. if point == 0 then
  25. log.info("buff", point, pcm_buff0:used())
  26. codec.encode(encoder, pcm_buff0, amr_buff)
  27. else
  28. log.info("buff", point, pcm_buff1:used())
  29. codec.encode(encoder, pcm_buff1, amr_buff)
  30. end
  31. elseif event == audio.RECORD_DONE then -- 录音完成
  32. sys.publish("AUDIO_RECORD_DONE")
  33. else
  34. local succ,stop,file_cnt = audio.getError(0)
  35. if not succ then
  36. if stop then
  37. log.info("用户停止播放")
  38. else
  39. log.info("第", file_cnt, "个文件解码失败")
  40. end
  41. end
  42. -- log.info("播放完成一个音频")
  43. sysplus.sendMsg(taskName, MSG_PD)
  44. end
  45. end)
  46. function audio_setup()
  47. local bsp = rtos.bsp()
  48. if bsp == "EC618" then
  49. --Air780E开发板配套+音频扩展板. ES7149
  50. --由于音频扩展板的PA是长供电的,有塔塔声音是正常的,做产品的话有额外的参考设计
  51. i2s.setup(0, 0, 0, 0, 0, i2s.MODE_I2S)
  52. --如果用TM8211,打开下面的注释
  53. -- i2s.setup(0, 0, 0, 0, 0, i2s.MODE_MSB)
  54. --如果用软件DAC,打开下面的注释
  55. -- if audio.setBus then
  56. -- audio.setBus(0, audio.BUS_SOFT_DAC)
  57. -- end
  58. audio.config(0, 25, 1, 3, 100)
  59. elseif string.find(bsp,"EC718") then
  60. -- CORE+音频小板是这个配置/云喇叭开发板同为这个配置
  61. local multimedia_id = 0
  62. local i2c_id = 0 --云喇叭开发版是1
  63. local i2s_id = 0
  64. local i2s_mode = 0
  65. local i2s_sample_rate = 16000
  66. local i2s_bits_per_sample = 16
  67. local i2s_channel_format = i2s.MONO_R
  68. local i2s_communication_format = i2s.MODE_LSB
  69. local i2s_channel_bits = 16
  70. local pa_pin = 25
  71. local pa_on_level = 1
  72. local pa_delay = 100
  73. local power_pin = 16 -- Air780EPVH 请修改成17
  74. local power_on_level = 1
  75. local power_delay = 3
  76. local power_time_delay = 100
  77. local voice_vol = 70
  78. local mic_vol = 80
  79. local find_es8311 = false
  80. --内置8311的模块(比如air780epa, air780epvh)打开下面的代码
  81. --power_pin = 255
  82. --gpio.setup(17,1,nil,nil,4)
  83. --自适应开发板,如果明确是I2C几就不用了
  84. i2c.setup(0, i2c.FAST)
  85. i2c.setup(1, i2c.FAST)
  86. pm.power(pm.LDO_CTL, false) --开发板上ES8311由LDO_CTL控制上下电
  87. sys.wait(10)
  88. pm.power(pm.LDO_CTL, true) --开发板上ES8311由LDO_CTL控制上下电
  89. sys.wait(10)
  90. if i2c.send(0, 0x18, 0xfd) == true then
  91. log.info("音频小板或内置ES8311", "codec on i2c0")
  92. i2c_id = 0
  93. find_es8311 = true
  94. else
  95. if i2c.send(1, 0x18, 0xfd) == true then
  96. log.info("云喇叭开发板", "codec on i2c1")
  97. find_es8311 = true
  98. power_pin = nil
  99. i2c_id = 1
  100. end
  101. end
  102. if not find_es8311 then
  103. while true do
  104. log.info("not find es8311")
  105. sys.wait(1000)
  106. end
  107. end
  108. i2s.setup(i2s_id, i2s_mode, i2s_sample_rate, i2s_bits_per_sample, i2s_channel_format, i2s_communication_format,i2s_channel_bits)
  109. audio.config(multimedia_id, pa_pin, pa_on_level, power_delay, pa_delay, power_pin, power_on_level, power_time_delay)
  110. audio.setBus(multimedia_id, audio.BUS_I2S,{chip = "es8311",i2cid = i2c_id , i2sid = i2s_id}) --通道0的硬件输出通道设置为I2S
  111. audio.vol(multimedia_id, voice_vol)
  112. audio.micVol(multimedia_id, mic_vol)
  113. -- audio.debug(true)
  114. --带TM8211的云喇叭开发板参考下面的配置
  115. --[[
  116. local multimedia_id = 0
  117. local i2s_id = 0
  118. local i2s_mode = 0
  119. local i2s_sample_rate = 0
  120. local i2s_bits_per_sample = 16
  121. local i2s_channel_format = i2s.STEREO
  122. local i2s_communication_format = i2s.MODE_MSB
  123. local i2s_channel_bits = 16
  124. local pa_pin = 25
  125. local pa_on_level = 1
  126. local pa_delay = 100
  127. local power_pin = nil
  128. local power_on_level = 1
  129. local power_delay = 3
  130. local power_time_delay = 0
  131. local voice_vol = 100
  132. -- local voice_vol = 200 --默认就不放大了
  133. i2s.setup(i2s_id, i2s_mode, i2s_sample_rate, i2s_bits_per_sample, i2s_channel_format, i2s_communication_format,i2s_channel_bits)
  134. audio.config(multimedia_id, pa_pin, pa_on_level, power_delay, pa_delay, power_pin, power_on_level, power_time_delay)
  135. audio.setBus(multimedia_id, audio.BUS_I2S,{chip = "tm8211", i2sid = i2s_id}) --通道0的硬件输出通道设置为I2S
  136. -- audio.vol(multimedia_id, voice_vol)
  137. ]]
  138. elseif bsp == "AIR105" then
  139. -- Air105开发板支持DAC直接输出
  140. audio.config(0, 25, 1, 3, 100)
  141. else
  142. -- 其他板子未支持
  143. while 1 do
  144. log.info("audio", "尚未支持的BSP")
  145. sys.wait(1000)
  146. end
  147. end
  148. sys.publish("AUDIO_READY")
  149. end
  150. -- 配置好audio外设
  151. sys.taskInit(audio_setup)
  152. local function audio_task()
  153. sys.waitUntil("AUDIO_READY")
  154. local result
  155. --下面为录音demo,根据适配情况选择性开启
  156. -- local recordPath = "/record.amr"
  157. -- -- 直接录音到文件
  158. -- err = audio.record(0, audio.AMR, 5, 7, recordPath)
  159. -- sys.waitUntil("AUDIO_RECORD_DONE")
  160. -- log.info("record","录音结束")
  161. -- result = audio.play(0, {recordPath})
  162. -- while true do
  163. -- msg = sysplus.waitMsg(taskName, nil)
  164. -- if type(msg) == 'table' then
  165. -- if msg[1] == MSG_PD then
  166. -- log.info("播放结束")
  167. -- break
  168. -- end
  169. -- else
  170. -- log.error(type(msg), msg)
  171. -- end
  172. -- end
  173. -- -- 录音到内存自行编码
  174. -- encoder = codec.create(codec.AMR, false, 7)
  175. -- print("encoder",encoder)
  176. -- err = audio.record(0, audio.AMR, 5, 7, nil, pcm_buff0, pcm_buff1)
  177. -- sys.waitUntil("AUDIO_RECORD_DONE")
  178. -- log.info("record","录音结束")
  179. -- os.remove(recordPath)
  180. -- io.writeFile(recordPath, "#!AMR\n")
  181. -- io.writeFile(recordPath, amr_buff:query(), "a+b")
  182. -- result = audio.play(0, {recordPath})
  183. -- while true do
  184. -- msg = sysplus.waitMsg(taskName, nil)
  185. -- if type(msg) == 'table' then
  186. -- if msg[1] == MSG_PD then
  187. -- log.info("播放结束")
  188. -- break
  189. -- end
  190. -- else
  191. -- log.error(type(msg), msg)
  192. -- end
  193. -- end
  194. -- amr 可播放采样率 8k/16k
  195. local amrs = {"/luadb/alipay.amr", "/luadb/2.amr", "/luadb/10.amr", "/luadb/yuan.amr"}
  196. -- 如需在同一个table内混播, 需要使用相同的采样率
  197. -- 此mp3为自由文件,无版权问题,合宙自录音频,若测试音质请使用其他高清mp3
  198. -- local mp3s = {"/luadb/test_32k.mp3"}
  199. -- ec618的固件需要用非full版本才能放下44k的MP3
  200. local mp3s = {"/luadb/test_44k.mp3"}
  201. local counter = 0
  202. while true do
  203. log.info("开始播放")
  204. -- 两个列表前后播放
  205. if rtos.bsp() == "AIR105" then
  206. result = audio.play(0, "/luadb/test_32k.mp3")
  207. else
  208. result = audio.play(0, counter % 2 == 1 and amrs or mp3s)
  209. end
  210. counter = counter + 1
  211. if result then
  212. --等待音频通道的回调消息,或者切换歌曲的消息
  213. while true do
  214. msg = sysplus.waitMsg(taskName, nil)
  215. if type(msg) == 'table' then
  216. if msg[1] == MSG_PD then
  217. log.info("播放结束")
  218. break
  219. end
  220. else
  221. log.error(type(msg), msg)
  222. end
  223. end
  224. else
  225. log.debug("解码失败!")
  226. sys.wait(1000)
  227. end
  228. if not audio.isEnd(0) then
  229. log.info("手动关闭")
  230. audio.playStop(0)
  231. end
  232. audio.pm(0,audio.SHUTDOWN)
  233. --低功耗测试打开下面的代码
  234. --[[
  235. audio.pm(0,audio.POWEROFF) --低功耗可以选择SHUTDOWN或者POWEROFF,如果codec无法断电用SHUTDOWN
  236. pm.power(pm.USB, false)
  237. mobile.flymode(0, true)
  238. pm.request(pm.LIGHT)
  239. sys.wait(20000)
  240. mobile.flymode(0, false)
  241. ]]
  242. log.info(rtos.meminfo("sys"))
  243. log.info(rtos.meminfo("lua"))
  244. sys.wait(1000)
  245. end
  246. sysplus.taskDel(taskName)
  247. end
  248. sysplus.taskInitEx(audio_task, taskName, task_cb)
  249. -- 用户代码已结束---------------------------------------------
  250. -- 结尾总是这一句
  251. sys.run()
  252. -- sys.run()之后后面不要加任何语句!!!!!