audio_play.c 6.8 KB

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