luat_audio_air105.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /*
  2. * Copyright (c) 2022 OpenLuat & AirM2M
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  5. * this software and associated documentation files (the "Software"), to deal in
  6. * the Software without restriction, including without limitation the rights to
  7. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  8. * the Software, and to permit persons to whom the Software is furnished to do so,
  9. * subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in all
  12. * copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  16. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  17. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  18. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  19. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. */
  21. #include "luat_base.h"
  22. #include "luat_msgbus.h"
  23. #include "luat_fs.h"
  24. #include <stdlib.h>
  25. #include "luat_multimedia.h"
  26. #include "app_interface.h"
  27. #include "mp3_decode/minimp3.h"
  28. #define LUAT_LOG_TAG "audio"
  29. #include "luat_log.h"
  30. #include "luat_audio.h"
  31. //#define __DECODE_DEBUG__
  32. #ifdef __DECODE_DEBUG__
  33. #define STEP(X) Stream->DecodeStep=X
  34. #else
  35. #define STEP(X)
  36. #endif
  37. #define MP3_FRAME_LEN 4 * 1152
  38. static Audio_StreamStruct prvAudioStream;
  39. int luat_audio_write_blank_raw(uint32_t multimedia_id, uint8_t cnt);
  40. static int32_t luat_audio_wav_decode(void *pData, void *pParam)
  41. {
  42. Audio_StreamStruct *Stream = (Audio_StreamStruct *)pData;
  43. while ( (llist_num(&Stream->DataHead) < 3) && !Stream->IsStop)
  44. {
  45. Stream->FileDataBuffer.Pos = luat_fs_fread(Stream->FileDataBuffer.Data, Stream->FileDataBuffer.MaxLen, 1, Stream->fd);
  46. if (Stream->FileDataBuffer.Pos > 0)
  47. {
  48. if (!Stream->IsStop)
  49. {
  50. Audio_WriteRaw(Stream, Stream->FileDataBuffer.Data, Stream->FileDataBuffer.Pos, 0);
  51. }
  52. }
  53. else
  54. {
  55. return 0;
  56. }
  57. }
  58. return 0;
  59. }
  60. static int32_t luat_audio_mp3_decode(void *pData, void *pParam)
  61. {
  62. uint32_t pos = 0;
  63. int read_len;
  64. int result;
  65. mp3dec_frame_info_t info;
  66. mp3dec_t *mp3_decoder = (mp3dec_t *)pParam;
  67. Audio_StreamStruct *Stream = (Audio_StreamStruct *)pData;
  68. Stream->AudioDataBuffer.Pos = 0;
  69. STEP(1);
  70. while ((llist_num(&Stream->DataHead) < 4) && (Stream->IsFileNotEnd || Stream->FileDataBuffer.Pos > 2)&& !Stream->IsStop)
  71. {
  72. STEP(2);
  73. while (( Stream->AudioDataBuffer.Pos < (Stream->AudioDataBuffer.MaxLen - MP3_FRAME_LEN * 2) ) && (Stream->IsFileNotEnd || Stream->FileDataBuffer.Pos > 2) && !Stream->IsStop)
  74. {
  75. STEP(3);
  76. if (Stream->FileDataBuffer.Pos < MINIMP3_MAX_SAMPLES_PER_FRAME)
  77. {
  78. if (Stream->IsFileNotEnd)
  79. {
  80. read_len = luat_fs_fread(Stream->FileDataBuffer.Data + Stream->FileDataBuffer.Pos, MINIMP3_MAX_SAMPLES_PER_FRAME, 1, Stream->fd);
  81. if (read_len > 0)
  82. {
  83. Stream->FileDataBuffer.Pos += read_len;
  84. }
  85. else
  86. {
  87. Stream->IsFileNotEnd = 0;
  88. }
  89. }
  90. }
  91. pos = 0;
  92. STEP(4);
  93. do
  94. {
  95. memset(&info, 0, sizeof(info));
  96. STEP(5);
  97. result = mp3dec_decode_frame(mp3_decoder, Stream->FileDataBuffer.Data + pos, Stream->FileDataBuffer.Pos - pos,
  98. (mp3d_sample_t *)&Stream->AudioDataBuffer.Data[Stream->AudioDataBuffer.Pos], &info);
  99. STEP(6);
  100. if (result > 0)
  101. {
  102. Stream->AudioDataBuffer.Pos += (result * info.channels * 2);
  103. }
  104. pos += info.frame_bytes;
  105. if (Stream->AudioDataBuffer.Pos >= (Stream->AudioDataBuffer.MaxLen - MP3_FRAME_LEN * 2))
  106. {
  107. break;
  108. }
  109. } while ( ((Stream->FileDataBuffer.Pos - pos) >= (MINIMP3_MAX_SAMPLES_PER_FRAME * Stream->IsFileNotEnd + 1)) && !Stream->IsStop);
  110. STEP(7);
  111. OS_BufferRemove(&Stream->FileDataBuffer, pos);
  112. }
  113. if (!Stream->IsStop)
  114. {
  115. STEP(8);
  116. Audio_WriteRaw(Stream, Stream->AudioDataBuffer.Data, Stream->AudioDataBuffer.Pos, 0);
  117. STEP(9);
  118. }
  119. Stream->AudioDataBuffer.Pos = 0;
  120. }
  121. STEP(0);
  122. return 0;
  123. }
  124. static int32_t luat_audio_pa_on(void *pData, void *pParam)
  125. {
  126. if (prvAudioStream.UseOutPA)
  127. {
  128. GPIO_Output(prvAudioStream.PAPin, prvAudioStream.PAOnLevel);
  129. }
  130. }
  131. int32_t luat_audio_decode_run(void *pData, void *pParam)
  132. {
  133. if (!prvAudioStream.IsStop)
  134. {
  135. prvAudioStream.Decoder(pData, pParam);
  136. }
  137. if (prvAudioStream.waitRequire)
  138. {
  139. prvAudioStream.waitRequire--;
  140. }
  141. }
  142. int32_t luat_audio_app_cb(void *pData, void *pParam)
  143. {
  144. rtos_msg_t msg = {0};
  145. msg.handler = l_multimedia_raw_handler;
  146. msg.arg1 = (pParam == INVALID_HANDLE_VALUE)?MULTIMEDIA_CB_AUDIO_DONE:MULTIMEDIA_CB_AUDIO_NEED_DATA;
  147. msg.arg2 = prvAudioStream.pParam;
  148. luat_msgbus_put(&msg, 1);
  149. return 0;
  150. }
  151. int32_t luat_audio_play_cb(void *pData, void *pParam)
  152. {
  153. Audio_StreamStruct *Stream = (Audio_StreamStruct *)pData;
  154. if (pParam == INVALID_HANDLE_VALUE)
  155. {
  156. rtos_msg_t msg = {0};
  157. msg.handler = l_multimedia_raw_handler;
  158. msg.arg1 = MULTIMEDIA_CB_AUDIO_DONE;
  159. msg.arg2 = prvAudioStream.pParam;
  160. luat_msgbus_put(&msg, 1);
  161. }
  162. else
  163. {
  164. if (!prvAudioStream.IsStop)
  165. {
  166. prvAudioStream.waitRequire++;
  167. if (prvAudioStream.waitRequire > 2)
  168. {
  169. DBG("%d,%d,%u,%u", prvAudioStream.waitRequire, prvAudioStream.DecodeStep,prvAudioStream.FileDataBuffer.Pos,prvAudioStream.AudioDataBuffer.Pos);
  170. }
  171. Core_ServiceRunUserAPIWithFile(luat_audio_decode_run, &prvAudioStream, prvAudioStream.CoderParam);
  172. }
  173. }
  174. return 0;
  175. }
  176. int luat_audio_start_raw(uint8_t multimedia_id, uint8_t audio_format, uint8_t num_channels, uint32_t sample_rate, uint8_t bits_per_sample, uint8_t is_signed)
  177. {
  178. prvAudioStream.pParam = multimedia_id;
  179. if (prvAudioStream.fd) {
  180. prvAudioStream.CB = luat_audio_play_cb;
  181. } else {
  182. prvAudioStream.CB = luat_audio_app_cb;
  183. }
  184. prvAudioStream.BitDepth = bits_per_sample;
  185. prvAudioStream.BusType = AUSTREAM_BUS_DAC;
  186. prvAudioStream.BusID = 0;
  187. prvAudioStream.Format = audio_format;
  188. prvAudioStream.ChannelCount = num_channels;
  189. prvAudioStream.SampleRate = sample_rate;
  190. prvAudioStream.IsDataSigned = is_signed;
  191. GPIO_Iomux(GPIOC_01, 2);
  192. int result = Audio_StartRaw(&prvAudioStream);
  193. if (!result)
  194. {
  195. if (prvAudioStream.DummyAudioTime)
  196. {
  197. luat_audio_write_blank_raw(multimedia_id, prvAudioStream.DummyAudioTime);
  198. }
  199. if (prvAudioStream.PADelayTimer)
  200. {
  201. Timer_StartMS(prvAudioStream.PADelayTimer, prvAudioStream.PADelayTime, 0);
  202. }
  203. }
  204. return result;
  205. }
  206. int luat_audio_write_blank_raw(uint32_t multimedia_id, uint8_t cnt)
  207. {
  208. uint32_t total = ((prvAudioStream.SampleRate / 10) * prvAudioStream.ChannelCount * (prvAudioStream.BitDepth / 8) );
  209. uint8_t *dummy = malloc(total);
  210. memset(dummy, 0, total);
  211. for(int i = 0 ; i < cnt; i++)
  212. {
  213. Audio_WriteRaw(&prvAudioStream, dummy, total, 1);
  214. }
  215. free(dummy);
  216. return 0;
  217. }
  218. int luat_audio_write_raw(uint8_t multimedia_id, uint8_t *data, uint32_t len)
  219. {
  220. if (len)
  221. return Audio_WriteRaw(&prvAudioStream, data, len, 0);
  222. return -1;
  223. }
  224. int luat_audio_stop_raw(uint8_t multimedia_id)
  225. {
  226. if (prvAudioStream.UseOutPA)
  227. {
  228. GPIO_Output(prvAudioStream.PAPin, !prvAudioStream.PAOnLevel);
  229. }
  230. if (prvAudioStream.PADelayTimer)
  231. {
  232. Timer_Stop(prvAudioStream.PADelayTimer);
  233. }
  234. Audio_Stop(&prvAudioStream);
  235. OS_DeInitBuffer(&prvAudioStream.FileDataBuffer);
  236. OS_DeInitBuffer(&prvAudioStream.AudioDataBuffer);
  237. if (prvAudioStream.fd)
  238. {
  239. luat_fs_fclose(prvAudioStream.fd);
  240. prvAudioStream.fd = NULL;
  241. }
  242. if (prvAudioStream.CoderParam)
  243. {
  244. luat_heap_free(prvAudioStream.CoderParam);
  245. prvAudioStream.CoderParam = NULL;
  246. }
  247. prvAudioStream.IsStop = 0;
  248. prvAudioStream.IsPlaying = 0;
  249. prvAudioStream.waitRequire = 0;
  250. return ERROR_NONE;
  251. }
  252. int luat_audio_pause_raw(uint8_t multimedia_id, uint8_t is_pause)
  253. {
  254. if (is_pause)
  255. {
  256. Audio_Pause(&prvAudioStream);
  257. }
  258. else
  259. {
  260. Audio_Resume(&prvAudioStream);
  261. }
  262. return ERROR_NONE;
  263. }
  264. int luat_audio_play_stop(uint8_t multimedia_id)
  265. {
  266. prvAudioStream.IsStop = 1;
  267. prvAudioStream.LastError = -1;
  268. }
  269. uint8_t luat_audio_is_finish(uint8_t multimedia_id)
  270. {
  271. ASSERT(prvAudioStream.waitRequire < 5);
  272. return !prvAudioStream.waitRequire;
  273. }
  274. int luat_audio_play_multi_files(uint8_t multimedia_id, uData_t *info, uint32_t files_num, uint8_t error_stop)
  275. {
  276. return -1;
  277. }
  278. int luat_audio_play_file(uint8_t multimedia_id, const char *path)
  279. {
  280. if (prvAudioStream.IsPlaying)
  281. {
  282. luat_audio_stop_raw(multimedia_id);
  283. }
  284. uint32_t jump, i;
  285. uint8_t temp[16];
  286. mp3dec_t *mp3_decoder;
  287. int result;
  288. int audio_format = MULTIMEDIA_DATA_TYPE_PCM;
  289. int num_channels;
  290. int sample_rate;
  291. int bits_per_sample = 16;
  292. uint32_t align;
  293. int is_signed = 1;
  294. size_t len;
  295. mp3dec_frame_info_t info;
  296. FILE *fd = luat_fs_fopen(path, "r");
  297. if (!fd)
  298. {
  299. return -1;
  300. }
  301. luat_fs_fread(temp, 12, 1, fd);
  302. if (!memcmp(temp, "ID3", 3) || (temp[0] == 0xff))
  303. {
  304. if (temp[0] != 0xff)
  305. {
  306. jump = 0;
  307. for(i = 0; i < 4; i++)
  308. {
  309. jump <<= 7;
  310. jump |= temp[6 + i] & 0x7f;
  311. }
  312. // LLOGD("jump head %d", jump);
  313. luat_fs_fseek(fd, jump, SEEK_SET);
  314. }
  315. else
  316. {
  317. luat_fs_fseek(fd, 0, SEEK_SET);
  318. }
  319. mp3_decoder = luat_heap_malloc(sizeof(mp3dec_t));
  320. memset(mp3_decoder, 0, sizeof(mp3dec_t));
  321. mp3dec_init(mp3_decoder);
  322. OS_InitBuffer(&prvAudioStream.FileDataBuffer, MP3_FRAME_LEN);
  323. prvAudioStream.FileDataBuffer.Pos = luat_fs_fread(prvAudioStream.FileDataBuffer.Data, MP3_FRAME_LEN, 1, fd);
  324. result = mp3dec_decode_frame(mp3_decoder, prvAudioStream.FileDataBuffer.Data, prvAudioStream.FileDataBuffer.Pos, NULL, &info);
  325. if (result)
  326. {
  327. prvAudioStream.CoderParam = mp3_decoder;
  328. memset(mp3_decoder, 0, sizeof(mp3dec_t));
  329. num_channels = info.channels;
  330. sample_rate = info.hz;
  331. len = (num_channels * sample_rate >> 2); //一次时间为1/16秒
  332. OS_ReInitBuffer(&prvAudioStream.AudioDataBuffer, len + MP3_FRAME_LEN * 2); //防止溢出,需要多一点空间
  333. prvAudioStream.Decoder = luat_audio_mp3_decode;
  334. }
  335. else
  336. {
  337. luat_heap_free(mp3_decoder);
  338. }
  339. }
  340. else if (!memcmp(temp, "RIFF", 4) || !memcmp(temp + 8, "WAVE", 4))
  341. {
  342. result = 0;
  343. prvAudioStream.CoderParam = NULL;
  344. OS_DeInitBuffer(&prvAudioStream.AudioDataBuffer);
  345. luat_fs_fread(temp, 8, 1, fd);
  346. if (!memcmp(temp, "fmt ", 4))
  347. {
  348. memcpy(&len, temp + 4, 4);
  349. OS_InitBuffer(&prvAudioStream.FileDataBuffer, len);
  350. luat_fs_fread(prvAudioStream.FileDataBuffer.Data, len, 1, fd);
  351. audio_format = prvAudioStream.FileDataBuffer.Data[0];
  352. num_channels = prvAudioStream.FileDataBuffer.Data[2];
  353. memcpy(&sample_rate, prvAudioStream.FileDataBuffer.Data + 4, 4);
  354. align = prvAudioStream.FileDataBuffer.Data[12];
  355. bits_per_sample = prvAudioStream.FileDataBuffer.Data[14];
  356. len = ((align * sample_rate) >> 3) & ~(3); //一次时间为1/8秒
  357. OS_ReInitBuffer(&prvAudioStream.FileDataBuffer, len);
  358. luat_fs_fread(temp, 8, 1, fd);
  359. if (!memcmp(temp, "fact", 4))
  360. {
  361. memcpy(&len, temp + 4, 4);
  362. luat_fs_fseek(fd, len, SEEK_CUR);
  363. luat_fs_fread(temp, 8, 1, fd);
  364. }
  365. if (!memcmp(temp, "data", 4))
  366. {
  367. result = 1;
  368. prvAudioStream.Decoder = luat_audio_wav_decode;
  369. }
  370. }
  371. }
  372. else
  373. {
  374. result = 0;
  375. }
  376. if (result)
  377. {
  378. prvAudioStream.fd = fd;
  379. result = luat_audio_start_raw(multimedia_id, audio_format, num_channels, sample_rate, bits_per_sample, is_signed);
  380. if (!result)
  381. {
  382. LLOGD("decode %s ok,param,%d,%d,%d,%d,%d,%d,%u,%u", path,multimedia_id, audio_format, num_channels, sample_rate, bits_per_sample, is_signed, prvAudioStream.FileDataBuffer.MaxLen, prvAudioStream.AudioDataBuffer.MaxLen);
  383. prvAudioStream.IsPlaying = 1;
  384. prvAudioStream.pParam = multimedia_id;
  385. prvAudioStream.IsFileNotEnd = 1;
  386. prvAudioStream.Decoder(&prvAudioStream, prvAudioStream.CoderParam);
  387. prvAudioStream.LastError = 0;
  388. if (!llist_num(&prvAudioStream.DataHead))
  389. {
  390. prvAudioStream.fd = NULL;
  391. }
  392. else
  393. {
  394. return 0;
  395. }
  396. }
  397. else
  398. {
  399. prvAudioStream.fd = 0;
  400. }
  401. }
  402. luat_fs_fclose(fd);
  403. OS_DeInitBuffer(&prvAudioStream.FileDataBuffer);
  404. OS_DeInitBuffer(&prvAudioStream.AudioDataBuffer);
  405. if (prvAudioStream.CoderParam)
  406. {
  407. luat_heap_free(prvAudioStream.CoderParam);
  408. prvAudioStream.CoderParam = NULL;
  409. }
  410. return -1;
  411. }
  412. void luat_audio_config_pa(uint8_t multimedia_id, uint32_t pin, int level, uint32_t dummy_time_len, uint32_t pa_delay_time)
  413. {
  414. if (pin < GPIO_NONE)
  415. {
  416. prvAudioStream.PAPin = pin;
  417. prvAudioStream.PAOnLevel = level;
  418. prvAudioStream.UseOutPA = 1;
  419. GPIO_Config(prvAudioStream.PAPin, 0, !prvAudioStream.PAOnLevel);
  420. }
  421. else
  422. {
  423. prvAudioStream.UseOutPA = 0;
  424. }
  425. prvAudioStream.DummyAudioTime = dummy_time_len;
  426. prvAudioStream.PADelayTime = pa_delay_time;
  427. if (!prvAudioStream.PADelayTimer && prvAudioStream.PADelayTime)
  428. {
  429. prvAudioStream.PADelayTimer = Timer_Create(luat_audio_pa_on, NULL, NULL);
  430. }
  431. }
  432. void luat_audio_config_dac(uint8_t multimedia_id, int pin, int level)
  433. {
  434. }
  435. uint16_t luat_audio_vol(uint8_t multimedia_id, uint16_t vol)
  436. {
  437. return 100;
  438. }
  439. int luat_audio_play_get_last_error(uint8_t multimedia_id)
  440. {
  441. return prvAudioStream.LastError;
  442. }