dev_audio.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. /*
  2. * Copyright (c) 2006-2025 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. * 2025-03-04 wumingzi add doxygen comments.
  11. */
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <rthw.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. /**
  23. * @addtogroup group_Audio
  24. */
  25. /** @{ */
  26. enum
  27. {
  28. REPLAY_EVT_NONE = 0x00,
  29. REPLAY_EVT_START = 0x01,
  30. REPLAY_EVT_STOP = 0x02,
  31. };
  32. /**
  33. * @brief Send a replay frame to the audio hardware device
  34. *
  35. * This function handles sending audio data from the memory queue to the hardware buffer for playback.
  36. * If there is no data available in the queue, it sends zero frames. Otherwise, it copies data from the memory pool
  37. * to the hardware device FIFO and manages the read index and position accordingly.
  38. *
  39. * @param[in] audio pointer to the audio device structure
  40. *
  41. * @return error code, RT_EOK is successful otherwise means failure
  42. *
  43. * @note This function may temporarily disable interrupts or perform time-consuming operations like memcpy,
  44. * which could affect system responsiveness
  45. */
  46. static rt_err_t _audio_send_replay_frame(struct rt_audio_device *audio)
  47. {
  48. rt_err_t result = RT_EOK;
  49. rt_uint8_t *data;
  50. rt_size_t dst_size, src_size;
  51. rt_uint16_t position, remain_bytes = 0, index = 0;
  52. struct rt_audio_buf_info *buf_info;
  53. RT_ASSERT(audio != RT_NULL);
  54. buf_info = &audio->replay->buf_info;
  55. /* save current pos */
  56. position = audio->replay->pos;
  57. dst_size = buf_info->block_size;
  58. /* check replay queue is empty */
  59. if (rt_data_queue_peek(&audio->replay->queue, (const void **)&data, &src_size) != RT_EOK)
  60. {
  61. /* ack stop event */
  62. if (audio->replay->event & REPLAY_EVT_STOP)
  63. rt_completion_done(&audio->replay->cmp);
  64. /* send zero frames */
  65. rt_memset(&buf_info->buffer[audio->replay->pos], 0, dst_size);
  66. audio->replay->pos += dst_size;
  67. audio->replay->pos %= buf_info->total_size;
  68. }
  69. else
  70. {
  71. rt_memset(&buf_info->buffer[audio->replay->pos], 0, dst_size);
  72. /* copy data from memory pool to hardware device fifo */
  73. while (index < dst_size)
  74. {
  75. result = rt_data_queue_peek(&audio->replay->queue, (const void **)&data, &src_size);
  76. if (result != RT_EOK)
  77. {
  78. LOG_D("under run %d, remain %d", audio->replay->pos, remain_bytes);
  79. audio->replay->pos -= remain_bytes;
  80. audio->replay->pos += dst_size;
  81. audio->replay->pos %= buf_info->total_size;
  82. audio->replay->read_index = 0;
  83. result = -RT_EEMPTY;
  84. break;
  85. }
  86. remain_bytes = MIN((dst_size - index), (src_size - audio->replay->read_index));
  87. rt_memcpy(&buf_info->buffer[audio->replay->pos],
  88. &data[audio->replay->read_index], remain_bytes);
  89. index += remain_bytes;
  90. audio->replay->read_index += remain_bytes;
  91. audio->replay->pos += remain_bytes;
  92. audio->replay->pos %= buf_info->total_size;
  93. if (audio->replay->read_index == src_size)
  94. {
  95. /* free memory */
  96. audio->replay->read_index = 0;
  97. rt_data_queue_pop(&audio->replay->queue, (const void **)&data, &src_size, RT_WAITING_NO);
  98. rt_mp_free(data);
  99. /* notify transmitted complete. */
  100. if (audio->parent.tx_complete != RT_NULL)
  101. audio->parent.tx_complete(&audio->parent, (void *)data);
  102. }
  103. }
  104. }
  105. if (audio->ops->transmit != RT_NULL)
  106. {
  107. if (audio->ops->transmit(audio, &buf_info->buffer[position], RT_NULL, dst_size) != dst_size)
  108. result = -RT_ERROR;
  109. }
  110. return result;
  111. }
  112. /**
  113. * @brief Write replay frame into audio device replay queue
  114. *
  115. * @param[in] audio pointer to audio device
  116. *
  117. * @return error code, RT_EOK is successful otherwise means failure
  118. */
  119. static rt_err_t _audio_flush_replay_frame(struct rt_audio_device *audio)
  120. {
  121. rt_err_t result = RT_EOK;
  122. if (audio->replay->write_index)
  123. {
  124. result = rt_data_queue_push(&audio->replay->queue,
  125. (const void **)audio->replay->write_data,
  126. audio->replay->write_index,
  127. RT_WAITING_FOREVER);
  128. audio->replay->write_index = 0;
  129. }
  130. return result;
  131. }
  132. /**
  133. * @brief Replay audio
  134. *
  135. * @param[in] audio pointer to audio device
  136. *
  137. * @return error code, RT_EOK is successful otherwise means failure
  138. */
  139. static rt_err_t _aduio_replay_start(struct rt_audio_device *audio)
  140. {
  141. rt_err_t result = RT_EOK;
  142. if (audio->replay->activated != RT_TRUE)
  143. {
  144. /* start playback hardware device */
  145. if (audio->ops->start)
  146. result = audio->ops->start(audio, AUDIO_STREAM_REPLAY);
  147. audio->replay->activated = RT_TRUE;
  148. LOG_D("start audio replay device");
  149. }
  150. return result;
  151. }
  152. /**
  153. * @brief Stop replaying audio
  154. *
  155. * When audio->replay->queue is empty and the audio->replay->event was set REPLAY_EVT_STOP,
  156. * _audio_send_replay_frame will send completion to stop replaying audio.
  157. *
  158. * @param[in] audio pointer to audio device
  159. *
  160. * @return error code, RT_EOK is successful otherwise means failure
  161. */
  162. static rt_err_t _aduio_replay_stop(struct rt_audio_device *audio)
  163. {
  164. rt_err_t result = RT_EOK;
  165. if (audio->replay->activated == RT_TRUE)
  166. {
  167. /* flush replay remian frames */
  168. _audio_flush_replay_frame(audio);
  169. /* notify irq(or thread) to stop the data transmission */
  170. audio->replay->event |= REPLAY_EVT_STOP;
  171. /* waiting for the remaining data transfer to complete */
  172. rt_completion_init(&audio->replay->cmp);
  173. rt_completion_wait(&audio->replay->cmp, RT_WAITING_FOREVER);
  174. audio->replay->event &= ~REPLAY_EVT_STOP;
  175. /* stop playback hardware device */
  176. if (audio->ops->stop)
  177. result = audio->ops->stop(audio, AUDIO_STREAM_REPLAY);
  178. audio->replay->activated = RT_FALSE;
  179. LOG_D("stop audio replay device");
  180. }
  181. return result;
  182. }
  183. /**
  184. * @brief Open audio pipe and start to record audio
  185. *
  186. * @param[in] audio pointer to audio device
  187. *
  188. * @return error code, RT_EOK is successful otherwise means failure
  189. */
  190. static rt_err_t _audio_record_start(struct rt_audio_device *audio)
  191. {
  192. rt_err_t result = RT_EOK;
  193. if (audio->record->activated != RT_TRUE)
  194. {
  195. /* open audio record pipe */
  196. rt_device_open(RT_DEVICE(&audio->record->pipe), RT_DEVICE_OFLAG_RDONLY);
  197. /* start record hardware device */
  198. if (audio->ops->start)
  199. result = audio->ops->start(audio, AUDIO_STREAM_RECORD);
  200. audio->record->activated = RT_TRUE;
  201. LOG_D("start audio record device");
  202. }
  203. return result;
  204. }
  205. /**
  206. * @brief stop recording audio and closeaudio pipe
  207. *
  208. * @param[in] audio pointer to audio device
  209. *
  210. * @return error code, RT_EOK is successful otherwise means failure
  211. */
  212. static rt_err_t _audio_record_stop(struct rt_audio_device *audio)
  213. {
  214. rt_err_t result = RT_EOK;
  215. if (audio->record->activated == RT_TRUE)
  216. {
  217. /* stop record hardware device */
  218. if (audio->ops->stop)
  219. result = audio->ops->stop(audio, AUDIO_STREAM_RECORD);
  220. /* close audio record pipe */
  221. rt_device_close(RT_DEVICE(&audio->record->pipe));
  222. audio->record->activated = RT_FALSE;
  223. LOG_D("stop audio record device");
  224. }
  225. return result;
  226. }
  227. /**
  228. * @brief Init audio pipe
  229. *
  230. * In kernel, this function will set replay or record function depending on device
  231. * flag. For replaying, it will malloc for managing audio replay struct meanwhile
  232. * creating mempool and dataqueue.For recording, it will creat audio pipe and
  233. * it's ringbuffer.
  234. * In driver, this function will only execute hardware driver initialization code
  235. * and get hardware buffer infomation.
  236. *
  237. * @param[in] dev pointer to audio device
  238. *
  239. * @return error code, RT_EOK is successful otherwise means failure
  240. */
  241. static rt_err_t _audio_dev_init(struct rt_device *dev)
  242. {
  243. rt_err_t result = RT_EOK;
  244. struct rt_audio_device *audio;
  245. RT_ASSERT(dev != RT_NULL);
  246. audio = (struct rt_audio_device *) dev;
  247. /* initialize replay & record */
  248. audio->replay = RT_NULL;
  249. audio->record = RT_NULL;
  250. /* initialize replay */
  251. if (dev->flag & RT_DEVICE_FLAG_WRONLY)
  252. {
  253. struct rt_audio_replay *replay = (struct rt_audio_replay *) rt_malloc(sizeof(struct rt_audio_replay));
  254. if (replay == RT_NULL)
  255. return -RT_ENOMEM;
  256. rt_memset(replay, 0, sizeof(struct rt_audio_replay));
  257. /* init memory pool for replay */
  258. replay->mp = rt_mp_create("adu_mp", RT_AUDIO_REPLAY_MP_BLOCK_COUNT, RT_AUDIO_REPLAY_MP_BLOCK_SIZE);
  259. if (replay->mp == RT_NULL)
  260. {
  261. rt_free(replay);
  262. LOG_E("create memory pool for replay failed");
  263. return -RT_ENOMEM;
  264. }
  265. /* init queue for audio replay */
  266. rt_data_queue_init(&replay->queue, CFG_AUDIO_REPLAY_QUEUE_COUNT, 0, RT_NULL);
  267. /* init mutex lock for audio replay */
  268. rt_mutex_init(&replay->lock, "replay", RT_IPC_FLAG_PRIO);
  269. replay->activated = RT_FALSE;
  270. audio->replay = replay;
  271. }
  272. /* initialize record */
  273. if (dev->flag & RT_DEVICE_FLAG_RDONLY)
  274. {
  275. struct rt_audio_record *record = (struct rt_audio_record *) rt_malloc(sizeof(struct rt_audio_record));
  276. rt_uint8_t *buffer;
  277. if (record == RT_NULL)
  278. return -RT_ENOMEM;
  279. rt_memset(record, 0, sizeof(struct rt_audio_record));
  280. /* init pipe for record*/
  281. buffer = rt_malloc(RT_AUDIO_RECORD_PIPE_SIZE);
  282. if (buffer == RT_NULL)
  283. {
  284. rt_free(record);
  285. LOG_E("malloc memory for for record pipe failed");
  286. return -RT_ENOMEM;
  287. }
  288. rt_audio_pipe_init(&record->pipe, "record",
  289. (rt_int32_t)(RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD),
  290. buffer,
  291. RT_AUDIO_RECORD_PIPE_SIZE);
  292. record->activated = RT_FALSE;
  293. audio->record = record;
  294. }
  295. /* initialize hardware configuration */
  296. if (audio->ops->init)
  297. audio->ops->init(audio);
  298. /* get replay buffer information */
  299. if (audio->ops->buffer_info)
  300. audio->ops->buffer_info(audio, &audio->replay->buf_info);
  301. return result;
  302. }
  303. /**
  304. * @brief Start record audio
  305. *
  306. * @param[in] dev pointer to audio device
  307. *
  308. * @param[in] oflag device flag
  309. *
  310. * @return error code, RT_EOK is successful otherwise means failure
  311. */
  312. static rt_err_t _audio_dev_open(struct rt_device *dev, rt_uint16_t oflag)
  313. {
  314. struct rt_audio_device *audio;
  315. RT_ASSERT(dev != RT_NULL);
  316. audio = (struct rt_audio_device *) dev;
  317. /* check device flag with the open flag */
  318. if ((oflag & RT_DEVICE_OFLAG_RDONLY) && !(dev->flag & RT_DEVICE_FLAG_RDONLY))
  319. return -RT_EIO;
  320. if ((oflag & RT_DEVICE_OFLAG_WRONLY) && !(dev->flag & RT_DEVICE_FLAG_WRONLY))
  321. return -RT_EIO;
  322. /* get open flags */
  323. dev->open_flag = oflag & 0xff;
  324. /* initialize the Rx/Tx structure according to open flag */
  325. if (oflag & RT_DEVICE_OFLAG_WRONLY)
  326. {
  327. if (audio->replay->activated != RT_TRUE)
  328. {
  329. LOG_D("open audio replay device, oflag = %x\n", oflag);
  330. audio->replay->write_index = 0;
  331. audio->replay->read_index = 0;
  332. audio->replay->pos = 0;
  333. audio->replay->event = REPLAY_EVT_NONE;
  334. }
  335. dev->open_flag |= RT_DEVICE_OFLAG_WRONLY;
  336. }
  337. if (oflag & RT_DEVICE_OFLAG_RDONLY)
  338. {
  339. /* open record pipe */
  340. if (audio->record->activated != RT_TRUE)
  341. {
  342. LOG_D("open audio record device ,oflag = %x\n", oflag);
  343. _audio_record_start(audio);
  344. audio->record->activated = RT_TRUE;
  345. }
  346. dev->open_flag |= RT_DEVICE_OFLAG_RDONLY;
  347. }
  348. return RT_EOK;
  349. }
  350. /**
  351. * @brief Stop record, replay or both.
  352. *
  353. * @param[in] dev pointer to audio device
  354. *
  355. * @return useless param
  356. */
  357. static rt_err_t _audio_dev_close(struct rt_device *dev)
  358. {
  359. struct rt_audio_device *audio;
  360. RT_ASSERT(dev != RT_NULL);
  361. audio = (struct rt_audio_device *) dev;
  362. if (dev->open_flag & RT_DEVICE_OFLAG_WRONLY)
  363. {
  364. /* stop replay stream */
  365. _aduio_replay_stop(audio);
  366. dev->open_flag &= ~RT_DEVICE_OFLAG_WRONLY;
  367. }
  368. if (dev->open_flag & RT_DEVICE_OFLAG_RDONLY)
  369. {
  370. /* stop record stream */
  371. _audio_record_stop(audio);
  372. dev->open_flag &= ~RT_DEVICE_OFLAG_RDONLY;
  373. }
  374. return RT_EOK;
  375. }
  376. /**
  377. * @brief Read audio device
  378. *
  379. * @param[in] dev pointer to device
  380. *
  381. * @param[in] pos position when reading
  382. *
  383. * @param[out] buffer a data buffer to save the read data
  384. *
  385. * @param[in] size buffer size
  386. *
  387. * @return the actually read size on successfully, otherwise 0 will be returned.
  388. *
  389. * @note
  390. */
  391. static rt_ssize_t _audio_dev_read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size)
  392. {
  393. struct rt_audio_device *audio;
  394. RT_ASSERT(dev != RT_NULL);
  395. audio = (struct rt_audio_device *) dev;
  396. if (!(dev->open_flag & RT_DEVICE_OFLAG_RDONLY) || (audio->record == RT_NULL))
  397. return 0;
  398. return rt_device_read(RT_DEVICE(&audio->record->pipe), pos, buffer, size);
  399. }
  400. /**
  401. * @brief Write data into replay data queue and replay it
  402. *
  403. * @param[in] dev pointer to device
  404. *
  405. * @param[in] pos useless param
  406. *
  407. * @param[in] buffer a data buffer to be written into data queue
  408. *
  409. * @param[in] size buffer size
  410. *
  411. * @return the actually read size on successfully, otherwise 0 will be returned.
  412. *
  413. * @note This function will take mutex.
  414. */
  415. static rt_ssize_t _audio_dev_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size)
  416. {
  417. struct rt_audio_device *audio;
  418. rt_uint8_t *ptr;
  419. rt_uint16_t block_size, remain_bytes, index = 0;
  420. RT_ASSERT(dev != RT_NULL);
  421. audio = (struct rt_audio_device *) dev;
  422. if (!(dev->open_flag & RT_DEVICE_OFLAG_WRONLY) || (audio->replay == RT_NULL))
  423. return 0;
  424. /* push a new frame to replay data queue */
  425. ptr = (rt_uint8_t *)buffer;
  426. block_size = RT_AUDIO_REPLAY_MP_BLOCK_SIZE;
  427. rt_mutex_take(&audio->replay->lock, RT_WAITING_FOREVER);
  428. while (index < size)
  429. {
  430. /* request buffer from replay memory pool */
  431. if (audio->replay->write_index % block_size == 0)
  432. {
  433. audio->replay->write_data = rt_mp_alloc(audio->replay->mp, RT_WAITING_FOREVER);
  434. rt_memset(audio->replay->write_data, 0, block_size);
  435. }
  436. /* copy data to replay memory pool */
  437. remain_bytes = MIN((block_size - audio->replay->write_index), (size - index));
  438. rt_memcpy(&audio->replay->write_data[audio->replay->write_index], &ptr[index], remain_bytes);
  439. index += remain_bytes;
  440. audio->replay->write_index += remain_bytes;
  441. audio->replay->write_index %= block_size;
  442. if (audio->replay->write_index == 0)
  443. {
  444. rt_data_queue_push(&audio->replay->queue,
  445. audio->replay->write_data,
  446. block_size,
  447. RT_WAITING_FOREVER);
  448. }
  449. }
  450. rt_mutex_release(&audio->replay->lock);
  451. /* check replay state */
  452. if (audio->replay->activated != RT_TRUE)
  453. {
  454. _aduio_replay_start(audio);
  455. audio->replay->activated = RT_TRUE;
  456. }
  457. return index;
  458. }
  459. /**
  460. * @brief Control audio device
  461. *
  462. * @param[in] dev pointer to device
  463. *
  464. * @param[in] cmd audio cmd, it can be one of value in @ref group_audio_control
  465. *
  466. * @param[in] args command argument
  467. *
  468. * @return error code, RT_EOK is successful otherwise means failure
  469. */
  470. static rt_err_t _audio_dev_control(struct rt_device *dev, int cmd, void *args)
  471. {
  472. rt_err_t result = RT_EOK;
  473. struct rt_audio_device *audio;
  474. RT_ASSERT(dev != RT_NULL);
  475. audio = (struct rt_audio_device *) dev;
  476. /* dev stat...*/
  477. switch (cmd)
  478. {
  479. case AUDIO_CTL_GETCAPS:
  480. {
  481. struct rt_audio_caps *caps = (struct rt_audio_caps *) args;
  482. LOG_D("AUDIO_CTL_GETCAPS: main_type = %d,sub_type = %d", caps->main_type, caps->sub_type);
  483. if (audio->ops->getcaps != RT_NULL)
  484. {
  485. result = audio->ops->getcaps(audio, caps);
  486. }
  487. break;
  488. }
  489. case AUDIO_CTL_CONFIGURE:
  490. {
  491. struct rt_audio_caps *caps = (struct rt_audio_caps *) args;
  492. LOG_D("AUDIO_CTL_CONFIGURE: main_type = %d,sub_type = %d", caps->main_type, caps->sub_type);
  493. if (audio->ops->configure != RT_NULL)
  494. {
  495. result = audio->ops->configure(audio, caps);
  496. }
  497. break;
  498. }
  499. case AUDIO_CTL_START:
  500. {
  501. int stream = *(int *) args;
  502. LOG_D("AUDIO_CTL_START: stream = %d", stream);
  503. if (stream == AUDIO_STREAM_REPLAY)
  504. {
  505. result = _aduio_replay_start(audio);
  506. }
  507. else
  508. {
  509. result = _audio_record_start(audio);
  510. }
  511. break;
  512. }
  513. case AUDIO_CTL_STOP:
  514. {
  515. int stream = *(int *) args;
  516. LOG_D("AUDIO_CTL_STOP: stream = %d", stream);
  517. if (stream == AUDIO_STREAM_REPLAY)
  518. {
  519. result = _aduio_replay_stop(audio);
  520. }
  521. else
  522. {
  523. result = _audio_record_stop(audio);
  524. }
  525. break;
  526. }
  527. default:
  528. break;
  529. }
  530. return result;
  531. }
  532. #ifdef RT_USING_DEVICE_OPS
  533. const static struct rt_device_ops audio_ops =
  534. {
  535. _audio_dev_init,
  536. _audio_dev_open,
  537. _audio_dev_close,
  538. _audio_dev_read,
  539. _audio_dev_write,
  540. _audio_dev_control
  541. };
  542. #endif
  543. /**
  544. * @brief Register and initialize audio device
  545. *
  546. * @param[in] audio pointer to audio deive
  547. *
  548. * @param[in] name device name
  549. *
  550. * @param[in] flag device flags
  551. *
  552. * @param[in] data user data
  553. *
  554. * @return error code, RT_EOK is successful otherwise means failure
  555. */
  556. rt_err_t rt_audio_register(struct rt_audio_device *audio, const char *name, rt_uint32_t flag, void *data)
  557. {
  558. rt_err_t result = RT_EOK;
  559. struct rt_device *device;
  560. RT_ASSERT(audio != RT_NULL);
  561. device = &(audio->parent);
  562. device->type = RT_Device_Class_Sound;
  563. device->rx_indicate = RT_NULL;
  564. device->tx_complete = RT_NULL;
  565. #ifdef RT_USING_DEVICE_OPS
  566. device->ops = &audio_ops;
  567. #else
  568. device->init = _audio_dev_init;
  569. device->open = _audio_dev_open;
  570. device->close = _audio_dev_close;
  571. device->read = _audio_dev_read;
  572. device->write = _audio_dev_write;
  573. device->control = _audio_dev_control;
  574. #endif
  575. device->user_data = data;
  576. /* register a character device */
  577. result = rt_device_register(device, name, flag | RT_DEVICE_FLAG_REMOVABLE);
  578. /* initialize audio device */
  579. if (result == RT_EOK)
  580. result = rt_device_init(device);
  581. return result;
  582. }
  583. /**
  584. * @brief Set audio sample rate
  585. *
  586. * @param[in] bitValue audio sample rate, it can be one of value in @ref group_audio_samp_rates
  587. *
  588. * @return speed has been set
  589. */
  590. int rt_audio_samplerate_to_speed(rt_uint32_t bitValue)
  591. {
  592. int speed = 0;
  593. switch (bitValue)
  594. {
  595. case AUDIO_SAMP_RATE_8K:
  596. speed = 8000;
  597. break;
  598. case AUDIO_SAMP_RATE_11K:
  599. speed = 11052;
  600. break;
  601. case AUDIO_SAMP_RATE_16K:
  602. speed = 16000;
  603. break;
  604. case AUDIO_SAMP_RATE_22K:
  605. speed = 22050;
  606. break;
  607. case AUDIO_SAMP_RATE_32K:
  608. speed = 32000;
  609. break;
  610. case AUDIO_SAMP_RATE_44K:
  611. speed = 44100;
  612. break;
  613. case AUDIO_SAMP_RATE_48K:
  614. speed = 48000;
  615. break;
  616. case AUDIO_SAMP_RATE_96K:
  617. speed = 96000;
  618. break;
  619. case AUDIO_SAMP_RATE_128K:
  620. speed = 128000;
  621. break;
  622. case AUDIO_SAMP_RATE_160K:
  623. speed = 160000;
  624. break;
  625. case AUDIO_SAMP_RATE_172K:
  626. speed = 176400;
  627. break;
  628. case AUDIO_SAMP_RATE_192K:
  629. speed = 192000;
  630. break;
  631. default:
  632. break;
  633. }
  634. return speed;
  635. }
  636. /**
  637. * @brief Send a replay frame to the audio hardware device
  638. *
  639. * See _audio_send_replay_frame for details
  640. *
  641. * @param[in] audio pointer to audio device
  642. *
  643. * @return void
  644. */
  645. void rt_audio_tx_complete(struct rt_audio_device *audio)
  646. {
  647. /* try to send next frame */
  648. _audio_send_replay_frame(audio);
  649. }
  650. /**
  651. * @brief Receive recording from audio device
  652. *
  653. * @param[in] audio pointer to audio device
  654. *
  655. * @param[in] pbuf pointer ro data to be received
  656. *
  657. * @param[in] len buffer size
  658. *
  659. * @return void
  660. */
  661. void rt_audio_rx_done(struct rt_audio_device *audio, rt_uint8_t *pbuf, rt_size_t len)
  662. {
  663. /* save data to record pipe */
  664. rt_device_write(RT_DEVICE(&audio->record->pipe), 0, pbuf, len);
  665. /* invoke callback */
  666. if (audio->parent.rx_indicate != RT_NULL)
  667. audio->parent.rx_indicate(&audio->parent, len);
  668. }
  669. /** @} group_Audio */