dev_audio.c 21 KB

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