audio.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2017-05-09 Urey first version
  9. * 2019-07-09 Zero-Free improve device ops interface and data flows
  10. */
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <rthw.h>
  14. #include <rtthread.h>
  15. #include <rtdevice.h>
  16. #define DBG_TAG "audio"
  17. #define DBG_LVL DBG_INFO
  18. #include <rtdbg.h>
  19. #ifndef MIN
  20. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  21. #endif
  22. enum
  23. {
  24. REPLAY_EVT_NONE = 0x00,
  25. REPLAY_EVT_START = 0x01,
  26. REPLAY_EVT_STOP = 0x02,
  27. };
  28. static rt_err_t _audio_send_replay_frame(struct rt_audio_device *audio)
  29. {
  30. rt_err_t result = RT_EOK;
  31. rt_uint8_t *data;
  32. rt_size_t dst_size, src_size;
  33. rt_uint16_t position, remain_bytes = 0, index = 0;
  34. struct rt_audio_buf_info *buf_info;
  35. RT_ASSERT(audio != RT_NULL);
  36. buf_info = &audio->replay->buf_info;
  37. /* save current pos */
  38. position = audio->replay->pos;
  39. dst_size = buf_info->block_size;
  40. /* check repaly queue is empty */
  41. if (rt_data_queue_peak(&audio->replay->queue, (const void **)&data, &src_size) != RT_EOK)
  42. {
  43. /* ack stop event */
  44. if (audio->replay->event & REPLAY_EVT_STOP)
  45. rt_completion_done(&audio->replay->cmp);
  46. /* send zero frames */
  47. memset(&buf_info->buffer[audio->replay->pos], 0, dst_size);
  48. audio->replay->pos += dst_size;
  49. audio->replay->pos %= buf_info->total_size;
  50. }
  51. else
  52. {
  53. memset(&buf_info->buffer[audio->replay->pos], 0, dst_size);
  54. /* copy data from memory pool to hardware device fifo */
  55. while (index < dst_size)
  56. {
  57. result = rt_data_queue_peak(&audio->replay->queue, (const void **)&data, &src_size);
  58. if (result != RT_EOK)
  59. {
  60. LOG_D("under run %d, remain %d", audio->replay->pos, remain_bytes);
  61. audio->replay->pos -= remain_bytes;
  62. audio->replay->pos += dst_size;
  63. audio->replay->pos %= buf_info->total_size;
  64. audio->replay->read_index = 0;
  65. result = -RT_EEMPTY;
  66. break;
  67. }
  68. remain_bytes = MIN((dst_size - index), (src_size - audio->replay->read_index));
  69. memcpy(&buf_info->buffer[audio->replay->pos],
  70. &data[audio->replay->read_index], remain_bytes);
  71. index += remain_bytes;
  72. audio->replay->read_index += remain_bytes;
  73. audio->replay->pos += remain_bytes;
  74. audio->replay->pos %= buf_info->total_size;
  75. if (audio->replay->read_index == src_size)
  76. {
  77. /* free memory */
  78. audio->replay->read_index = 0;
  79. rt_data_queue_pop(&audio->replay->queue, (const void **)&data, &src_size, RT_WAITING_NO);
  80. rt_mp_free(data);
  81. /* notify transmitted complete. */
  82. if (audio->parent.tx_complete != RT_NULL)
  83. audio->parent.tx_complete(&audio->parent, (void *)data);
  84. }
  85. }
  86. }
  87. if (audio->ops->transmit != RT_NULL)
  88. {
  89. if (audio->ops->transmit(audio, &buf_info->buffer[position], RT_NULL, dst_size) != dst_size)
  90. result = -RT_ERROR;
  91. }
  92. return result;
  93. }
  94. static rt_err_t _audio_flush_replay_frame(struct rt_audio_device *audio)
  95. {
  96. rt_err_t result = RT_EOK;
  97. if (audio->replay->write_index)
  98. {
  99. result = rt_data_queue_push(&audio->replay->queue,
  100. (const void **)audio->replay->write_data,
  101. audio->replay->write_index,
  102. RT_WAITING_FOREVER);
  103. audio->replay->write_index = 0;
  104. }
  105. return result;
  106. }
  107. static rt_err_t _aduio_replay_start(struct rt_audio_device *audio)
  108. {
  109. rt_err_t result = RT_EOK;
  110. if (audio->replay->activated != RT_TRUE)
  111. {
  112. /* start playback hardware device */
  113. if (audio->ops->start)
  114. result = audio->ops->start(audio, AUDIO_STREAM_REPLAY);
  115. audio->replay->activated = RT_TRUE;
  116. LOG_D("start audio replay device");
  117. }
  118. return result;
  119. }
  120. static rt_err_t _aduio_replay_stop(struct rt_audio_device *audio)
  121. {
  122. rt_err_t result = RT_EOK;
  123. if (audio->replay->activated == RT_TRUE)
  124. {
  125. /* flush replay remian frames */
  126. _audio_flush_replay_frame(audio);
  127. /* notify irq(or thread) to stop the data transmission */
  128. audio->replay->event |= REPLAY_EVT_STOP;
  129. /* waiting for the remaining data transfer to complete */
  130. rt_completion_init(&audio->replay->cmp);
  131. rt_completion_wait(&audio->replay->cmp, RT_WAITING_FOREVER);
  132. audio->replay->event &= ~REPLAY_EVT_STOP;
  133. /* stop playback hardware device */
  134. if (audio->ops->stop)
  135. result = audio->ops->stop(audio, AUDIO_STREAM_REPLAY);
  136. audio->replay->activated = RT_FALSE;
  137. LOG_D("stop audio replay device");
  138. }
  139. return result;
  140. }
  141. static rt_err_t _audio_record_start(struct rt_audio_device *audio)
  142. {
  143. rt_err_t result = RT_EOK;
  144. if (audio->record->activated != RT_TRUE)
  145. {
  146. /* open audio record pipe */
  147. rt_device_open(RT_DEVICE(&audio->record->pipe), RT_DEVICE_OFLAG_RDONLY);
  148. /* start record hardware device */
  149. if (audio->ops->start)
  150. result = audio->ops->start(audio, AUDIO_STREAM_RECORD);
  151. audio->record->activated = RT_TRUE;
  152. LOG_D("start audio record device");
  153. }
  154. return result;
  155. }
  156. static rt_err_t _audio_record_stop(struct rt_audio_device *audio)
  157. {
  158. rt_err_t result = RT_EOK;
  159. if (audio->record->activated == RT_TRUE)
  160. {
  161. /* stop record hardware device */
  162. if (audio->ops->stop)
  163. result = audio->ops->stop(audio, AUDIO_STREAM_RECORD);
  164. /* close audio record pipe */
  165. rt_device_close(RT_DEVICE(&audio->record->pipe));
  166. audio->record->activated = RT_FALSE;
  167. LOG_D("stop audio record device");
  168. }
  169. return result;
  170. }
  171. static rt_err_t _audio_dev_init(struct rt_device *dev)
  172. {
  173. rt_err_t result = RT_EOK;
  174. struct rt_audio_device *audio;
  175. RT_ASSERT(dev != RT_NULL);
  176. audio = (struct rt_audio_device *) dev;
  177. /* initialize replay & record */
  178. audio->replay = RT_NULL;
  179. audio->record = RT_NULL;
  180. /* initialize replay */
  181. if (dev->flag & RT_DEVICE_FLAG_WRONLY)
  182. {
  183. struct rt_audio_replay *replay = (struct rt_audio_replay *) rt_malloc(sizeof(struct rt_audio_replay));
  184. if (replay == RT_NULL)
  185. return -RT_ENOMEM;
  186. memset(replay, 0, sizeof(struct rt_audio_replay));
  187. /* init memory pool for replay */
  188. replay->mp = rt_mp_create("adu_mp", RT_AUDIO_REPLAY_MP_BLOCK_COUNT, RT_AUDIO_REPLAY_MP_BLOCK_SIZE);
  189. if (replay->mp == RT_NULL)
  190. {
  191. rt_free(replay);
  192. LOG_E("create memory pool for repaly failed");
  193. return -RT_ENOMEM;
  194. }
  195. /* init queue for audio replay */
  196. rt_data_queue_init(&replay->queue, CFG_AUDIO_REPLAY_QUEUE_COUNT, 0, RT_NULL);
  197. /* init mutex lock for audio replay */
  198. rt_mutex_init(&replay->lock, "replay", RT_IPC_FLAG_PRIO);
  199. replay->activated = RT_FALSE;
  200. audio->replay = replay;
  201. }
  202. /* initialize record */
  203. if (dev->flag & RT_DEVICE_FLAG_RDONLY)
  204. {
  205. struct rt_audio_record *record = (struct rt_audio_record *) rt_malloc(sizeof(struct rt_audio_record));
  206. rt_uint8_t *buffer;
  207. if (record == RT_NULL)
  208. return -RT_ENOMEM;
  209. memset(record, 0, sizeof(struct rt_audio_record));
  210. /* init pipe for record*/
  211. buffer = rt_malloc(RT_AUDIO_RECORD_PIPE_SIZE);
  212. if (buffer == RT_NULL)
  213. {
  214. rt_free(record);
  215. LOG_E("malloc memory for for record pipe failed");
  216. return -RT_ENOMEM;
  217. }
  218. rt_audio_pipe_init(&record->pipe, "record",
  219. (rt_int32_t)(RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD),
  220. buffer,
  221. RT_AUDIO_RECORD_PIPE_SIZE);
  222. record->activated = RT_FALSE;
  223. audio->record = record;
  224. }
  225. /* initialize hardware configuration */
  226. if (audio->ops->init)
  227. audio->ops->init(audio);
  228. /* get replay buffer information */
  229. if (audio->ops->buffer_info)
  230. audio->ops->buffer_info(audio, &audio->replay->buf_info);
  231. return result;
  232. }
  233. static rt_err_t _audio_dev_open(struct rt_device *dev, rt_uint16_t oflag)
  234. {
  235. struct rt_audio_device *audio;
  236. RT_ASSERT(dev != RT_NULL);
  237. audio = (struct rt_audio_device *) dev;
  238. /* check device flag with the open flag */
  239. if ((oflag & RT_DEVICE_OFLAG_RDONLY) && !(dev->flag & RT_DEVICE_FLAG_RDONLY))
  240. return -RT_EIO;
  241. if ((oflag & RT_DEVICE_OFLAG_WRONLY) && !(dev->flag & RT_DEVICE_FLAG_WRONLY))
  242. return -RT_EIO;
  243. /* get open flags */
  244. dev->open_flag = oflag & 0xff;
  245. /* initialize the Rx/Tx structure according to open flag */
  246. if (oflag & RT_DEVICE_OFLAG_WRONLY)
  247. {
  248. if (audio->replay->activated != RT_TRUE)
  249. {
  250. LOG_D("open audio replay device, oflag = %x\n", oflag);
  251. audio->replay->write_index = 0;
  252. audio->replay->read_index = 0;
  253. audio->replay->pos = 0;
  254. audio->replay->event = REPLAY_EVT_NONE;
  255. }
  256. dev->open_flag |= RT_DEVICE_OFLAG_WRONLY;
  257. }
  258. if (oflag & RT_DEVICE_OFLAG_RDONLY)
  259. {
  260. /* open record pipe */
  261. if (audio->record->activated != RT_TRUE)
  262. {
  263. LOG_D("open audio record device ,oflag = %x\n", oflag);
  264. _audio_record_start(audio);
  265. audio->record->activated = RT_TRUE;
  266. }
  267. dev->open_flag |= RT_DEVICE_OFLAG_RDONLY;
  268. }
  269. return RT_EOK;
  270. }
  271. static rt_err_t _audio_dev_close(struct rt_device *dev)
  272. {
  273. struct rt_audio_device *audio;
  274. RT_ASSERT(dev != RT_NULL);
  275. audio = (struct rt_audio_device *) dev;
  276. if (dev->open_flag & RT_DEVICE_OFLAG_WRONLY)
  277. {
  278. /* stop replay stream */
  279. _aduio_replay_stop(audio);
  280. dev->open_flag &= ~RT_DEVICE_OFLAG_WRONLY;
  281. }
  282. if (dev->open_flag & RT_DEVICE_OFLAG_RDONLY)
  283. {
  284. /* stop record stream */
  285. _audio_record_stop(audio);
  286. dev->open_flag &= ~RT_DEVICE_OFLAG_RDONLY;
  287. }
  288. return RT_EOK;
  289. }
  290. static rt_size_t _audio_dev_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size)
  291. {
  292. struct rt_audio_device *audio;
  293. RT_ASSERT(dev != RT_NULL);
  294. audio = (struct rt_audio_device *) dev;
  295. if (!(dev->open_flag & RT_DEVICE_OFLAG_RDONLY) || (audio->record == RT_NULL))
  296. return 0;
  297. return rt_device_read(RT_DEVICE(&audio->record->pipe), pos, buffer, size);
  298. }
  299. static rt_size_t _audio_dev_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size)
  300. {
  301. struct rt_audio_device *audio;
  302. rt_uint8_t *ptr;
  303. rt_uint16_t block_size, remain_bytes, index = 0;
  304. RT_ASSERT(dev != RT_NULL);
  305. audio = (struct rt_audio_device *) dev;
  306. if (!(dev->open_flag & RT_DEVICE_OFLAG_WRONLY) || (audio->replay == RT_NULL))
  307. return 0;
  308. /* push a new frame to replay data queue */
  309. ptr = (rt_uint8_t *)buffer;
  310. block_size = RT_AUDIO_REPLAY_MP_BLOCK_SIZE;
  311. rt_mutex_take(&audio->replay->lock, RT_WAITING_FOREVER);
  312. while (index < size)
  313. {
  314. /* request buffer from replay memory pool */
  315. if (audio->replay->write_index % block_size == 0)
  316. {
  317. audio->replay->write_data = rt_mp_alloc(audio->replay->mp, RT_WAITING_FOREVER);
  318. memset(audio->replay->write_data, 0, block_size);
  319. }
  320. /* copy data to replay memory pool */
  321. remain_bytes = MIN((block_size - audio->replay->write_index), (size - index));
  322. memcpy(&audio->replay->write_data[audio->replay->write_index], &ptr[index], remain_bytes);
  323. index += remain_bytes;
  324. audio->replay->write_index += remain_bytes;
  325. audio->replay->write_index %= block_size;
  326. if (audio->replay->write_index == 0)
  327. {
  328. rt_data_queue_push(&audio->replay->queue,
  329. audio->replay->write_data,
  330. block_size,
  331. RT_WAITING_FOREVER);
  332. }
  333. }
  334. rt_mutex_release(&audio->replay->lock);
  335. /* check replay state */
  336. if (audio->replay->activated != RT_TRUE)
  337. {
  338. _aduio_replay_start(audio);
  339. audio->replay->activated = RT_TRUE;
  340. }
  341. return index;
  342. }
  343. static rt_err_t _audio_dev_control(struct rt_device *dev, int cmd, void *args)
  344. {
  345. rt_err_t result = RT_EOK;
  346. struct rt_audio_device *audio;
  347. RT_ASSERT(dev != RT_NULL);
  348. audio = (struct rt_audio_device *) dev;
  349. /* dev stat...*/
  350. switch (cmd)
  351. {
  352. case AUDIO_CTL_GETCAPS:
  353. {
  354. struct rt_audio_caps *caps = (struct rt_audio_caps *) args;
  355. LOG_D("AUDIO_CTL_GETCAPS: main_type = %d,sub_type = %d", caps->main_type, caps->sub_type);
  356. if (audio->ops->getcaps != RT_NULL)
  357. {
  358. result = audio->ops->getcaps(audio, caps);
  359. }
  360. break;
  361. }
  362. case AUDIO_CTL_CONFIGURE:
  363. {
  364. struct rt_audio_caps *caps = (struct rt_audio_caps *) args;
  365. LOG_D("AUDIO_CTL_CONFIGURE: main_type = %d,sub_type = %d", caps->main_type, caps->sub_type);
  366. if (audio->ops->configure != RT_NULL)
  367. {
  368. result = audio->ops->configure(audio, caps);
  369. }
  370. break;
  371. }
  372. case AUDIO_CTL_START:
  373. {
  374. int stream = *(int *) args;
  375. LOG_D("AUDIO_CTL_START: stream = %d", stream);
  376. if (stream == AUDIO_STREAM_REPLAY)
  377. {
  378. result = _aduio_replay_start(audio);
  379. }
  380. else
  381. {
  382. result = _audio_record_start(audio);
  383. }
  384. break;
  385. }
  386. case AUDIO_CTL_STOP:
  387. {
  388. int stream = *(int *) args;
  389. LOG_D("AUDIO_CTL_STOP: stream = %d", stream);
  390. if (stream == AUDIO_STREAM_REPLAY)
  391. {
  392. result = _aduio_replay_stop(audio);
  393. }
  394. else
  395. {
  396. result = _audio_record_stop(audio);
  397. }
  398. break;
  399. }
  400. default:
  401. break;
  402. }
  403. return result;
  404. }
  405. #ifdef RT_USING_DEVICE_OPS
  406. const static struct rt_device_ops audio_ops =
  407. {
  408. _audio_dev_init,
  409. _audio_dev_open,
  410. _audio_dev_close,
  411. _audio_dev_read,
  412. _audio_dev_write,
  413. _audio_dev_control
  414. };
  415. #endif
  416. rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data)
  417. {
  418. rt_err_t result = RT_EOK;
  419. struct rt_device *device;
  420. RT_ASSERT(audio != RT_NULL);
  421. device = &(audio->parent);
  422. device->type = RT_Device_Class_Sound;
  423. device->rx_indicate = RT_NULL;
  424. device->tx_complete = RT_NULL;
  425. #ifdef RT_USING_DEVICE_OPS
  426. device->ops = &audio_ops;
  427. #else
  428. device->init = _audio_dev_init;
  429. device->open = _audio_dev_open;
  430. device->close = _audio_dev_close;
  431. device->read = _audio_dev_read;
  432. device->write = _audio_dev_write;
  433. device->control = _audio_dev_control;
  434. #endif
  435. device->user_data = data;
  436. /* register a character device */
  437. result = rt_device_register(device, name, flag | RT_DEVICE_FLAG_REMOVABLE);
  438. /* initialize audio device */
  439. if (result == RT_EOK)
  440. result = rt_device_init(device);
  441. return result;
  442. }
  443. int rt_audio_samplerate_to_speed(rt_uint32_t bitValue)
  444. {
  445. int speed = 0;
  446. switch (bitValue)
  447. {
  448. case AUDIO_SAMP_RATE_8K:
  449. speed = 8000;
  450. break;
  451. case AUDIO_SAMP_RATE_11K:
  452. speed = 11052;
  453. break;
  454. case AUDIO_SAMP_RATE_16K:
  455. speed = 16000;
  456. break;
  457. case AUDIO_SAMP_RATE_22K:
  458. speed = 22050;
  459. break;
  460. case AUDIO_SAMP_RATE_32K:
  461. speed = 32000;
  462. break;
  463. case AUDIO_SAMP_RATE_44K:
  464. speed = 44100;
  465. break;
  466. case AUDIO_SAMP_RATE_48K:
  467. speed = 48000;
  468. break;
  469. case AUDIO_SAMP_RATE_96K:
  470. speed = 96000;
  471. break;
  472. case AUDIO_SAMP_RATE_128K:
  473. speed = 128000;
  474. break;
  475. case AUDIO_SAMP_RATE_160K:
  476. speed = 160000;
  477. break;
  478. case AUDIO_SAMP_RATE_172K:
  479. speed = 176400;
  480. break;
  481. case AUDIO_SAMP_RATE_192K:
  482. speed = 192000;
  483. break;
  484. default:
  485. break;
  486. }
  487. return speed;
  488. }
  489. void rt_audio_tx_complete(struct rt_audio_device *audio)
  490. {
  491. /* try to send next frame */
  492. _audio_send_replay_frame(audio);
  493. }
  494. void rt_audio_rx_done(struct rt_audio_device *audio, rt_uint8_t *pbuf, rt_size_t len)
  495. {
  496. /* save data to record pipe */
  497. rt_device_write(RT_DEVICE(&audio->record->pipe), 0, pbuf, len);
  498. /* invoke callback */
  499. if (audio->parent.rx_indicate != RT_NULL)
  500. audio->parent.rx_indicate(&audio->parent, len);
  501. }