1
0

audio_play.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-11-24 thread-liu first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include <dfs_posix.h>
  13. #if defined(BSP_USING_AUDIO) && defined(BSP_USING_SDMMC)
  14. #define BUFSZ 1024
  15. #define SOUND_DEVICE_NAME "sound0"
  16. static rt_device_t snd_dev;
  17. struct RIFF_HEADER_DEF
  18. {
  19. char riff_id[4]; // 'R','I','F','F'
  20. uint32_t riff_size;
  21. char riff_format[4]; // 'W','A','V','E'
  22. };
  23. struct WAVE_FORMAT_DEF
  24. {
  25. uint16_t FormatTag;
  26. uint16_t Channels;
  27. uint32_t SamplesPerSec;
  28. uint32_t AvgBytesPerSec;
  29. uint16_t BlockAlign;
  30. uint16_t BitsPerSample;
  31. };
  32. struct FMT_BLOCK_DEF
  33. {
  34. char fmt_id[4]; // 'f','m','t',' '
  35. uint32_t fmt_size;
  36. struct WAVE_FORMAT_DEF wav_format;
  37. };
  38. struct DATA_BLOCK_DEF
  39. {
  40. char data_id[4]; // 'R','I','F','F'
  41. uint32_t data_size;
  42. };
  43. struct wav_info
  44. {
  45. struct RIFF_HEADER_DEF header;
  46. struct FMT_BLOCK_DEF fmt_block;
  47. struct DATA_BLOCK_DEF data_block;
  48. };
  49. int wavplay_sample(int argc, char **argv)
  50. {
  51. int fd = -1;
  52. uint8_t *buffer = NULL;
  53. struct wav_info *info = NULL;
  54. struct rt_audio_caps caps = {0};
  55. if (argc != 2)
  56. {
  57. rt_kprintf("Usage:\n");
  58. rt_kprintf("wavplay_sample song.wav\n");
  59. return 0;
  60. }
  61. fd = open(argv[1], O_WRONLY);
  62. if (fd < 0)
  63. {
  64. rt_kprintf("open file failed!\n");
  65. goto __exit;
  66. }
  67. buffer = rt_malloc(BUFSZ);
  68. if (buffer == RT_NULL)
  69. goto __exit;
  70. info = (struct wav_info *) rt_malloc(sizeof * info);
  71. if (info == RT_NULL)
  72. goto __exit;
  73. if (read(fd, &(info->header), sizeof(struct RIFF_HEADER_DEF)) <= 0)
  74. goto __exit;
  75. if (read(fd, &(info->fmt_block), sizeof(struct FMT_BLOCK_DEF)) <= 0)
  76. goto __exit;
  77. if (read(fd, &(info->data_block), sizeof(struct DATA_BLOCK_DEF)) <= 0)
  78. goto __exit;
  79. rt_kprintf("wav information:\n");
  80. rt_kprintf("samplerate %d\n", info->fmt_block.wav_format.SamplesPerSec);
  81. rt_kprintf("channel %d\n", info->fmt_block.wav_format.Channels);
  82. snd_dev = rt_device_find(SOUND_DEVICE_NAME);
  83. rt_device_open(snd_dev, RT_DEVICE_OFLAG_WRONLY);
  84. caps.main_type = AUDIO_TYPE_OUTPUT;
  85. caps.sub_type = AUDIO_DSP_PARAM;
  86. caps.udata.config.samplerate = info->fmt_block.wav_format.SamplesPerSec;
  87. caps.udata.config.channels = info->fmt_block.wav_format.Channels;
  88. caps.udata.config.samplebits = 16;
  89. rt_device_control(snd_dev, AUDIO_CTL_CONFIGURE, &caps);
  90. while (1)
  91. {
  92. int length;
  93. length = read(fd, buffer, BUFSZ);
  94. if (length <= 0)
  95. break;
  96. rt_device_write(snd_dev, 0, buffer, length);
  97. }
  98. rt_device_close(snd_dev);
  99. __exit:
  100. if (fd >= 0)
  101. close(fd);
  102. if (buffer)
  103. rt_free(buffer);
  104. if (info)
  105. rt_free(info);
  106. return 0;
  107. }
  108. MSH_CMD_EXPORT(wavplay_sample, play wav file);
  109. #endif
  110. #if defined(BSP_USING_AUDIO) && defined(BSP_USING_SDMMC) && defined(BSP_USING_AUDIO_RECORD)
  111. #define RECORD_TIME_MS 5000
  112. #define RECORD_SAMPLERATE 16000
  113. #define RECORD_CHANNEL 2
  114. #define RECORD_CHUNK_SZ ((RECORD_SAMPLERATE * RECORD_CHANNEL * 2) * 20 / 1000)
  115. #define MIC_DEVICE_NAME "mic0"
  116. static rt_device_t mic_dev;
  117. struct wav_header
  118. {
  119. char riff_id[4]; /* "RIFF" */
  120. int riff_datasize; /* RIFF chunk data size,exclude riff_id[4] and riff_datasize,total - 8 */
  121. char riff_type[4]; /* "WAVE" */
  122. char fmt_id[4]; /* "fmt " */
  123. int fmt_datasize; /* fmt chunk data size,16 for pcm */
  124. short fmt_compression_code; /* 1 for PCM */
  125. short fmt_channels; /* 1(mono) or 2(stereo) */
  126. int fmt_sample_rate; /* samples per second */
  127. int fmt_avg_bytes_per_sec; /* sample_rate * channels * bit_per_sample / 8 */
  128. short fmt_block_align; /* number bytes per sample, bit_per_sample * channels / 8 */
  129. short fmt_bit_per_sample; /* bits of each sample(8,16,32). */
  130. char data_id[4]; /* "data" */
  131. int data_datasize; /* data chunk size,pcm_size - 44 */
  132. };
  133. static void wavheader_init(struct wav_header *header, int sample_rate, int channels, int datasize)
  134. {
  135. memcpy(header->riff_id, "RIFF", 4);
  136. header->riff_datasize = datasize + 44 - 8;
  137. memcpy(header->riff_type, "WAVE", 4);
  138. memcpy(header->fmt_id, "fmt ", 4);
  139. header->fmt_datasize = 16;
  140. header->fmt_compression_code = 1;
  141. header->fmt_channels = channels;
  142. header->fmt_sample_rate = sample_rate;
  143. header->fmt_bit_per_sample = 16;
  144. header->fmt_avg_bytes_per_sec = header->fmt_sample_rate * header->fmt_channels * header->fmt_bit_per_sample / 8;
  145. header->fmt_block_align = header->fmt_bit_per_sample * header->fmt_channels / 8;
  146. memcpy(header->data_id, "data", 4);
  147. header->data_datasize = datasize;
  148. }
  149. int wavrecord_sample(int argc, char **argv)
  150. {
  151. int fd = -1;
  152. uint8_t *buffer = NULL;
  153. struct wav_header header;
  154. struct rt_audio_caps caps = {0};
  155. int length, total_length = 0;
  156. if (argc != 2)
  157. {
  158. rt_kprintf("Usage:\n");
  159. rt_kprintf("wavrecord_sample file.wav\n");
  160. return -1;
  161. }
  162. fd = open(argv[1], O_WRONLY | O_CREAT);
  163. if (fd < 0)
  164. {
  165. rt_kprintf("open file for recording failed!\n");
  166. return -1;
  167. }
  168. write(fd, &header, sizeof(struct wav_header));
  169. buffer = rt_malloc(RECORD_CHUNK_SZ);
  170. if (buffer == RT_NULL)
  171. goto __exit;
  172. mic_dev = rt_device_find(MIC_DEVICE_NAME);
  173. if (mic_dev == RT_NULL)
  174. goto __exit;
  175. rt_device_open(mic_dev, RT_DEVICE_OFLAG_RDONLY);
  176. caps.main_type = AUDIO_TYPE_INPUT;
  177. caps.sub_type = AUDIO_DSP_PARAM;
  178. caps.udata.config.samplerate = RECORD_SAMPLERATE;
  179. caps.udata.config.channels = RECORD_CHANNEL;
  180. caps.udata.config.samplebits = 16;
  181. rt_device_control(mic_dev, AUDIO_CTL_CONFIGURE, &caps);
  182. while (1)
  183. {
  184. length = rt_device_read(mic_dev, 0, buffer, RECORD_CHUNK_SZ);
  185. if (length)
  186. {
  187. write(fd, buffer, length);
  188. total_length += length;
  189. }
  190. if ((total_length / RECORD_CHUNK_SZ) > (RECORD_TIME_MS / 20))
  191. break;
  192. }
  193. /* write wav file head */
  194. wavheader_init(&header, RECORD_SAMPLERATE, RECORD_CHANNEL, total_length);
  195. lseek(fd, 0, SEEK_SET);
  196. write(fd, &header, sizeof(struct wav_header));
  197. close(fd);
  198. /* close audio mic device */
  199. rt_device_close(mic_dev);
  200. __exit:
  201. if (fd >= 0)
  202. close(fd);
  203. if (buffer)
  204. rt_free(buffer);
  205. return 0;
  206. }
  207. MSH_CMD_EXPORT(wavrecord_sample, record voice to a wav file);
  208. #endif