es8311.lua 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. audio.on(0, function(id, event)
  2. --使用play来播放文件时只有播放完成回调
  3. local succ,stop,file_cnt = audio.getError(0)
  4. if not succ then
  5. if stop then
  6. log.info("用户停止播放")
  7. else
  8. log.info("第", file_cnt, "个文件解码失败")
  9. end
  10. end
  11. -- log.info("播放完成一个音频")
  12. sys.publish("AUDIO_PLAY_DONE")
  13. end)
  14. local i2c_id = 1
  15. local i2s_id = 0
  16. local samplerate = 16000 --支持内部amr编码的soc才能用
  17. -- es8311器件地址
  18. local es8311_address = 0x18
  19. local record_cnt = 0
  20. -- es8311初始化寄存器配置
  21. local es8311_reg = {
  22. {0x45,0x00},
  23. {0x01,0x30},
  24. {0x02,0x10},
  25. {0x02,0x00},
  26. {0x03,0x10},
  27. {0x16,0x24},
  28. {0x04,0x20},
  29. {0x05,0x00},
  30. {0x06,3},
  31. {0x07,0x00},
  32. {0x08,0xFF},
  33. {0x09,0x0C},
  34. {0x0A,0x0C},
  35. {0x0B,0x00},
  36. {0x0C,0x00},
  37. {0x10,0x03},
  38. {0x11,0x7F},
  39. {0x00,0x80},
  40. {0x0D,0x01},
  41. {0x01,0x3F},
  42. {0x14,0x1a},
  43. {0x12,0x28},
  44. {0x13,0x00},
  45. {0x0E,0x02},
  46. {0x0F,0x44},
  47. {0x15,0x00},
  48. {0x1B,0x0A},
  49. {0x1C,0x6A},
  50. {0x37,0x48},
  51. {0x44,(0 <<7)},
  52. {0x17,210},
  53. {0x32,200},
  54. }
  55. -- i2s数据接收buffer
  56. local rx_buff = zbuff.create(3200)
  57. -- amr数据存放buffer,尽可能地给大一些
  58. local amr_buff = zbuff.create(20 * 1024)
  59. --创建一个amr的encoder
  60. local encoder
  61. -- 录音文件路径
  62. local recordPath = "/record.amr"
  63. -- i2s数据接收回调
  64. local function record_cb(id, buff)
  65. if buff then
  66. log.info("I2S", id, "接收了", rx_buff:used())
  67. log.info("编码结果", codec.encode(encoder, rx_buff, amr_buff)) -- 对录音数据进行amr编码,成功的话这个接口会返回true, 默认编码等级为MR475
  68. record_cnt = record_cnt + 1
  69. if samplerate > 8000 then
  70. if record_cnt >= 50 then --超过5秒后停止
  71. log.info("I2S", "stop")
  72. i2s.stop(i2s_id)
  73. end
  74. else
  75. if record_cnt >= 25 then --超过5秒后停止
  76. log.info("I2S", "stop")
  77. i2s.stop(i2s_id)
  78. end
  79. end
  80. end
  81. end
  82. ---- MultipartForm上传文件
  83. -- url string 请求URL地址
  84. -- filename string 上传服务器的文件名
  85. -- filePath string 待上传文件的路径
  86. local function postMultipartFormData(url, filename, filePath)
  87. local boundary = "----WebKitFormBoundary"..os.time()
  88. local req_headers = {
  89. ["Content-Type"] = "multipart/form-data; boundary=" .. boundary,
  90. }
  91. local body = {}
  92. table.insert(body, "--"..boundary.."\r\nContent-Disposition: form-data; name=\"file\"; filename=\"".. filename .."\"\r\n\r\n")
  93. table.insert(body, io.readFile(filePath))
  94. table.insert(body, "\r\n")
  95. table.insert(body, "--"..boundary.."--\r\n")
  96. body = table.concat(body)
  97. log.info("headers: ", "\r\n" .. json.encode(req_headers), type(body))
  98. log.info("body: " .. body:len() .. "\r\n" .. body)
  99. local code, headers, body = http.request("POST",url,
  100. req_headers,
  101. body
  102. ).wait()
  103. log.info("http.post", code, headers, body)
  104. end
  105. local function record_task()
  106. os.remove(recordPath)
  107. audio.config(0, 25, 1, 6, 200)
  108. pm.power(pm.LDO_CTL, true) -- 打开es8311芯片供电
  109. --自适应开发板,自己做的板子不需要2个I2C都用
  110. i2c.setup(0, i2c.FAST)
  111. i2c.setup(1, i2c.FAST)
  112. if i2c.send(0, 0x18, 0xfd) == true then
  113. log.info("音频小板", "codec on i2c0")
  114. end
  115. if i2c.send(1, 0x18, 0xfd) == true then
  116. log.info("云喇叭开发板", "codec on i2c1")
  117. power_pin = nil
  118. i2c_id = 1
  119. end
  120. for i, v in pairs(es8311_reg) do -- 初始化es8311
  121. i2c.send(i2c_id, es8311_address, v, 1)
  122. end
  123. if samplerate > 8000 then
  124. encoder = codec.create(codec.AMR_WB, false, 7)
  125. if encoder == nil then
  126. log.info("不支持16K编码,改成8K采样")
  127. samplerate = 8000
  128. encoder = codec.create(codec.AMR, false, 7)
  129. end
  130. else
  131. encoder = codec.create(codec.AMR, false, 7)
  132. end
  133. i2s.setup(i2s_id, 1, samplerate, 16, 1, i2s.MODE_LSB) -- 开启i2s
  134. i2s.on(i2s_id, record_cb) -- 注册i2s接收回调
  135. i2s.recv(i2s_id, rx_buff, 3200)
  136. i2c.send(i2c_id, es8311_address, {0x00, 0xc0}, 1)
  137. sys.wait(6000)
  138. i2c.send(i2c_id, es8311_address, {0x00, 0x80}, 1) -- ES8311停止录音
  139. log.info("录音5秒结束")
  140. codec.release(encoder)
  141. codec = nil
  142. if samplerate > 8000 then
  143. io.writeFile(recordPath, "#!AMR-WB\n") -- 向文件写入amr文件标识数据
  144. else
  145. io.writeFile(recordPath, "#!AMR\n") -- 向文件写入amr文件标识数据
  146. end
  147. io.writeFile(recordPath, amr_buff:query(), "a+b") -- 向文件写入编码后的amr数据
  148. i2s.setup(i2s_id, 0, 0, 0, 0, i2s.MODE_LSB)
  149. local result = audio.play(0, {recordPath}) -- 请求音频播放
  150. log.info("音频播放结果", result)
  151. if result then
  152. sys.waitUntil("AUDIO_PLAY_DONE") -- 等待音频播放完毕
  153. else
  154. -- 音频播放出错
  155. end
  156. -- 下面的演示是将音频文件发送到服务器上,如有需要,可以将下面代码注释打开,这里的url是合宙的文件上传测试服务器,上传的文件到http://tools.openluat.com/tools/device-upload-test查看
  157. --[[
  158. local timeTable = os.date("*t", os.time())
  159. local nowTime = string.format("%4d%02d%02d_%02d%02d%02d", timeTable.year, timeTable.month, timeTable.day, timeTable.hour, timeTable.min, timeTable.sec)
  160. local filename = mobile.imei() .. "_" .. nowTime .. ".amr"
  161. postMultipartFormData("http://tools.openluat.com/api/site/device_upload_file", filename, recordPath)
  162. ]]
  163. uart.setup(1, 115200) -- 开启串口1
  164. uart.write(1, io.readFile(recordPath)) -- 向串口发送录音文件
  165. end
  166. sys.taskInit(record_task)