audio_play.lua 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. --[[
  2. 本demo当前仅支持Ar780E和Air600E
  3. ## 提醒:
  4. 1. 本demo需要2022.12.21及之后的源码所编译的LuatOS固件
  5. 2. 本demo若使用外置TTS资源的LuatOS固件, 就必须有外挂的SPI Flash, 起码1M字节, 后面有刷写说明
  6. 3. 下载脚本时, 把txt也加上一起下载
  7. 4. 本demo需要音频扩展板, 780E只有I2S输出, 需要codec和PA才能驱动喇叭
  8. 5. 内置TTS资源的LuatOS最低版本是V1104,且去掉了很多库, 尤其是UI方面的库
  9. ## 使用本demo前,如果是外置TTS资源的LuatOS固件, 必须先刷tts.binpkg进行SPI Flash的刷写
  10. 1. 下载链接 https://gitee.com/openLuat/luatos-soc-2022/attach_files
  11. 2. 在LuaTools主界面, 用"下载固件"按钮进行下载.
  12. 3. 下载前需要接好SPI Flash!!
  13. 4. 下载前选日志模式 4G USB, luatools版本号2.1.85或以上
  14. ## SPI Flash布局, 以1M字节为例,供参考:
  15. -----------------------------------
  16. 64 k 保留空间, 用户自行分配
  17. -----------------------------------
  18. 704k TTS数据
  19. -----------------------------------
  20. 剩余空间, 256k,用户自行分配
  21. -----------------------------------
  22. ## 基本流程:
  23. 1. 初始化sfud, 本demo使用SPI0 + GPIO8
  24. 2. 使用 audio.tts播放文本
  25. 3. 等待 播放结束事件
  26. 4. 从第二步重新下一个循环
  27. ## 接线说明
  28. 以780E开发板为例, 需要1.5版本或以上,团购版本均为1.5或以上.
  29. 1.4版本SPI分布有所不同, 注意区分.
  30. https://wiki.luatos.com/chips/air780e/board.html
  31. xx脚指开发板pinout图上的顺序编号, 非GPIO编号
  32. Flash -- 开发板
  33. GND -- 16脚, GND
  34. VCC -- 15脚, 3.3V
  35. CLK -- 14脚, GPIO11/SPI0_CLK/LCD_CLK, 时钟. 如果是1.4版本的开发板, 接05脚的GPIO11/UART2_TXD
  36. MOSI -- 13脚, GPIO09/SPI0_MOSI/LCD_OUT,主控数据输出
  37. MISO -- 11脚, GPIO10/SPI0_MISO/LCD_RS,主控数据输入. 如果是1.4版本的开发板, 接06脚的GPIO10/UART2_RXD
  38. CS -- 10脚, GPIO08/SPI0_CS/LCD_CS,片选.
  39. 注意: 12脚是跳过的, 接线完毕后请检查好再通电!!
  40. ]]
  41. local taskName = "task_audio"
  42. local MSG_MD = "moreData" -- 播放缓存有空余
  43. local MSG_PD = "playDone" -- 播放完成所有数据
  44. audio.on(0, function(id, event)
  45. -- 使用play来播放文件时只有播放完成回调
  46. local succ, stop, file_cnt = audio.getError(0)
  47. if not succ then
  48. if stop then
  49. log.info("用户停止播放")
  50. else
  51. log.info("第", file_cnt, "个文件解码失败")
  52. end
  53. end
  54. sysplus.sendMsg(taskName, MSG_PD)
  55. end)
  56. local function audio_task()
  57. --Air780E开发板配套+音频扩展板. ES8211
  58. --由于音频扩展板的PA是长供电的,有塔塔声音是正常的,做产品的话有额外的参考设计
  59. --i2s.setup(0, 0, 0, 0, 0, i2s.MODE_MSB)
  60. --如果用软件DAC,打开下面的注释
  61. if audio.setBus then
  62. audio.setBus(audio.BUS_SOFT_DAC)
  63. end
  64. audio.config(0, 25, 1, 6, 200)
  65. gpio.setup(24, 0)
  66. gpio.setup(23, 0)
  67. gpio.setup(27, 0)
  68. gpio.setup(2, 0)
  69. -- 初始化spi flash, 如果是极限版TTS_ONCHIP,就不需要初始化
  70. -- if sfud then
  71. -- spi_flash = spi.deviceSetup(0,8,0,0,8,25600000,spi.MSB,1,0)
  72. -- local ret = sfud.init(spi_flash)
  73. -- if ret then
  74. -- log.info("sfud.init ok")
  75. -- else
  76. -- log.info("sfud.init error", ret)
  77. -- return
  78. -- end
  79. -- end
  80. log.info("开始播放音频")
  81. result = audio.play(0, {"/audio.mp3"})
  82. if result then
  83. -- 等待音频通道的回调消息,或者切换歌曲的消息
  84. while true do
  85. msg = sysplus.waitMsg(taskName, nil)
  86. if type(msg) == 'table' then
  87. if msg[1] == MSG_PD then
  88. log.info("音频播放结束")
  89. sys.publish("audio_end")
  90. break
  91. end
  92. else
  93. log.error(type(msg), msg)
  94. end
  95. end
  96. else
  97. log.debug("解码失败!")
  98. sys.wait(1000)
  99. end
  100. if not audio.isEnd(0) then
  101. log.info("手动关闭")
  102. audio.playStop(0)
  103. end
  104. -- sys.wait(1000)
  105. sysplus.taskDel(taskName)
  106. end
  107. local function tts_task()
  108. --Air780E开发板配套+音频扩展板. ES8211
  109. --由于音频扩展板的PA是长供电的,有塔塔声音是正常的,做产品的话有额外的参考设计
  110. --i2s.setup(0, 0, 0, 0, 0, i2s.MODE_MSB)
  111. --如果用软件DAC,打开下面的注释。 注意此功能适配pwm音频播放开发板,由于MP3文件是32K现在PWM还不支持,播出来的声音会比较慢
  112. if audio.setBus then
  113. audio.setBus(audio.BUS_SOFT_DAC)
  114. end
  115. audio.config(0, 25, 1, 6, 200)
  116. gpio.setup(24, 0)
  117. gpio.setup(23, 0)
  118. gpio.setup(27, 0)
  119. gpio.setup(2, 0)
  120. -- 初始化spi flash, 如果是极限版TTS_ONCHIP,就不需要初始化,
  121. -- if sfud then
  122. -- spi_flash = spi.deviceSetup(0,8,0,0,8,25600000,spi.MSB,1,0)
  123. -- local ret = sfud.init(spi_flash)
  124. -- if ret then
  125. -- log.info("sfud.init ok")
  126. -- else
  127. -- log.info("sfud.init error", ret)
  128. -- return
  129. -- end
  130. -- end
  131. log.info("开始播放TTS")
  132. local result, data = sys.waitUntil("TTS_msg")
  133. result = audio.tts(0, data)
  134. if result then
  135. -- 等待音频通道的回调消息,或者切换歌曲的消息
  136. while true do
  137. msg = sysplus.waitMsg(taskName, nil)
  138. if type(msg) == 'table' then
  139. if msg[1] == MSG_PD then
  140. log.info("TTS播放结束")
  141. sys.publish("audio_end")
  142. break
  143. end
  144. else
  145. log.error(type(msg), msg)
  146. end
  147. end
  148. else
  149. log.debug("解码失败!")
  150. sys.wait(1000)
  151. end
  152. if not audio.isEnd(0) then
  153. log.info("手动关闭")
  154. audio.playStop(0)
  155. end
  156. -- sys.wait(1000)
  157. sysplus.taskDel(taskName)
  158. end
  159. sys.subscribe("Audio_msg",function() sysplus.taskInitEx(audio_task, taskName, task_cb) end)
  160. sys.subscribe("TTS_msg",function() sysplus.taskInitEx(tts_task, taskName, task_cb) end)